From de97b7f5bbe07328a86aa34ee29862b1ae1ee2c9 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 28 Apr 2025 21:45:13 +0200 Subject: [PATCH 001/161] nr2.0: late: Correctly initialize funny_error member gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::Late): False initialize the funny_error field. --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 6ec04229c8e7..821c61d6cc52 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -33,7 +33,9 @@ namespace Rust { namespace Resolver2_0 { -Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {} +Late::Late (NameResolutionContext &ctx) + : DefaultResolver (ctx), funny_error (false) +{} static NodeId next_node_id () From 33769e4612c7c59b850d2b5f9d1e67a3ff12f127 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 16 Apr 2025 16:03:26 +0200 Subject: [PATCH 002/161] backend: Refactor struct pattern compilation gcc/rust/ChangeLog: * backend/rust-compile-pattern.h: Split struct pattern compilation into three functions. * backend/rust-compile-pattern.cc: Implement them. --- gcc/rust/backend/rust-compile-pattern.cc | 105 +++++++++++++---------- gcc/rust/backend/rust-compile-pattern.h | 9 ++ 2 files changed, 68 insertions(+), 46 deletions(-) diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index e83717b378bc..89575021f283 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -22,6 +22,8 @@ #include "rust-constexpr.h" #include "rust-compile-type.h" #include "print-tree.h" +#include "rust-hir-pattern.h" +#include "rust-system.h" namespace Rust { namespace Compile { @@ -504,6 +506,57 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) } } +void +CompilePatternBindings::handle_struct_pattern_ident ( + HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant, + int variant_index) +{ + HIR::StructPatternFieldIdent &ident + = static_cast (pat); + + size_t offs = 0; + auto ok = variant->lookup_field (ident.get_identifier ().as_string (), + nullptr, &offs); + rust_assert (ok); + + tree binding = error_mark_node; + if (adt->is_enum ()) + { + tree payload_accessor_union + = Backend::struct_field_expression (match_scrutinee_expr, 1, + ident.get_locus ()); + + tree variant_accessor + = Backend::struct_field_expression (payload_accessor_union, + variant_index, ident.get_locus ()); + + binding = Backend::struct_field_expression (variant_accessor, offs, + ident.get_locus ()); + } + else + { + tree variant_accessor = match_scrutinee_expr; + binding = Backend::struct_field_expression (variant_accessor, offs, + ident.get_locus ()); + } + + ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (), binding); +} + +void +CompilePatternBindings::handle_struct_pattern_ident_pat ( + HIR::StructPatternField &pat) +{ + rust_unreachable (); +} + +void +CompilePatternBindings::handle_struct_pattern_tuple_pat ( + HIR::StructPatternField &pat) +{ + rust_unreachable (); +} + void CompilePatternBindings::visit (HIR::StructPattern &pattern) { @@ -539,54 +592,14 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern) { switch (field->get_item_type ()) { - case HIR::StructPatternField::ItemType::TUPLE_PAT: { - // TODO - rust_unreachable (); - } + case HIR::StructPatternField::ItemType::TUPLE_PAT: + handle_struct_pattern_tuple_pat (*field); break; - - case HIR::StructPatternField::ItemType::IDENT_PAT: { - // TODO - rust_unreachable (); - } + case HIR::StructPatternField::ItemType::IDENT_PAT: + handle_struct_pattern_ident_pat (*field); break; - - case HIR::StructPatternField::ItemType::IDENT: { - HIR::StructPatternFieldIdent &ident - = static_cast (*field.get ()); - - size_t offs = 0; - ok = variant->lookup_field (ident.get_identifier ().as_string (), - nullptr, &offs); - rust_assert (ok); - - tree binding = error_mark_node; - if (adt->is_enum ()) - { - tree payload_accessor_union - = Backend::struct_field_expression (match_scrutinee_expr, 1, - ident.get_locus ()); - - tree variant_accessor - = Backend::struct_field_expression (payload_accessor_union, - variant_index, - ident.get_locus ()); - - binding - = Backend::struct_field_expression (variant_accessor, offs, - ident.get_locus ()); - } - else - { - tree variant_accessor = match_scrutinee_expr; - binding - = Backend::struct_field_expression (variant_accessor, offs, - ident.get_locus ()); - } - - ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (), - binding); - } + case HIR::StructPatternField::ItemType::IDENT: + handle_struct_pattern_ident (*field, adt, variant, variant_index); break; } } diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h index c7a62fcbc532..90bcb35ca5c3 100644 --- a/gcc/rust/backend/rust-compile-pattern.h +++ b/gcc/rust/backend/rust-compile-pattern.h @@ -17,7 +17,9 @@ // . #include "rust-compile-base.h" +#include "rust-hir-pattern.h" #include "rust-hir-visitor.h" +#include "rust-tyty.h" namespace Rust { namespace Compile { @@ -78,6 +80,13 @@ class CompilePatternBindings : public HIRCompileBase, pattern.accept_vis (compiler); } + void handle_struct_pattern_ident (HIR::StructPatternField &pat, + TyTy::ADTType *adt, + TyTy::VariantDef *variant, + int variant_index); + void handle_struct_pattern_ident_pat (HIR::StructPatternField &pat); + void handle_struct_pattern_tuple_pat (HIR::StructPatternField &pat); + void visit (HIR::StructPattern &pattern) override; void visit (HIR::TupleStructPattern &pattern) override; void visit (HIR::ReferencePattern &pattern) override; From e0686d79693a6e316f37f04099b11ecae8d67da0 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 16 Apr 2025 16:32:35 +0200 Subject: [PATCH 003/161] backend: Compile struct rebinding patterns Allow matching on a struct instance and rebinding its fields to new names: match X { Foo { field0: new_name0, field1: new_name1, } => { do_something(new_name0, new_name1); }, } This will enable us to finish derives for PartialEq and PartialOrd but isn't a complete implementation of these patterns yet. gcc/rust/ChangeLog: * backend/rust-compile-pattern.cc (CompilePatternBindings::make_struct_access): New function. (CompilePatternBindings::visit): Properly implement patterns mentioned above and call make_struct_accesss. * backend/rust-compile-pattern.h: New declaration. gcc/testsuite/ChangeLog: * rust/execute/torture/struct_pattern1.rs: New test. --- gcc/rust/backend/rust-compile-pattern.cc | 68 ++++++++++++++----- gcc/rust/backend/rust-compile-pattern.h | 8 ++- .../rust/execute/torture/struct_pattern1.rs | 19 ++++++ 3 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/rust/execute/torture/struct_pattern1.rs diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index 89575021f283..64b036109cfb 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -22,8 +22,11 @@ #include "rust-constexpr.h" #include "rust-compile-type.h" #include "print-tree.h" +#include "rust-diagnostics.h" +#include "rust-hir-pattern-abstract.h" #include "rust-hir-pattern.h" #include "rust-system.h" +#include "rust-tyty.h" namespace Rust { namespace Compile { @@ -506,20 +509,16 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) } } -void -CompilePatternBindings::handle_struct_pattern_ident ( - HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant, - int variant_index) +tree +CompilePatternBindings::make_struct_access (TyTy::ADTType *adt, + TyTy::VariantDef *variant, + Identifier &ident, + int variant_index) { - HIR::StructPatternFieldIdent &ident - = static_cast (pat); - size_t offs = 0; - auto ok = variant->lookup_field (ident.get_identifier ().as_string (), - nullptr, &offs); + auto ok = variant->lookup_field (ident.as_string (), nullptr, &offs); rust_assert (ok); - tree binding = error_mark_node; if (adt->is_enum ()) { tree payload_accessor_union @@ -530,24 +529,59 @@ CompilePatternBindings::handle_struct_pattern_ident ( = Backend::struct_field_expression (payload_accessor_union, variant_index, ident.get_locus ()); - binding = Backend::struct_field_expression (variant_accessor, offs, - ident.get_locus ()); + return Backend::struct_field_expression (variant_accessor, offs, + ident.get_locus ()); } else { tree variant_accessor = match_scrutinee_expr; - binding = Backend::struct_field_expression (variant_accessor, offs, - ident.get_locus ()); + + return Backend::struct_field_expression (variant_accessor, offs, + ident.get_locus ()); } +} + +void +CompilePatternBindings::handle_struct_pattern_ident ( + HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant, + int variant_index) +{ + HIR::StructPatternFieldIdent &ident + = static_cast (pat); + + auto identifier = ident.get_identifier (); + tree binding = make_struct_access (adt, variant, identifier, variant_index); ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (), binding); } void CompilePatternBindings::handle_struct_pattern_ident_pat ( - HIR::StructPatternField &pat) + HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant, + int variant_index) { - rust_unreachable (); + auto &pattern = static_cast (pat); + + switch (pattern.get_pattern ().get_pattern_type ()) + { + case HIR::Pattern::IDENTIFIER: { + auto &id + = static_cast (pattern.get_pattern ()); + + CompilePatternBindings::Compile (id, match_scrutinee_expr, ctx); + } + break; + default: + rust_sorry_at (pat.get_locus (), + "cannot handle non-identifier struct patterns"); + return; + } + + auto ident = pattern.get_identifier (); + tree binding = make_struct_access (adt, variant, ident, variant_index); + + ctx->insert_pattern_binding ( + pattern.get_pattern ().get_mappings ().get_hirid (), binding); } void @@ -596,7 +630,7 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern) handle_struct_pattern_tuple_pat (*field); break; case HIR::StructPatternField::ItemType::IDENT_PAT: - handle_struct_pattern_ident_pat (*field); + handle_struct_pattern_ident_pat (*field, adt, variant, variant_index); break; case HIR::StructPatternField::ItemType::IDENT: handle_struct_pattern_ident (*field, adt, variant, variant_index); diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h index 90bcb35ca5c3..511613d58256 100644 --- a/gcc/rust/backend/rust-compile-pattern.h +++ b/gcc/rust/backend/rust-compile-pattern.h @@ -80,11 +80,17 @@ class CompilePatternBindings : public HIRCompileBase, pattern.accept_vis (compiler); } + tree make_struct_access (TyTy::ADTType *adt, TyTy::VariantDef *variant, + Identifier &ident, int variant_index); + void handle_struct_pattern_ident (HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant, int variant_index); - void handle_struct_pattern_ident_pat (HIR::StructPatternField &pat); + void handle_struct_pattern_ident_pat (HIR::StructPatternField &pat, + TyTy::ADTType *adt, + TyTy::VariantDef *variant, + int variant_index); void handle_struct_pattern_tuple_pat (HIR::StructPatternField &pat); void visit (HIR::StructPattern &pattern) override; diff --git a/gcc/testsuite/rust/execute/torture/struct_pattern1.rs b/gcc/testsuite/rust/execute/torture/struct_pattern1.rs new file mode 100644 index 000000000000..7a74092ad50c --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/struct_pattern1.rs @@ -0,0 +1,19 @@ +struct A { + // the two warnings are invalid but this should be fixed by our lint rework + // with this year's GSoC so ok for now + a: i32, // { dg-warning "never read" } + b: i32, // { dg-warning "never read" } +} + +fn main() -> i32 { + let a = A { a: 15, b: 14 }; + + let result = match a { + A { + a: self_a, + b: self_b, + } => self_a + self_b, + }; + + result - 29 +} From edf965de970d34de3046817e73ebdb2886fa19aa Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 16 Apr 2025 17:37:31 +0200 Subject: [PATCH 004/161] ast: builder: Allow building struct ident patterns gcc/rust/ChangeLog: * ast/rust-ast-builder.cc (Builder::struct_pattern_ident_pattern): New. * ast/rust-ast-builder.h: New declaration. --- gcc/rust/ast/rust-ast-builder.cc | 8 ++++++++ gcc/rust/ast/rust-ast-builder.h | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 08c52b155c44..ef0f92f14ce0 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -442,6 +442,14 @@ Builder::field_access (std::unique_ptr &&instance, new FieldAccessExpr (std::move (instance), field, {}, loc)); } +std::unique_ptr +Builder::struct_pattern_ident_pattern (std::string field_name, + std::unique_ptr &&pattern) +{ + return std::make_unique ( + field_name, std::move (pattern), std::vector (), loc); +} + std::unique_ptr Builder::wildcard () const { diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index 41ce118e7714..a5115b685ace 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -254,6 +254,10 @@ class Builder std::unique_ptr field_access (std::unique_ptr &&instance, std::string field) const; + std::unique_ptr + struct_pattern_ident_pattern (std::string field_name, + std::unique_ptr &&pattern); + /* Create a wildcard pattern (`_`) */ std::unique_ptr wildcard () const; /* Create a reference pattern (`&pattern`) */ From ed8f4dbc124f20233d82fae611c5fa6260dcf80f Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 16 Apr 2025 17:38:27 +0200 Subject: [PATCH 005/161] derive(PartialEq): Allow deriving enum structs gcc/rust/ChangeLog: * expand/rust-derive-partial-eq.cc (DerivePartialEq::match_enum_tuple): Remove debug call. (DerivePartialEq::match_enum_struct): Add proper implementation. (DerivePartialEq::visit_enum): Call it. gcc/testsuite/ChangeLog: * rust/execute/torture/derive-partialeq2.rs: New test. --- gcc/rust/expand/rust-derive-partial-eq.cc | 66 +++++++++++++++---- .../rust/execute/torture/derive-partialeq2.rs | 66 +++++++++++++++++++ 2 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/rust/execute/torture/derive-partialeq2.rs diff --git a/gcc/rust/expand/rust-derive-partial-eq.cc b/gcc/rust/expand/rust-derive-partial-eq.cc index ff66faabc781..22368bcb2b01 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.cc +++ b/gcc/rust/expand/rust-derive-partial-eq.cc @@ -199,8 +199,6 @@ DerivePartialEq::match_enum_tuple (PathInExpression variant_path, auto self_pattern_str = "__self_" + std::to_string (i); auto other_pattern_str = "__other_" + std::to_string (i); - rust_debug ("]ARTHUR[ %s", self_pattern_str.c_str ()); - self_patterns.emplace_back ( builder.identifier_pattern (self_pattern_str)); other_patterns.emplace_back ( @@ -240,15 +238,55 @@ MatchCase DerivePartialEq::match_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant) { - // NOTE: We currently do not support compiling struct patterns where an - // identifier is assigned a new pattern, e.g. Bloop { f0: x } - // This is what we should be using to compile PartialEq for enum struct - // variants, as we need to be comparing the field of each instance meaning we - // need to give two different names to two different instances of the same - // field. We cannot just use the field's name like we do when deriving - // `Clone`. - - rust_unreachable (); + auto self_fields = std::vector> (); + auto other_fields = std::vector> (); + + auto self_other_exprs = std::vector (); + + for (auto &field : variant.get_struct_fields ()) + { + // The patterns we're creating for each field are `self_` and + // `other_` where `field` is the name of the field. It doesn't + // actually matter what we use, as long as it's ordered, unique, and that + // we can reuse it in the match case's return expression to check that + // they are equal. + + auto field_name = field.get_field_name ().as_string (); + + auto self_pattern_str = "__self_" + field_name; + auto other_pattern_str = "__other_" + field_name; + + self_fields.emplace_back (builder.struct_pattern_ident_pattern ( + field_name, builder.identifier_pattern (self_pattern_str))); + other_fields.emplace_back (builder.struct_pattern_ident_pattern ( + field_name, builder.identifier_pattern (other_pattern_str))); + + self_other_exprs.emplace_back (SelfOther{ + builder.identifier (self_pattern_str), + builder.identifier (other_pattern_str), + }); + } + + auto self_elts = StructPatternElements (std::move (self_fields)); + auto other_elts = StructPatternElements (std::move (other_fields)); + + auto self_pattern = std::unique_ptr ( + new ReferencePattern (std::unique_ptr (new StructPattern ( + variant_path, loc, std::move (self_elts))), + false, false, loc)); + auto other_pattern = std::unique_ptr ( + new ReferencePattern (std::unique_ptr (new StructPattern ( + variant_path, loc, std::move (other_elts))), + false, false, loc)); + + auto tuple_items = std::make_unique ( + vec (std::move (self_pattern), std::move (other_pattern))); + + auto pattern = std::make_unique (std::move (tuple_items), loc); + + auto expr = build_eq_expression (std::move (self_other_exprs)); + + return builder.match_case (std::move (pattern), std::move (expr)); } void @@ -275,9 +313,9 @@ DerivePartialEq::visit_enum (Enum &item) static_cast (*variant))); break; case EnumItem::Kind::Struct: - rust_sorry_at ( - item.get_locus (), - "cannot derive(PartialEq) for enum struct variants yet"); + cases.emplace_back ( + match_enum_struct (variant_path, + static_cast (*variant))); break; } } diff --git a/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs b/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs new file mode 100644 index 000000000000..15374d9f5bf0 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs @@ -0,0 +1,66 @@ +// { dg-output "true\r*\nfalse\r*\nfalse\r*\nfalse\r*\nfalse\r*\n" } + +#![feature(intrinsics)] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[lang = "structural_peq"] +trait StructuralPartialEq {} + +#[lang = "eq"] +pub trait PartialEq { + /// This method tests for `self` and `other` values to be equal, and is used + /// by `==`. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn eq(&self, other: &Rhs) -> bool; + + /// This method tests for `!=`. + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } +} + +#[derive(PartialEq)] +enum Foo { + A { a: i32, b: i32 }, + B(i32, i32), + C, +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(b: bool) { + if b { + unsafe { puts("true" as *const str as *const i8) } + } else { + unsafe { puts("false" as *const str as *const i8) } + } +} + +fn main() -> i32 { + let x = Foo::A { a: 15, b: 14 }; + + let b1 = x == Foo::A { a: 15, b: 14 }; + let b12 = x == Foo::A { a: 15, b: 19 }; + let b13 = x == Foo::A { a: 19, b: 14 }; + let b2 = x == Foo::B(15, 14); + let b3 = x == Foo::C; + + print(b1); + print(b12); + print(b13); + print(b2); + print(b3); + + 0 +} From 20ebc5ea0aefd95ad6d7168ae4eea8cfd49c9f2a Mon Sep 17 00:00:00 2001 From: CohenArthur Date: Thu, 24 Apr 2025 18:41:11 +0200 Subject: [PATCH 006/161] derive(PartialEq): Fix raw strings in test gcc/testsuite/ChangeLog: * rust/execute/torture/derive-partialeq2.rs: Add missing terminating nul char. Co-authored-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/execute/torture/derive-partialeq2.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs b/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs index 15374d9f5bf0..70ed7dcd93d9 100644 --- a/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs +++ b/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs @@ -41,9 +41,9 @@ extern "C" { fn print(b: bool) { if b { - unsafe { puts("true" as *const str as *const i8) } + unsafe { puts("true\0" as *const str as *const i8) } } else { - unsafe { puts("false" as *const str as *const i8) } + unsafe { puts("false\0" as *const str as *const i8) } } } From 8f959d5580d8eb429c490bae1458c08af14c6cc3 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 5 May 2025 21:07:20 +0100 Subject: [PATCH 007/161] gccrs: Emit error diagnostic for bad impl type usage Rust only allows impl traits to be used in the return position of functions. Fixes Rust-GCC#1485 gcc/rust/ChangeLog: * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): allow impl type * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): likewise * hir/rust-ast-lower-type.cc (ASTLoweringType::ASTLoweringType): new flag for impl trait (ASTLoweringType::translate): pass flag (ASTLoweringType::visit): track impl trait tag (ASTLoweringType::emit_impl_trait_error): new diagnostic * hir/rust-ast-lower-type.h: add new field gcc/testsuite/ChangeLog: * rust/compile/impl_trait_diag.rs: New test. * rust/compile/issue-1485.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/hir/rust-ast-lower-implitem.cc | 3 +- gcc/rust/hir/rust-ast-lower-item.cc | 3 +- gcc/rust/hir/rust-ast-lower-type.cc | 57 ++++++++++++++----- gcc/rust/hir/rust-ast-lower-type.h | 13 ++--- gcc/testsuite/rust/compile/impl_trait_diag.rs | 17 ++++++ gcc/testsuite/rust/compile/issue-1485.rs | 16 ++++++ 6 files changed, 85 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/rust/compile/impl_trait_diag.rs create mode 100644 gcc/testsuite/rust/compile/issue-1485.rs diff --git a/gcc/rust/hir/rust-ast-lower-implitem.cc b/gcc/rust/hir/rust-ast-lower-implitem.cc index d815a71564ec..fc9fe1ace4a9 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.cc +++ b/gcc/rust/hir/rust-ast-lower-implitem.cc @@ -138,7 +138,8 @@ ASTLowerImplItem::visit (AST::Function &function) std::unique_ptr return_type = function.has_return_type () ? std::unique_ptr ( - ASTLoweringType::translate (function.get_return_type ())) + ASTLoweringType::translate (function.get_return_type (), false, + true /* impl trait is allowed here*/)) : nullptr; Defaultness defaultness diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc index f4396b58e595..1810d16d515d 100644 --- a/gcc/rust/hir/rust-ast-lower-item.cc +++ b/gcc/rust/hir/rust-ast-lower-item.cc @@ -411,7 +411,8 @@ ASTLoweringItem::visit (AST::Function &function) std::unique_ptr return_type = function.has_return_type () ? std::unique_ptr ( - ASTLoweringType::translate (function.get_return_type ())) + ASTLoweringType::translate (function.get_return_type (), false, + true /* impl trait is allowed here*/)) : nullptr; std::vector function_params; diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc index a678f189ac28..5aedb9196dc5 100644 --- a/gcc/rust/hir/rust-ast-lower-type.cc +++ b/gcc/rust/hir/rust-ast-lower-type.cc @@ -209,10 +209,17 @@ ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path) path.get_locus ()); } +ASTLoweringType::ASTLoweringType (bool default_to_static_lifetime, + bool impl_trait_allowed) + : ASTLoweringBase (), default_to_static_lifetime (default_to_static_lifetime), + impl_trait_allowed (impl_trait_allowed), translated (nullptr) +{} + HIR::Type * -ASTLoweringType::translate (AST::Type &type, bool default_to_static_lifetime) +ASTLoweringType::translate (AST::Type &type, bool default_to_static_lifetime, + bool impl_trait_allowed) { - ASTLoweringType resolver (default_to_static_lifetime); + ASTLoweringType resolver (default_to_static_lifetime, impl_trait_allowed); type.accept_vis (resolver); rust_assert (resolver.translated != nullptr); @@ -260,7 +267,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype) HIR::Type *param_type = ASTLoweringType::translate (param.get_type (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); HIR::MaybeNamedParam p (param.get_name (), kind, std::unique_ptr (param_type), @@ -272,7 +280,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype) if (fntype.has_return_type ()) { return_type = ASTLoweringType::translate (fntype.get_return_type (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); } auto crate_num = mappings.get_current_crate (); @@ -292,8 +301,8 @@ ASTLoweringType::visit (AST::TupleType &tuple) std::vector> elems; for (auto &e : tuple.get_elems ()) { - HIR::Type *t - = ASTLoweringType::translate (*e, default_to_static_lifetime); + HIR::Type *t = ASTLoweringType::translate (*e, default_to_static_lifetime, + impl_trait_allowed); elems.push_back (std::unique_ptr (t)); } @@ -323,7 +332,8 @@ ASTLoweringType::visit (AST::ArrayType &type) { HIR::Type *translated_type = ASTLoweringType::translate (type.get_elem_type (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); HIR::Expr *array_size = ASTLoweringExpr::translate (type.get_size_expr ()); auto crate_num = mappings.get_current_crate (); @@ -343,9 +353,9 @@ ASTLoweringType::visit (AST::ReferenceType &type) HIR::Lifetime lifetime = lower_lifetime (type.get_lifetime (), default_to_static_lifetime); - HIR::Type *base_type - = ASTLoweringType::translate (type.get_base_type (), - default_to_static_lifetime); + HIR::Type *base_type = ASTLoweringType::translate (type.get_base_type (), + default_to_static_lifetime, + impl_trait_allowed); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -364,7 +374,8 @@ ASTLoweringType::visit (AST::RawPointerType &type) { HIR::Type *base_type = ASTLoweringType::translate (type.get_type_pointed_to (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -384,9 +395,9 @@ ASTLoweringType::visit (AST::RawPointerType &type) void ASTLoweringType::visit (AST::SliceType &type) { - HIR::Type *base_type - = ASTLoweringType::translate (type.get_elem_type (), - default_to_static_lifetime); + HIR::Type *base_type = ASTLoweringType::translate (type.get_elem_type (), + default_to_static_lifetime, + impl_trait_allowed); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -463,7 +474,8 @@ void ASTLoweringType::visit (AST::ParenthesisedType &type) { auto *inner = ASTLoweringType::translate (*type.get_type_in_parens (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -480,6 +492,9 @@ ASTLoweringType::visit (AST::ParenthesisedType &type) void ASTLoweringType::visit (AST::ImplTraitType &type) { + if (!impl_trait_allowed) + emit_impl_trait_error (type.get_locus ()); + std::vector> bounds; for (auto &bound : type.get_type_param_bounds ()) { @@ -499,6 +514,9 @@ ASTLoweringType::visit (AST::ImplTraitType &type) void ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type) { + if (!impl_trait_allowed) + emit_impl_trait_error (type.get_locus ()); + std::vector> bounds; auto b = ASTLoweringTypeBounds::translate (type.get_trait_bound ()); @@ -513,6 +531,15 @@ ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type) = new HIR::ImplTraitType (mapping, std::move (bounds), type.get_locus ()); } +void +ASTLoweringType::emit_impl_trait_error (location_t locus) +{ + rich_location r (line_table, locus); + rust_error_at (r, ErrorCode::E0562, + "% not allowed outside of function and inherent " + "method return types"); +} + HIR::GenericParam * ASTLowerGenericParam::translate (AST::GenericParam ¶m) { diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 4efaeee13149..50f543a357cf 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -66,7 +66,8 @@ class ASTLoweringType : public ASTLoweringBase public: static HIR::Type *translate (AST::Type &type, - bool default_to_static_lifetime = false); + bool default_to_static_lifetime = false, + bool impl_trait_allowed = false); void visit (AST::BareFunctionType &fntype) override; void visit (AST::TupleType &tuple) override; @@ -81,19 +82,17 @@ class ASTLoweringType : public ASTLoweringBase void visit (AST::TraitObjectTypeOneBound &type) override; void visit (AST::TraitObjectType &type) override; void visit (AST::ParenthesisedType &type) override; - void visit (AST::ImplTraitType &type) override; void visit (AST::ImplTraitTypeOneBound &type) override; + void emit_impl_trait_error (location_t locus); + private: - ASTLoweringType (bool default_to_static_lifetime) - : ASTLoweringBase (), - default_to_static_lifetime (default_to_static_lifetime), - translated (nullptr) - {} + ASTLoweringType (bool default_to_static_lifetime, bool impl_trait_allowed); /** Used when compiling const and static items. */ bool default_to_static_lifetime; + bool impl_trait_allowed; HIR::Type *translated; }; diff --git a/gcc/testsuite/rust/compile/impl_trait_diag.rs b/gcc/testsuite/rust/compile/impl_trait_diag.rs new file mode 100644 index 000000000000..54a0cd220a39 --- /dev/null +++ b/gcc/testsuite/rust/compile/impl_trait_diag.rs @@ -0,0 +1,17 @@ +#[lang = "sized"] +pub trait Sized {} + +trait Foo { + fn method(&self); +} + +struct Bar; +impl Foo for Bar {} + +fn main() { + let x: impl Foo = Bar; // { dg-error ".impl Trait. not allowed outside of function and inherent method return types .E0562." } + + struct Wrapper { + field: impl Foo, // { dg-error ".impl Trait. not allowed outside of function and inherent method return types .E0562." } + } +} diff --git a/gcc/testsuite/rust/compile/issue-1485.rs b/gcc/testsuite/rust/compile/issue-1485.rs new file mode 100644 index 000000000000..a0cd5a0f1f92 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-1485.rs @@ -0,0 +1,16 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +struct BinOpInvalid { + lhs: i32, + rhs: i32, + f: impl FnOnce(i32) -> i32, // { dg-error ".impl Trait. not allowed outside of function and inherent method return types .E0562." } +} From 3e203b5d8b2896a917be1b46561315a315ee1a1f Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 30 Apr 2025 14:37:49 +0100 Subject: [PATCH 008/161] gccrs: desugar APIT impl traits Argument position impl traits are simply syntatic sugar for generics. This adds a new desugar pass to do this. So for example: fn foo(a: impl Value, b: impl Value) -> i32 Is desugared into: fn foo (a: T, b: U) -> i32 So it just works like any normal generic function. There are more complex cases such as: fn foo(_value: impl Bar) -> i32 Which has a generic argument binding which needs to be turned into a where constraint: fn foo(_value: T) -> i32 where T: Bar, U: Foo, Fixes Rust-GCC#2015 Fixes Rust-GCC#1487 Fixes Rust-GCC#3454 Fixes Rust-GCC#1482 gcc/rust/ChangeLog: * Make-lang.in: new desugar file * ast/rust-ast.cc (ImplTraitTypeOneBound::as_string): its a unique_ptr now (FormatArgs::set_outer_attrs): reformat * ast/rust-path.h: remove has_generic_args assertion (can be empty because of desugar) * ast/rust-type.h (class ImplTraitTypeOneBound): add copy ctor and use unique_ptr * hir/rust-ast-lower-type.cc (ASTLoweringType::visit): update to use unique_ptr * parse/rust-parse-impl.h (Parser::parse_type): reuse the existing unique_ptr instead (Parser::parse_type_no_bounds): likewise (Parser::parse_pattern): likewise * resolve/rust-ast-resolve-type.cc (ResolveType::visit): its a unique_ptr now * rust-session-manager.cc (Session::compile_crate): call desugar * ast/rust-desugar-apit.cc: New file. * ast/rust-desugar-apit.h: New file. gcc/testsuite/ChangeLog: * rust/compile/issue-2015.rs: fully supported now * rust/compile/nr2/exclude: nr2 cant handle some of these * rust/compile/issue-1487.rs: New test. * rust/compile/issue-3454.rs: New test. * rust/execute/torture/impl_desugar-2.rs: New test. * rust/execute/torture/impl_desugar.rs: New test. * rust/execute/torture/impl_trait1.rs: New test. * rust/execute/torture/impl_trait2.rs: New test. * rust/execute/torture/impl_trait3.rs: New test. * rust/execute/torture/impl_trait4.rs: New test. * rust/execute/torture/issue-1482.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/Make-lang.in | 1 + gcc/rust/ast/rust-ast.cc | 2 +- gcc/rust/ast/rust-desugar-apit.cc | 516 ++++++++++++++++++ gcc/rust/ast/rust-desugar-apit.h | 42 ++ gcc/rust/ast/rust-path.h | 6 +- gcc/rust/ast/rust-type.h | 47 +- gcc/rust/hir/rust-ast-lower-type.cc | 2 +- gcc/rust/parse/rust-parse-impl.h | 13 +- gcc/rust/resolve/rust-ast-resolve-type.cc | 2 +- gcc/rust/rust-session-manager.cc | 2 + gcc/testsuite/rust/compile/issue-1487.rs | 15 + gcc/testsuite/rust/compile/issue-2015.rs | 3 +- gcc/testsuite/rust/compile/issue-3454.rs | 20 + gcc/testsuite/rust/compile/nr2/exclude | 3 + .../rust/execute/torture/impl_desugar-2.rs | 32 ++ .../rust/execute/torture/impl_desugar.rs | 32 ++ .../rust/execute/torture/impl_trait1.rs | 31 ++ .../rust/execute/torture/impl_trait2.rs | 31 ++ .../rust/execute/torture/impl_trait3.rs | 46 ++ .../rust/execute/torture/impl_trait4.rs | 31 ++ .../rust/execute/torture/issue-1482.rs | 23 + 21 files changed, 866 insertions(+), 34 deletions(-) create mode 100644 gcc/rust/ast/rust-desugar-apit.cc create mode 100644 gcc/rust/ast/rust-desugar-apit.h create mode 100644 gcc/testsuite/rust/compile/issue-1487.rs create mode 100644 gcc/testsuite/rust/compile/issue-3454.rs create mode 100644 gcc/testsuite/rust/execute/torture/impl_desugar-2.rs create mode 100644 gcc/testsuite/rust/execute/torture/impl_desugar.rs create mode 100644 gcc/testsuite/rust/execute/torture/impl_trait1.rs create mode 100644 gcc/testsuite/rust/execute/torture/impl_trait2.rs create mode 100644 gcc/testsuite/rust/execute/torture/impl_trait3.rs create mode 100644 gcc/testsuite/rust/execute/torture/impl_trait4.rs create mode 100644 gcc/testsuite/rust/execute/torture/issue-1482.rs diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 835e113aee2c..94d3365d929e 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -242,6 +242,7 @@ GRS_OBJS = \ rust/rust-collect-lang-items.o \ rust/rust-desugar-for-loops.o \ rust/rust-desugar-question-mark.o \ + rust/rust-desugar-apit.o \ $(END) # removed object files from here diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 4e82be420fe1..d921353bf6ab 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -2714,7 +2714,7 @@ ImplTraitTypeOneBound::as_string () const { std::string str ("ImplTraitTypeOneBound: \n TraitBound: "); - return str + trait_bound.as_string (); + return str + trait_bound->as_string (); } std::string diff --git a/gcc/rust/ast/rust-desugar-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc new file mode 100644 index 000000000000..2f31bcfe7a32 --- /dev/null +++ b/gcc/rust/ast/rust-desugar-apit.cc @@ -0,0 +1,516 @@ +// Copyright (C) 2025 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 +// . + +#include "rust-desugar-apit.h" +#include "rust-ast.h" +#include "rust-type.h" + +namespace Rust { +namespace AST { + +class DesugarApitType : public DefaultASTVisitor +{ + using DefaultASTVisitor::visit; + +public: + static std::pair>> + Desugar (AST::Type &type) + { + DesugarApitType visitor (&type); + type.accept_vis (visitor); + rust_assert (visitor.translated != nullptr); + return std::make_pair (visitor.translated, + std::move (visitor.implicit_generic_params)); + } + + // Generate a unique impl trait parameter name + static Identifier get_impl_name () + { + static size_t counter = 0; + return Identifier ("Impl_" + std::to_string (counter++)); + } + + // these can hold other types + void visit (AST::TupleType &tuple) override + { + for (auto &elem : tuple.get_elems ()) + { + auto &type = *elem.get (); + auto desugar = Desugar (type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + continue; + + if (tt != elem.get ()) + elem = std::unique_ptr (tt); + + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + } + + void visit (AST::ArrayType &type) override + { + auto &element_type = type.get_element_type (); + auto desugar = Desugar (*element_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (tt != element_type.get ()) + element_type = std::unique_ptr (tt); + + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::ReferenceType &type) override + { + // Get a reference to the current type for in-place modification + auto &referenced_type = type.get_type_referenced (); + auto desugar = Desugar (referenced_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + // Update the reference type's contents rather than creating a new one + if (&referenced_type != tt) + { + std::unique_ptr new_type_no_bounds ( + static_cast (tt)); + type.get_type_ptr () = std::move (new_type_no_bounds); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::RawPointerType &type) override + { + auto &pointed_type = type.get_type_pointed_to (); + auto desugar = Desugar (pointed_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + // Update the pointer's inner type directly using the new accessor + if (&pointed_type != tt) + { + std::unique_ptr new_type_no_bounds ( + static_cast (tt)); + type.get_type_ptr () = std::move (new_type_no_bounds); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::SliceType &type) override + { + auto &element_type = type.get_elem_type (); + auto desugar = Desugar (element_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (&element_type != tt) + { + std::unique_ptr new_elem_type (tt); + type.get_elem_type_ptr () = std::move (new_elem_type); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::ParenthesisedType &type) override + { + auto &inner_type_ptr = type.get_type_in_parens (); + auto desugar = Desugar (*inner_type_ptr); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (inner_type_ptr.get () != tt) + { + std::unique_ptr new_inner_type (tt); + inner_type_ptr = std::move (new_inner_type); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + // this is where the desugar happens + void visit (AST::ImplTraitType &type) override + { + // Generate a unique name using the static method + auto ident = get_impl_name (); + + // Create a type path for the new generic parameter + // Create a SimplePathSegment with the identifier string + auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ()); + // Create a vector of SimplePathSegments for SimplePath constructor + std::vector simple_segs = {simple_seg}; + // Create a SimplePath + auto simple_path = SimplePath (simple_segs, false, type.get_locus ()); + + // Convert to TypePath by creating path segments + std::vector> segments; + segments.push_back (std::unique_ptr (new TypePathSegment ( + PathIdentSegment (ident.as_string (), type.get_locus ()), false, + type.get_locus ()))); + + // Create TypePath from segments + auto type_path + = new TypePath (std::move (segments), type.get_locus (), false); + + // Convert bounds from impl trait to generic parameter bounds + std::vector> bounds; + for (auto &bound : type.get_type_param_bounds ()) + bounds.push_back (bound->clone_type_param_bound ()); + + // Create the new generic parameter + auto generic_param = std::unique_ptr ( + new TypeParam (ident, type.get_locus (), std::move (bounds))); + + // Store the generic parameter to be added to the function signature + implicit_generic_params.push_back (std::move (generic_param)); + + // Replace impl trait with the new type parameter + translated = type_path; + } + + void visit (AST::ImplTraitTypeOneBound &type) override + { + // Generate a unique name using the static method + auto ident = get_impl_name (); + + // Create a type path for the new generic parameter + // Create a SimplePathSegment with the identifier string + auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ()); + // Create a vector of SimplePathSegments for SimplePath constructor + std::vector simple_segs = {simple_seg}; + // Create a SimplePath + auto simple_path = SimplePath (simple_segs, false, type.get_locus ()); + + // Convert to TypePath by creating path segments + std::vector> segments; + segments.push_back (std::unique_ptr (new TypePathSegment ( + PathIdentSegment (ident.as_string (), type.get_locus ()), false, + type.get_locus ()))); + + // Create TypePath from segments + auto type_path + = new TypePath (std::move (segments), type.get_locus (), false); + + // Convert the bound to a generic parameter bound + std::vector> bounds; + bounds.push_back (std::move (type.get_trait_bound ())); + + // Create the new generic parameter + auto generic_param = std::unique_ptr ( + new TypeParam (ident, type.get_locus (), std::move (bounds))); + + // Store the generic parameter to be added to the function signature + implicit_generic_params.push_back (std::move (generic_param)); + + // Replace impl trait with the new type parameter + translated = type_path; + } + +private: + DesugarApitType (AST::Type *base) + : translated (base), implicit_generic_params () + {} + + AST::Type *translated; + std::vector> implicit_generic_params; +}; + +// --------- + +class ApitBoundProcessor +{ +public: + ApitBoundProcessor ( + WhereClause &where_clause, + std::vector> &generic_params) + : where_clause (where_clause), generic_params (generic_params) + {} + + void go (std::vector> &implicit_generics) + { + // some desugars are more complex so imagine this case + // + // pub fn foo(_value: impl Bar) -> i32 { + // 15 + // } + // + // this needs to become: + // + // pub fn foo(_value: T) -> i32 + // where + // T: Bar, + // U: Foo, + // { + // 15 + // } + // + // so we need to walk all the implicit generics and the trait bounds paths + // for more generics + + for (auto &implicit_generic : implicit_generics) + { + switch (implicit_generic->get_kind ()) + { + case GenericParam::Kind::Type: { + TypeParam &p + = *static_cast (implicit_generic.get ()); + + process_type_param (p); + generic_params.push_back (std::move (implicit_generic)); + for (auto &synth : synthetic_params) + generic_params.push_back (std::move (synth)); + synthetic_params.clear (); + } + break; + + default: + generic_params.push_back (std::move (implicit_generic)); + break; + } + } + } + +private: + void process_type_param (TypeParam &p) + { + auto &bounds = p.get_type_param_bounds (); + std::vector bounds_to_remove; + for (size_t i = 0; i < bounds.size (); i++) + { + auto &tb = bounds[i]; + switch (tb->get_bound_type ()) + { + case TypeParamBound::TypeParamBoundType::TRAIT: { + TraitBound &ttb = *static_cast (tb.get ()); + TypePath &path = ttb.get_type_path (); + bool deusgared = process_type_path (p, ttb, path); + if (deusgared) + bounds_to_remove.push_back (i); + } + + default: + break; + } + } + for (auto it = bounds_to_remove.rbegin (); it != bounds_to_remove.rend (); + ++it) + bounds.erase (bounds.begin () + *it); + } + + bool process_type_path (TypeParam &p, TraitBound &parent, TypePath &path) + { + bool desugared = false; + for (auto &segment : path.get_segments ()) + { + switch (segment->get_type ()) + { + case TypePathSegment::SegmentType::GENERIC: { + TypePathSegmentGeneric &seg + = *static_cast (segment.get ()); + desugared |= process_generic_segment (p, parent, path, seg); + } + + default: + break; + } + } + return desugared; + } + + bool process_generic_segment (TypeParam &p, TraitBound &parent, + TypePath &path, TypePathSegmentGeneric &seg) + { + // we need to look for any impl types as default arguments in any generics + // and remove this index from the generic arguments by using a where + // constraint instead + + std::vector> new_clauses; + GenericArgs &generic_args = seg.get_generic_args (); + std::vector> + bindings_desugared; + std::vector &bindings + = generic_args.get_binding_args (); + + for (auto &generic : bindings) + { + auto &t = generic.get_type (); + auto translated = DesugarApitType::Desugar (t); + auto tt = translated.first; + + auto &implicit_generics = translated.second; + if (implicit_generics.empty ()) + continue; + + if (tt != &t) + { + bindings_desugared.push_back (generic); + generic.get_type_ptr () = std::unique_ptr (tt); + } + + for (auto &implicit_generic : implicit_generics) + { + switch (implicit_generic->get_kind ()) + { + case GenericParam::Kind::Type: { + TypeParam &tp + = *static_cast (implicit_generic.get ()); + + std::vector> + type_param_bounds; + for (auto &b : tp.get_type_param_bounds ()) + type_param_bounds.push_back (std::move (b)); + tp.get_type_param_bounds ().clear (); + + // add synthetic parameter for this + synthetic_params.push_back (std::move (implicit_generic)); + + auto bound_type_path + = get_type_for_identifier (tp.get_type_representation ()); + + auto clause = new TypeBoundWhereClauseItem ( + {}, std::move (bound_type_path), + std::move (type_param_bounds), tp.get_locus ()); + std::unique_ptr clause_item + = std::unique_ptr (clause); + new_clauses.push_back (std::move (clause_item)); + } + break; + + default: + synthetic_params.push_back (std::move (implicit_generic)); + break; + } + } + } + + std::vector> type_param_bounds; + auto bound = std::unique_ptr (new TraitBound (parent)); + type_param_bounds.push_back (std::move (bound)); + auto parent_type_path + = get_type_for_identifier (p.get_type_representation ()); + auto clause + = new TypeBoundWhereClauseItem ({}, std::move (parent_type_path), + std::move (type_param_bounds), + parent.get_locus ()); + std::unique_ptr clause_item + = std::unique_ptr (clause); + where_clause.get_items ().push_back (std::move (clause_item)); + + for (auto &where_item : new_clauses) + where_clause.get_items ().push_back (std::move (where_item)); + + return !bindings_desugared.empty (); + } + + static std::unique_ptr get_type_for_identifier (const Identifier &ident) + { + auto simple_seg + = SimplePathSegment (ident.as_string (), ident.get_locus ()); + std::vector simple_segs = {simple_seg}; + auto simple_path = SimplePath (simple_segs, false, ident.get_locus ()); + std::vector> segments; + segments.push_back (std::unique_ptr (new TypePathSegment ( + PathIdentSegment (ident.as_string (), ident.get_locus ()), false, + ident.get_locus ()))); + auto type_path = new TypePath (std::move (segments), ident.get_locus ()); + return std::unique_ptr (type_path); + } + +private: + WhereClause &where_clause; + std::vector> &generic_params; + + // mutates + std::vector> synthetic_params; +}; + +// --------- + +DesugarApit::DesugarApit () {} + +void +DesugarApit::go (AST::Crate &crate) +{ + DefaultASTVisitor::visit (crate); +} + +void +DesugarApit::visit (AST::Function &function) +{ + if (!function.has_function_params ()) + return; + + auto &fn_params = function.get_function_params (); + for (auto ¶m : fn_params) + { + if (param->is_variadic () || param->is_self ()) + continue; + + auto *p = param.get (); + auto &fp = *static_cast (p); + auto &type = fp.get_type (); + + auto translated = DesugarApitType::Desugar (type); + auto tt = translated.first; + + auto &implicit_generics = translated.second; + if (implicit_generics.empty ()) + continue; + + if (fp.get_type_ptr ().get () != tt) + { + fp.get_type_ptr () = std::unique_ptr (tt); + } + + ApitBoundProcessor processor (function.get_where_clause (), + function.get_generic_params ()); + processor.go (implicit_generics); + } +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-desugar-apit.h b/gcc/rust/ast/rust-desugar-apit.h new file mode 100644 index 000000000000..07c25e2405cf --- /dev/null +++ b/gcc/rust/ast/rust-desugar-apit.h @@ -0,0 +1,42 @@ +// Copyright (C) 2025 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 +// . + +#ifndef RUST_DESUGAR_APIT_H +#define RUST_DESUGAR_APIT_H + +#include "rust-ast-visitor.h" + +namespace Rust { +namespace AST { + +class DesugarApit : public DefaultASTVisitor +{ + using DefaultASTVisitor::visit; + +public: + DesugarApit (); + void go (AST::Crate &); + +private: + void visit (AST::Function &) override; +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DESUGAR_APIT_H diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index a4ba93b718e7..73e2f83104b3 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -968,11 +968,7 @@ class TypePathSegmentGeneric : public TypePathSegment void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_pattern" better? - GenericArgs &get_generic_args () - { - rust_assert (has_generic_args ()); - return generic_args; - } + GenericArgs &get_generic_args () { return generic_args; } // Use covariance to override base class method TypePathSegmentGeneric *clone_type_path_segment_impl () const override diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 1bb521d85850..6c0652a013f9 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -73,6 +73,13 @@ class TraitBound : public TypeParamBound type_path (std::move (type_path)), locus (locus) {} + TraitBound (TraitBound const &other) + : TypeParamBound (other.get_node_id ()), in_parens (other.in_parens), + opening_question_mark (other.opening_question_mark), + for_lifetimes (other.for_lifetimes), type_path (other.type_path), + locus (other.locus) + {} + std::string as_string () const override; location_t get_locus () const override final { return locus; } @@ -305,33 +312,31 @@ class ParenthesisedType : public TypeNoBounds // Impl trait with a single bound? Poor reference material here. class ImplTraitTypeOneBound : public TypeNoBounds { - TraitBound trait_bound; + std::unique_ptr trait_bound; location_t locus; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override - { - return new ImplTraitTypeOneBound (*this); - } - public: - ImplTraitTypeOneBound (TraitBound trait_bound, location_t locus) + ImplTraitTypeOneBound (std::unique_ptr trait_bound, + location_t locus) : trait_bound (std::move (trait_bound)), locus (locus) {} + ImplTraitTypeOneBound (ImplTraitTypeOneBound const &other) + : trait_bound (other.trait_bound->clone_type_param_bound ()), + locus (other.locus) + {} + std::string as_string () const override; location_t get_locus () const override final { return locus; } void accept_vis (ASTVisitor &vis) override; - // TODO: would a "vis_type" be better? - TraitBound &get_trait_bound () + std::unique_ptr &get_trait_bound () { return trait_bound; } + + TypeNoBounds *clone_type_no_bounds_impl () const override { - // TODO: check to ensure invariants are met? - return trait_bound; + return new ImplTraitTypeOneBound (*this); } }; @@ -529,6 +534,9 @@ class RawPointerType : public TypeNoBounds return *type; } + // Getter for direct access to the type unique_ptr + std::unique_ptr &get_type_ptr () { return type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -604,6 +612,9 @@ class ReferenceType : public TypeNoBounds TypeNoBounds &get_base_type () { return *type; } + // Getter for direct access to the type unique_ptr + std::unique_ptr &get_type_ptr () { return type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -666,6 +677,11 @@ class ArrayType : public TypeNoBounds return *size; } + std::unique_ptr &get_element_type () { return elem_type; } + + // Additional getter for direct access to the size expr unique_ptr + std::unique_ptr &get_size_ptr () { return size; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -719,6 +735,9 @@ class SliceType : public TypeNoBounds return *elem_type; } + // Getter for direct access to the elem_type unique_ptr + std::unique_ptr &get_elem_type_ptr () { return elem_type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc index 5aedb9196dc5..4e44b1b9ce37 100644 --- a/gcc/rust/hir/rust-ast-lower-type.cc +++ b/gcc/rust/hir/rust-ast-lower-type.cc @@ -519,7 +519,7 @@ ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type) std::vector> bounds; - auto b = ASTLoweringTypeBounds::translate (type.get_trait_bound ()); + auto b = ASTLoweringTypeBounds::translate (*type.get_trait_bound ().get ()); bounds.push_back (std::unique_ptr (b)); auto crate_num = mappings.get_current_crate (); diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 9dda231ba8fa..a0af8a3ac19b 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -9117,14 +9117,8 @@ Parser::parse_type (bool save_errors) t = lexer.peek_token (); if (t->get_id () != PLUS) { - // convert trait bound to value object - AST::TraitBound value_bound (*initial_bound); - - // DEBUG: removed as unique ptr, so should auto-delete - // delete initial_bound; - return std::unique_ptr ( - new AST::ImplTraitTypeOneBound (std::move (value_bound), + new AST::ImplTraitTypeOneBound (std::move (initial_bound), locus)); } @@ -9955,11 +9949,8 @@ Parser::parse_type_no_bounds () return nullptr; } - // convert trait bound to value object - AST::TraitBound value_bound (*initial_bound); - return std::unique_ptr ( - new AST::ImplTraitTypeOneBound (std::move (value_bound), locus)); + new AST::ImplTraitTypeOneBound (std::move (initial_bound), locus)); } case DYN: case QUESTION_MARK: { diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc index 8fd69c3ead6a..891fcf5d9f1d 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ b/gcc/rust/resolve/rust-ast-resolve-type.cc @@ -140,7 +140,7 @@ ResolveType::visit (AST::ImplTraitType &type) void ResolveType::visit (AST::ImplTraitTypeOneBound &type) { - ResolveTypeBound::go (type.get_trait_bound ()); + ResolveTypeBound::go (*type.get_trait_bound ().get ()); } // resolve relative type-paths diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 48acbf342222..09f7e2ee4efb 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -20,6 +20,7 @@ #include "rust-collect-lang-items.h" #include "rust-desugar-for-loops.h" #include "rust-desugar-question-mark.h" +#include "rust-desugar-apit.h" #include "rust-diagnostics.h" #include "rust-hir-pattern-analysis.h" #include "rust-immutable-name-resolution-context.h" @@ -619,6 +620,7 @@ Session::compile_crate (const char *filename) AST::DesugarForLoops ().go (parsed_crate); AST::DesugarQuestionMark ().go (parsed_crate); + AST::DesugarApit ().go (parsed_crate); rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m"); if (options.dump_option_enabled (CompileOptions::EXPANSION_DUMP)) diff --git a/gcc/testsuite/rust/compile/issue-1487.rs b/gcc/testsuite/rust/compile/issue-1487.rs new file mode 100644 index 000000000000..4a4d759ef2e9 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-1487.rs @@ -0,0 +1,15 @@ +// { dg-options "-w" } +#[lang = "sized"] +trait Sized {} + +trait Printable { + fn print(&self); +} + +struct Foo; + +impl Printable for Foo { + fn print(&self) {} +} + +fn take_printable(_: impl Printable) {} diff --git a/gcc/testsuite/rust/compile/issue-2015.rs b/gcc/testsuite/rust/compile/issue-2015.rs index 7789ecda3763..7e0365163e5a 100644 --- a/gcc/testsuite/rust/compile/issue-2015.rs +++ b/gcc/testsuite/rust/compile/issue-2015.rs @@ -1,4 +1,5 @@ -// { dg-additional-options "-frust-compile-until=lowering" } +#[lang = "sized"] +trait Sized {} macro_rules! impl_foo { () => { impl Foo } diff --git a/gcc/testsuite/rust/compile/issue-3454.rs b/gcc/testsuite/rust/compile/issue-3454.rs new file mode 100644 index 000000000000..2a3c0c714606 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3454.rs @@ -0,0 +1,20 @@ +#[lang = "sized"] +pub trait Sized {} + +macro_rules! impl_foo { + () => { impl Foo } +} + +pub trait Foo {} + +pub trait Bar { + type Baz; +} + +pub fn foo(_value: impl Bar) -> i32 { + 15 +} + +pub fn bar(_value: impl Bar) -> i32 { + 16 +} diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index c020e36fba4a..d3bdb1cce0df 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -14,4 +14,7 @@ issue-3663.rs issue-3671.rs issue-3652.rs issue-3649.rs +issue-1487.rs +issue-2015.rs +issue-3454.rs # please don't delete the trailing newline diff --git a/gcc/testsuite/rust/execute/torture/impl_desugar-2.rs b/gcc/testsuite/rust/execute/torture/impl_desugar-2.rs new file mode 100644 index 000000000000..c73ea34c6dab --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_desugar-2.rs @@ -0,0 +1,32 @@ +#[lang = "sized"] +trait Sized {} + +macro_rules! impl_foo { + () => { impl Foo } +} + +pub trait Foo {} + +pub trait Bar { + type Baz; +} + +struct MyBaz; // { dg-warning "struct is never constructed" } +impl Foo for MyBaz {} + +struct MyBar; + +impl Bar for MyBar { + type Baz = MyBaz; +} + +pub fn foo(_value: impl Bar) -> i32 { + 15 +} + +fn main() -> i32 { + let bar = MyBar; + let result: i32 = foo(bar); + + result - 15 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_desugar.rs b/gcc/testsuite/rust/execute/torture/impl_desugar.rs new file mode 100644 index 000000000000..22d39519f305 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_desugar.rs @@ -0,0 +1,32 @@ +#[lang = "sized"] +trait Sized {} + +pub trait Foo {} + +pub trait Bar { + type Baz; +} + +struct MyBaz; // { dg-warning "struct is never constructed" } +impl Foo for MyBaz {} + +struct MyBar; + +impl Bar for MyBar { + type Baz = MyBaz; +} + +pub fn foo(_value: T) -> i32 +where + T: Bar, + U: Foo, +{ + 15 +} + +fn main() -> i32 { + let bar = MyBar; + let result: i32 = foo::(bar); + + result - 15 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_trait1.rs b/gcc/testsuite/rust/execute/torture/impl_trait1.rs new file mode 100644 index 000000000000..33a5c8cf1dbb --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_trait1.rs @@ -0,0 +1,31 @@ +#[lang = "sized"] +trait Sized {} + +pub trait Value { + fn get(&self) -> i32; +} + +struct Foo(i32); +struct Bar(i32); + +impl Value for Foo { + fn get(&self) -> i32 { + self.0 + } +} +impl Value for Bar { + fn get(&self) -> i32 { + self.0 + } +} + +pub fn foo(a: impl Value, b: impl Value) -> i32 { + a.get() + b.get() +} + +fn main() -> i32 { + let a = Foo(1); + let b = Bar(2); + + foo(a, b) - 3 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_trait2.rs b/gcc/testsuite/rust/execute/torture/impl_trait2.rs new file mode 100644 index 000000000000..29f393d679d2 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_trait2.rs @@ -0,0 +1,31 @@ +#[lang = "sized"] +trait Sized {} + +pub trait Value { + fn get(&self) -> i32; +} + +struct Foo(i32); +struct Bar(i32); + +impl Value for Foo { + fn get(&self) -> i32 { + self.0 + } +} +impl Value for Bar { + fn get(&self) -> i32 { + self.0 + } +} + +pub fn foo(a: &impl Value, b: &impl Value) -> i32 { + a.get() + b.get() +} + +fn main() -> i32 { + let a = Foo(1); + let b = Bar(2); + + foo(&a, &b) - 3 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_trait3.rs b/gcc/testsuite/rust/execute/torture/impl_trait3.rs new file mode 100644 index 000000000000..97e2972aeb22 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_trait3.rs @@ -0,0 +1,46 @@ +/* { dg-output "Hello from Message\r*\n" } */ +#[lang = "sized"] +pub trait Sized {} + +extern "C" { + fn printf(s: *const i8, ...); +} + +trait Speak { + fn speak(&self) -> &'static str; +} + +trait Printer { + fn print(&self, input: impl Speak); +} + +struct Console; + +impl Printer for Console { + fn print(&self, input: impl Speak) { + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + unsafe { + let a = input.speak(); + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + } +} + +struct Message(&'static str); + +impl Speak for Message { + fn speak(&self) -> &'static str { + self.0 + } +} + +fn main() -> i32 { + let c = Console; + let msg = Message("Hello from Message\n"); + c.print(msg); + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_trait4.rs b/gcc/testsuite/rust/execute/torture/impl_trait4.rs new file mode 100644 index 000000000000..67d00957e3d6 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_trait4.rs @@ -0,0 +1,31 @@ +#[lang = "sized"] +trait Sized {} + +trait Foo { + fn id(&self) -> i32; +} + +struct A(i32); +struct B(i32); + +impl Foo for A { + fn id(&self) -> i32 { + self.0 + } +} + +impl Foo for B { + fn id(&self) -> i32 { + self.0 + } +} + +fn takes_tuple(pair: (impl Foo, impl Foo)) -> i32 { + pair.0.id() + pair.1.id() +} + +fn main() -> i32 { + let a = A(1); + let b = B(2); + takes_tuple((a, b)) - 3 +} diff --git a/gcc/testsuite/rust/execute/torture/issue-1482.rs b/gcc/testsuite/rust/execute/torture/issue-1482.rs new file mode 100644 index 000000000000..ed8dc8146103 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-1482.rs @@ -0,0 +1,23 @@ +#[lang = "sized"] +trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +fn takes_fn(a: i32, f: impl FnOnce(i32) -> i32) -> i32 { + f(a) +} + +pub fn main() -> i32 { + let capture = 2; + let a = |i: i32| { + let b = i + capture; + b + }; + takes_fn(1, a) - 3 +} From 8852eafac682977b55f4e5c7d1c551832da23e6e Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 2 May 2025 20:28:15 -0400 Subject: [PATCH 009/161] Improve canonical path handling for impl items gcc/rust/ChangeLog: * resolve/rust-ast-resolve-item.cc (ResolveItem::visit): Use the return values of CanonicalPath::inherent_impl_seg and CanonicalPath::trait_impl_projection_seg more directly. * util/rust-canonical-path.h (CanonicalPath::trait_impl_projection_seg): Append " --- gcc/rust/resolve/rust-ast-resolve-item.cc | 13 ++----------- gcc/rust/util/rust-canonical-path.h | 8 ++++++-- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index 30f6d430b861..9f95f517187e 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -608,10 +608,7 @@ ResolveItem::visit (AST::InherentImpl &impl_block) } else { - std::string seg_buf = ""; - CanonicalPath seg - = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf); - cpath = canonical_prefix.append (seg); + cpath = canonical_prefix.append (impl_type_seg); } // done setup paths @@ -732,13 +729,7 @@ ResolveItem::visit (AST::TraitImpl &impl_block) } else { - std::string projection_str = canonical_projection.get (); - std::string seg_buf - = ""; - CanonicalPath seg - = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf); - cpath = canonical_prefix.append (seg); + cpath = canonical_prefix.append (canonical_projection); } // DONE setup canonical-path diff --git a/gcc/rust/util/rust-canonical-path.h b/gcc/rust/util/rust-canonical-path.h index 4d8f9542c8b1..ee37befb2e04 100644 --- a/gcc/rust/util/rust-canonical-path.h +++ b/gcc/rust/util/rust-canonical-path.h @@ -68,14 +68,18 @@ class CanonicalPath trait_impl_projection_seg (NodeId id, const CanonicalPath &trait_seg, const CanonicalPath &impl_type_seg) { - return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + " as " + // https://doc.rust-lang.org/reference/paths.html#canonical-paths + // should be ""? + return CanonicalPath::new_seg (id, ""); } static CanonicalPath inherent_impl_seg (NodeId id, const CanonicalPath &impl_type_seg) { - return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + ">"); + // https://doc.rust-lang.org/reference/paths.html#canonical-paths + // should be ""? + return CanonicalPath::new_seg (id, ""); } std::string get () const From 593c3f37a30a27b8eee84950dee9ccd3f9886c25 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Wed, 30 Apr 2025 21:54:53 -0400 Subject: [PATCH 010/161] Improve struct pattern compilation gcc/rust/ChangeLog: * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit): Fix GENERIC generation in light of enum layout changes since this code was written. (CompilePatternBindings::handle_struct_pattern_ident_pat): Delegate handling of child patterns to another CompilePatternBindings::Compile call. (CompilePatternBindings::make_struct_access): Make field name parameter const qualified. * backend/rust-compile-pattern.h (CompilePatternBindings::make_struct_access): Likewise. gcc/testsuite/ChangeLog: * rust/execute/torture/struct-pattern-match.rs: New test. Signed-off-by: Owen Avery --- gcc/rust/backend/rust-compile-pattern.cc | 44 +++++++------------ gcc/rust/backend/rust-compile-pattern.h | 2 +- .../execute/torture/struct-pattern-match.rs | 13 ++++++ 3 files changed, 30 insertions(+), 29 deletions(-) create mode 100644 gcc/testsuite/rust/execute/torture/struct-pattern-match.rs diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index 64b036109cfb..afde2a61f82d 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -209,6 +209,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) rust_assert (adt->number_of_variants () > 0); TyTy::VariantDef *variant = nullptr; + tree variant_accesser_expr = nullptr; if (adt->is_enum ()) { // lookup the variant @@ -223,9 +224,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) // find expected discriminant // // need to access qualifier the field, if we use QUAL_UNION_TYPE this - // // would be DECL_QUALIFIER i think. For now this will just access the - // // first record field and its respective qualifier because it will - // // always be set because this is all a big special union + // // would be DECL_QUALIFIER i think. HIR::Expr &discrim_expr = variant->get_discriminant (); tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); @@ -234,6 +233,14 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) = Backend::struct_field_expression (match_scrutinee_expr, 0, pattern.get_path ().get_locus ()); + // access variant data + tree scrutinee_union_expr + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern.get_path ().get_locus ()); + variant_accesser_expr + = Backend::struct_field_expression (scrutinee_union_expr, variant_index, + pattern.get_path ().get_locus ()); + check_expr = Backend::comparison_expression (ComparisonOperator::EQUAL, scrutinee_expr_qualifier_expr, @@ -245,6 +252,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) else { variant = adt->get_variants ().at (0); + variant_accesser_expr = match_scrutinee_expr; check_expr = boolean_true_node; } @@ -268,11 +276,8 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) nullptr, &offs); rust_assert (ok); - // we may be offsetting by + 1 here since the first field in the - // record is always the discriminator - offs += adt->is_enum (); tree field_expr - = Backend::struct_field_expression (match_scrutinee_expr, offs, + = Backend::struct_field_expression (variant_accesser_expr, offs, ident.get_locus ()); tree check_expr_sub @@ -512,7 +517,7 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) tree CompilePatternBindings::make_struct_access (TyTy::ADTType *adt, TyTy::VariantDef *variant, - Identifier &ident, + const Identifier &ident, int variant_index) { size_t offs = 0; @@ -562,26 +567,9 @@ CompilePatternBindings::handle_struct_pattern_ident_pat ( { auto &pattern = static_cast (pat); - switch (pattern.get_pattern ().get_pattern_type ()) - { - case HIR::Pattern::IDENTIFIER: { - auto &id - = static_cast (pattern.get_pattern ()); - - CompilePatternBindings::Compile (id, match_scrutinee_expr, ctx); - } - break; - default: - rust_sorry_at (pat.get_locus (), - "cannot handle non-identifier struct patterns"); - return; - } - - auto ident = pattern.get_identifier (); - tree binding = make_struct_access (adt, variant, ident, variant_index); - - ctx->insert_pattern_binding ( - pattern.get_pattern ().get_mappings ().get_hirid (), binding); + tree binding = make_struct_access (adt, variant, pattern.get_identifier (), + variant_index); + CompilePatternBindings::Compile (pattern.get_pattern (), binding, ctx); } void diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h index 511613d58256..85c82b8458f8 100644 --- a/gcc/rust/backend/rust-compile-pattern.h +++ b/gcc/rust/backend/rust-compile-pattern.h @@ -81,7 +81,7 @@ class CompilePatternBindings : public HIRCompileBase, } tree make_struct_access (TyTy::ADTType *adt, TyTy::VariantDef *variant, - Identifier &ident, int variant_index); + const Identifier &ident, int variant_index); void handle_struct_pattern_ident (HIR::StructPatternField &pat, TyTy::ADTType *adt, diff --git a/gcc/testsuite/rust/execute/torture/struct-pattern-match.rs b/gcc/testsuite/rust/execute/torture/struct-pattern-match.rs new file mode 100644 index 000000000000..6aec51f93fe0 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/struct-pattern-match.rs @@ -0,0 +1,13 @@ +enum Foo { + A { x: i32 }, + B { y: i32 } +} + +fn main() -> i32 { + let x = Foo::A { x: 12 }; + match x { + Foo::A { x: 10 } => 1, + Foo::B { y: 11 } => 2, + Foo::A { x: abc } => { abc - 12 } + } +} From cd7756f1c6b53a7db0a353e6dd3950bc58b512b4 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 2 May 2025 18:37:45 -0400 Subject: [PATCH 011/161] nr2.0: Adjust enum item visitors gcc/rust/ChangeLog: * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Make call to EnumItem visitor from EnumItem derived class visitors non-virtual. * ast/rust-collect-lang-items.cc (CollectLangItems::visit): Handle visitation of classes derived from EnumItem. * ast/rust-collect-lang-items.h (CollectLangItems::visit): Likewise. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Call DefaultResolver::visit on EnumItem instances. Signed-off-by: Owen Avery --- gcc/rust/ast/rust-ast-visitor.cc | 6 ++--- gcc/rust/ast/rust-collect-lang-items.cc | 24 +++++++++++++++++++ gcc/rust/ast/rust-collect-lang-items.h | 3 +++ .../rust-toplevel-name-resolver-2.0.cc | 8 +++++++ 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index b6833f69314e..3dfcf5ace025 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -922,7 +922,7 @@ DefaultASTVisitor::visit (AST::EnumItem &item) void DefaultASTVisitor::visit (AST::EnumItemTuple &item) { - visit (reinterpret_cast (item)); + DefaultASTVisitor::visit (reinterpret_cast (item)); for (auto &field : item.get_tuple_fields ()) visit (field); } @@ -930,7 +930,7 @@ DefaultASTVisitor::visit (AST::EnumItemTuple &item) void DefaultASTVisitor::visit (AST::EnumItemStruct &item) { - visit (reinterpret_cast (item)); + DefaultASTVisitor::visit (reinterpret_cast (item)); for (auto &field : item.get_struct_fields ()) visit (field); } @@ -938,7 +938,7 @@ DefaultASTVisitor::visit (AST::EnumItemStruct &item) void DefaultASTVisitor::visit (AST::EnumItemDiscriminant &item) { - visit (reinterpret_cast (item)); + DefaultASTVisitor::visit (reinterpret_cast (item)); visit (item.get_expr ()); } diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc index cd6be7fbeb9c..306c6f747e2b 100644 --- a/gcc/rust/ast/rust-collect-lang-items.cc +++ b/gcc/rust/ast/rust-collect-lang-items.cc @@ -109,5 +109,29 @@ CollectLangItems::visit (AST::EnumItem &item) DefaultASTVisitor::visit (item); } +void +CollectLangItems::visit (AST::EnumItemTuple &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::EnumItemStruct &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::EnumItemDiscriminant &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-collect-lang-items.h b/gcc/rust/ast/rust-collect-lang-items.h index ddb34a914ed7..ddc7b51313bd 100644 --- a/gcc/rust/ast/rust-collect-lang-items.h +++ b/gcc/rust/ast/rust-collect-lang-items.h @@ -50,6 +50,9 @@ class CollectLangItems : public DefaultASTVisitor void visit (AST::Function &item) override; void visit (AST::StructStruct &item) override; void visit (AST::EnumItem &item) override; + void visit (AST::EnumItemTuple &item) override; + void visit (AST::EnumItemStruct &item) override; + void visit (AST::EnumItemDiscriminant &item) override; private: template void maybe_add_lang_item (const T &item); diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index 2f036fe40b3f..dad9205cc26f 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -374,24 +374,32 @@ void TopLevel::visit (AST::EnumItem &variant) { insert_enum_variant_or_error_out (variant.get_identifier (), variant); + + DefaultResolver::visit (variant); } void TopLevel::visit (AST::EnumItemTuple &variant) { insert_enum_variant_or_error_out (variant.get_identifier (), variant); + + DefaultResolver::visit (variant); } void TopLevel::visit (AST::EnumItemStruct &variant) { insert_enum_variant_or_error_out (variant.get_identifier (), variant); + + DefaultResolver::visit (variant); } void TopLevel::visit (AST::EnumItemDiscriminant &variant) { insert_or_error_out (variant.get_identifier (), variant, Namespace::Types); + + DefaultResolver::visit (variant); } void From ba79250925c43a8562ea2c35f544c14389214f03 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 7 May 2025 16:07:43 +0100 Subject: [PATCH 012/161] gccrs: Prevent passing generic arguments to impl traits in argument position When using impl traits in argument position (APIT), they are desugared into generics, and supplying explicit generic arguments is not allowed. This commit adds the error diagnostic E0632 for attempting to pass generic arguments to impl traits, completing the implementation of the APIT feature. gcc/rust/ChangeLog: * ast/rust-desugar-apit.cc: track if this is a impl-trait generic * ast/rust-item.h (class TypeParam): add field to track if from impl trait * hir/rust-ast-lower-type.cc (ASTLowerGenericParam::visit): likewise * hir/tree/rust-hir-item.cc (TypeParam::TypeParam): upate hir as well (TypeParam::operator=): likewise * hir/tree/rust-hir-item.h (class TypeParam): likewise * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_generic_param): add error * typecheck/rust-tyty-subst.h: add const getter for the associated TypeParm gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: nr2 cant handle this * rust/compile/impl_trait_generic_arg.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/ast/rust-desugar-apit.cc | 6 +++-- gcc/rust/ast/rust-item.h | 25 ++++++++----------- gcc/rust/hir/rust-ast-lower-type.cc | 3 ++- gcc/rust/hir/tree/rust-hir-item.cc | 9 ++++--- gcc/rust/hir/tree/rust-hir-item.h | 16 +++++------- gcc/rust/typecheck/rust-tyty-subst.cc | 21 ++++++++++++++-- gcc/rust/typecheck/rust-tyty-subst.h | 1 + .../rust/compile/impl_trait_generic_arg.rs | 24 ++++++++++++++++++ gcc/testsuite/rust/compile/nr2/exclude | 1 + 9 files changed, 73 insertions(+), 33 deletions(-) create mode 100644 gcc/testsuite/rust/compile/impl_trait_generic_arg.rs diff --git a/gcc/rust/ast/rust-desugar-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc index 2f31bcfe7a32..5b9486ea6714 100644 --- a/gcc/rust/ast/rust-desugar-apit.cc +++ b/gcc/rust/ast/rust-desugar-apit.cc @@ -203,7 +203,8 @@ class DesugarApitType : public DefaultASTVisitor // Create the new generic parameter auto generic_param = std::unique_ptr ( - new TypeParam (ident, type.get_locus (), std::move (bounds))); + new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {}, + true /*from impl trait*/)); // Store the generic parameter to be added to the function signature implicit_generic_params.push_back (std::move (generic_param)); @@ -241,7 +242,8 @@ class DesugarApitType : public DefaultASTVisitor // Create the new generic parameter auto generic_param = std::unique_ptr ( - new TypeParam (ident, type.get_locus (), std::move (bounds))); + new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {}, + true /*from impl trait*/)); // Store the generic parameter to be added to the function signature implicit_generic_params.push_back (std::move (generic_param)); diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 062f85d22127..247a65f39c2e 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -51,21 +51,12 @@ class TypePath; // A type generic parameter (as opposed to a lifetime generic parameter) class TypeParam : public GenericParam { - // bool has_outer_attribute; - // std::unique_ptr outer_attr; AST::AttrVec outer_attrs; - Identifier type_representation; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - std::vector> - type_param_bounds; // inlined form - - // bool has_type; + std::vector> type_param_bounds; std::unique_ptr type; - location_t locus; + bool was_impl_trait; public: Identifier get_type_representation () const { return type_representation; } @@ -85,18 +76,19 @@ class TypeParam : public GenericParam std::vector> type_param_bounds = std::vector> (), std::unique_ptr type = nullptr, - AST::AttrVec outer_attrs = {}) + AST::AttrVec outer_attrs = {}, bool was_impl_trait = false) : GenericParam (Analysis::Mappings::get ().get_next_node_id ()), outer_attrs (std::move (outer_attrs)), type_representation (std::move (type_representation)), type_param_bounds (std::move (type_param_bounds)), - type (std::move (type)), locus (locus) + type (std::move (type)), locus (locus), was_impl_trait (was_impl_trait) {} // Copy constructor uses clone TypeParam (TypeParam const &other) : GenericParam (other.node_id), outer_attrs (other.outer_attrs), - type_representation (other.type_representation), locus (other.locus) + type_representation (other.type_representation), locus (other.locus), + was_impl_trait (other.was_impl_trait) { // guard to prevent null pointer dereference if (other.type != nullptr) @@ -114,6 +106,7 @@ class TypeParam : public GenericParam outer_attrs = other.outer_attrs; locus = other.locus; node_id = other.node_id; + was_impl_trait = other.was_impl_trait; // guard to prevent null pointer dereference if (other.type != nullptr) @@ -153,17 +146,19 @@ class TypeParam : public GenericParam return type; } - // TODO: mutable getter seems kinda dodgy std::vector> &get_type_param_bounds () { return type_param_bounds; } + const std::vector> & get_type_param_bounds () const { return type_param_bounds; } + bool from_impl_trait () const { return was_impl_trait; } + protected: // Clone function implementation as virtual method TypeParam *clone_generic_param_impl () const override diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc index 4e44b1b9ce37..1841576b29f4 100644 --- a/gcc/rust/hir/rust-ast-lower-type.cc +++ b/gcc/rust/hir/rust-ast-lower-type.cc @@ -620,7 +620,8 @@ ASTLowerGenericParam::visit (AST::TypeParam ¶m) translated = new HIR::TypeParam (mapping, param.get_type_representation (), param.get_locus (), std::move (type_param_bounds), - std::move (type), param.get_outer_attrs ()); + std::move (type), param.get_outer_attrs (), + param.from_impl_trait ()); } HIR::TypeParamBound * diff --git a/gcc/rust/hir/tree/rust-hir-item.cc b/gcc/rust/hir/tree/rust-hir-item.cc index 160f710408af..1406e7aeb515 100644 --- a/gcc/rust/hir/tree/rust-hir-item.cc +++ b/gcc/rust/hir/tree/rust-hir-item.cc @@ -26,16 +26,18 @@ TypeParam::TypeParam ( Analysis::NodeMapping mappings, Identifier type_representation, location_t locus, std::vector> type_param_bounds, - tl::optional> type, AST::AttrVec outer_attrs) + tl::optional> type, AST::AttrVec outer_attrs, + bool was_impl_trait) : GenericParam (mappings), outer_attrs (std::move (outer_attrs)), type_representation (std::move (type_representation)), type_param_bounds (std::move (type_param_bounds)), type (std::move (type)), - locus (locus) + locus (locus), was_impl_trait (was_impl_trait) {} TypeParam::TypeParam (TypeParam const &other) : GenericParam (other.mappings), outer_attrs (other.outer_attrs), - type_representation (other.type_representation), locus (other.locus) + type_representation (other.type_representation), locus (other.locus), + was_impl_trait (other.was_impl_trait) { // guard to prevent null pointer dereference if (other.has_type ()) @@ -55,6 +57,7 @@ TypeParam::operator= (TypeParam const &other) outer_attrs = other.outer_attrs; locus = other.locus; mappings = other.mappings; + was_impl_trait = other.was_impl_trait; // guard to prevent null pointer dereference if (other.has_type ()) diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 37f599cdee4a..d61027732ab9 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -95,17 +95,11 @@ class Item : public Stmt, public WithOuterAttrs class TypeParam : public GenericParam { AST::AttrVec outer_attrs; - Identifier type_representation; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - std::vector> - type_param_bounds; // inlined form - + std::vector> type_param_bounds; tl::optional> type; - location_t locus; + bool was_impl_trait; public: // Returns whether the type of the type param has been specified. @@ -121,9 +115,9 @@ class TypeParam : public GenericParam TypeParam (Analysis::NodeMapping mappings, Identifier type_representation, location_t locus = UNDEF_LOCATION, std::vector> type_param_bounds - = std::vector> (), + = {}, tl::optional> type = tl::nullopt, - AST::AttrVec outer_attrs = std::vector ()); + AST::AttrVec outer_attrs = {}, bool was_impl_trait = false); // Copy constructor uses clone TypeParam (TypeParam const &other); @@ -154,6 +148,8 @@ class TypeParam : public GenericParam std::vector> &get_type_param_bounds (); + bool from_impl_trait () const { return was_impl_trait; } + protected: // Clone function implementation as (not pure) virtual method TypeParam *clone_generic_param_impl () const override diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index bdb6474aeeb4..28d311a8aad2 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -72,6 +72,12 @@ SubstitutionParamMapping::get_generic_param () return generic; } +const HIR::TypeParam & +SubstitutionParamMapping::get_generic_param () const +{ + return generic; +} + bool SubstitutionParamMapping::needs_substitution () const { @@ -618,7 +624,6 @@ SubstitutionRef::get_mappings_from_generic_args ( if (args.get_binding_args ().size () > get_num_associated_bindings ()) { rich_location r (line_table, args.get_locus ()); - rust_error_at (r, "generic item takes at most %lu type binding " "arguments but %lu were supplied", @@ -702,7 +707,19 @@ SubstitutionRef::get_mappings_from_generic_args ( return SubstitutionArgumentMappings::error (); } - SubstitutionArg subst_arg (&substitutions.at (offs), resolved); + const auto ¶m_mapping = substitutions.at (offs); + const auto &type_param = param_mapping.get_generic_param (); + if (type_param.from_impl_trait ()) + { + rich_location r (line_table, arg->get_locus ()); + r.add_fixit_remove (arg->get_locus ()); + rust_error_at (r, ErrorCode::E0632, + "cannot provide explicit generic arguments when " + "% is used in argument position"); + return SubstitutionArgumentMappings::error (); + } + + SubstitutionArg subst_arg (¶m_mapping, resolved); offs++; mappings.push_back (std::move (subst_arg)); } diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h index e6ed1fc42d67..2f5de23aa00f 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.h +++ b/gcc/rust/typecheck/rust-tyty-subst.h @@ -60,6 +60,7 @@ class SubstitutionParamMapping const ParamType *get_param_ty () const; HIR::TypeParam &get_generic_param (); + const HIR::TypeParam &get_generic_param () const; // this is used for the backend to override the HirId ref of the param to // what the concrete type is for the rest of the context diff --git a/gcc/testsuite/rust/compile/impl_trait_generic_arg.rs b/gcc/testsuite/rust/compile/impl_trait_generic_arg.rs new file mode 100644 index 000000000000..ecdb08803b40 --- /dev/null +++ b/gcc/testsuite/rust/compile/impl_trait_generic_arg.rs @@ -0,0 +1,24 @@ +#[lang = "sized"] +trait Sized {} + +trait Foo { + fn id(&self) -> u8; +} + +struct Bar; + +impl Foo for Bar { + fn id(&self) -> u8 { + 1 + } +} + +fn takes(val: impl Foo) -> u8 { + val.id() +} + +fn main() { + let b = Bar; + let x = takes::(b); + // { dg-error "cannot provide explicit generic arguments when .impl Trait. is used in argument position .E0632." "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index d3bdb1cce0df..b9b9e39aa82c 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -17,4 +17,5 @@ issue-3649.rs issue-1487.rs issue-2015.rs issue-3454.rs +impl_trait_generic_arg.rs # please don't delete the trailing newline From 149f806098768b16a026d2834a6b654bf612a583 Mon Sep 17 00:00:00 2001 From: Tom Schollenberger Date: Thu, 8 May 2025 07:26:07 -0400 Subject: [PATCH 013/161] gccrs: fix ICE on empty constexpr loops Empty loops have no body which means this is a NULL_TREE during const evaluation which needs a check. Fixes Rust-GCC #3618. gcc/rust/ChangeLog: * backend/rust-constexpr.cc (eval_constant_expression): Check if t is a NULL_TREE gcc/testsuite/ChangeLog: * rust/compile/issue-3618.rs: Test empty loops error properly. Signed-off-by: Tom Schollenberger --- gcc/rust/backend/rust-constexpr.cc | 3 +++ gcc/testsuite/rust/compile/issue-3618.rs | 1 + 2 files changed, 4 insertions(+) create mode 100644 gcc/testsuite/rust/compile/issue-3618.rs diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index dc2d6b1066be..0ed56c71ad30 100644 --- a/gcc/rust/backend/rust-constexpr.cc +++ b/gcc/rust/backend/rust-constexpr.cc @@ -1901,6 +1901,9 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, location_t loc = EXPR_LOCATION (t); + if (t == NULL_TREE) + return NULL_TREE; + if (CONSTANT_CLASS_P (t)) { if (TREE_OVERFLOW (t)) diff --git a/gcc/testsuite/rust/compile/issue-3618.rs b/gcc/testsuite/rust/compile/issue-3618.rs new file mode 100644 index 000000000000..97286135e3a5 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3618.rs @@ -0,0 +1 @@ +static _X: () = loop {}; // { dg-error "loop iteration count exceeds limit" } From 5fc78b4bf71fed18639debdcabc0f231e5c40408 Mon Sep 17 00:00:00 2001 From: 0xn4utilus Date: Wed, 7 May 2025 22:21:10 +0530 Subject: [PATCH 014/161] ast: collector: visit InlineAsm node during ast dump gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Implement for InlineAsm. * ast/rust-ast-full-decls.h (enum class): Move InlineAsmOption enum inside InlineAsm. * ast/rust-expr.h (enum class): Likewise. (class InlineAsm): Likewise. * expand/rust-macro-builtins-asm.cc (check_and_set): Likewise. (parse_options): Likewise. * expand/rust-macro-builtins-asm.h (check_and_set): Likewise. * hir/tree/rust-hir-expr.cc (InlineAsm::InlineAsm): Likewise. * hir/tree/rust-hir-expr.h: Likewise. * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise. --- gcc/rust/ast/rust-ast-collector.cc | 83 ++++++++++++++++++- gcc/rust/ast/rust-ast-full-decls.h | 1 - gcc/rust/ast/rust-expr.h | 59 +++++++++---- gcc/rust/expand/rust-macro-builtins-asm.cc | 35 +++----- gcc/rust/expand/rust-macro-builtins-asm.h | 2 +- gcc/rust/hir/tree/rust-hir-expr.cc | 2 +- gcc/rust/hir/tree/rust-hir-expr.h | 6 +- .../typecheck/rust-hir-type-check-expr.cc | 2 +- 8 files changed, 143 insertions(+), 47 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index c850e965cf4d..538c6a411d1c 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -1518,7 +1518,88 @@ TokenCollector::visit (AsyncBlockExpr &expr) void TokenCollector::visit (InlineAsm &expr) -{} +{ + push (Rust::Token::make_identifier (expr.get_locus (), "asm")); + push (Rust::Token::make (EXCLAM, expr.get_locus ())); + push (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); + + for (auto &template_str : expr.get_template_strs ()) + push (Rust::Token::make_string (template_str.get_locus (), + std::move (template_str.symbol))); + + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &operand : expr.get_operands ()) + { + using RegisterType = AST::InlineAsmOperand::RegisterType; + switch (operand.get_register_type ()) + { + case RegisterType::In: { + visit (operand.get_in ().expr); + break; + } + case RegisterType::Out: { + visit (operand.get_out ().expr); + break; + } + case RegisterType::InOut: { + visit (operand.get_in_out ().expr); + break; + } + case RegisterType::SplitInOut: { + auto split = operand.get_split_in_out (); + visit (split.in_expr); + visit (split.out_expr); + break; + } + case RegisterType::Const: { + visit (operand.get_const ().anon_const.expr); + break; + } + case RegisterType::Sym: { + visit (operand.get_sym ().expr); + break; + } + case RegisterType::Label: { + visit (operand.get_label ().expr); + break; + } + } + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &clobber : expr.get_clobber_abi ()) + { + push (Rust::Token::make_string (expr.get_locus (), + std::move (clobber.symbol))); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto it = expr.named_args.begin (); it != expr.named_args.end (); ++it) + { + auto &arg = *it; + push ( + Rust::Token::make_identifier (expr.get_locus (), arg.first.c_str ())); + push (Rust::Token::make (EQUAL, expr.get_locus ())); + push (Rust::Token::make_identifier (expr.get_locus (), + std::to_string (arg.second))); + + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &option : expr.get_options ()) + { + push (Rust::Token::make_identifier ( + expr.get_locus (), InlineAsm::option_to_string (option).c_str ())); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ())); +} void TokenCollector::visit (LlvmInlineAsm &expr) diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 9359248aabd5..1d5853d0deb5 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -145,7 +145,6 @@ struct MatchCase; class MatchExpr; class AwaitExpr; class AsyncBlockExpr; -enum class InlineAsmOption; struct AnonConst; struct InlineAsmRegOrRegClass; class InlineAsmOperand; diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index fdb6360eb3b4..9ecca2251031 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -4822,20 +4822,6 @@ class AsyncBlockExpr : public ExprWithBlock } }; -// Inline-assembly specific options -enum class InlineAsmOption -{ - PURE = 1 << 0, - NOMEM = 1 << 1, - READONLY = 1 << 2, - PRESERVES_FLAGS = 1 << 3, - NORETURN = 1 << 4, - NOSTACK = 1 << 5, - ATT_SYNTAX = 1 << 6, - RAW = 1 << 7, - MAY_UNWIND = 1 << 8, -}; - struct AnonConst { NodeId id; @@ -5288,6 +5274,20 @@ struct TupleTemplateStr // Inline Assembly Node class InlineAsm : public ExprWithoutBlock { +public: + enum class Option + { + PURE = 1 << 0, + NOMEM = 1 << 1, + READONLY = 1 << 2, + PRESERVES_FLAGS = 1 << 3, + NORETURN = 1 << 4, + NOSTACK = 1 << 5, + ATT_SYNTAX = 1 << 6, + RAW = 1 << 7, + MAY_UNWIND = 1 << 8, + }; + private: location_t locus; // TODO: Not sure how outer_attrs plays with InlineAsm, I put it here in order @@ -5311,7 +5311,7 @@ class InlineAsm : public ExprWithoutBlock std::map named_args; std::set reg_args; std::vector clobber_abi; - std::set options; + std::set options; std::vector line_spans; @@ -5342,7 +5342,7 @@ class InlineAsm : public ExprWithoutBlock std::vector get_clobber_abi () { return clobber_abi; } - std::set get_options () { return options; } + std::set get_options () { return options; } InlineAsm *clone_expr_without_block_impl () const override { @@ -5350,6 +5350,33 @@ class InlineAsm : public ExprWithoutBlock } Expr::Kind get_expr_kind () const override { return Expr::Kind::InlineAsm; } + + static std::string option_to_string (Option option) + { + switch (option) + { + case Option::PURE: + return "pure"; + case Option::NOMEM: + return "nomem"; + case Option::READONLY: + return "readonly"; + case Option::PRESERVES_FLAGS: + return "preserves_flags"; + case Option::NORETURN: + return "noreturn"; + case Option::NOSTACK: + return "nostack"; + case Option::ATT_SYNTAX: + return "att_syntax"; + case Option::RAW: + return "raw"; + case Option::MAY_UNWIND: + return "may_unwind"; + default: + rust_unreachable (); + } + } }; class LlvmInlineAsm : public ExprWithoutBlock diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc index e255729885b8..ca3c22e7f8b0 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.cc +++ b/gcc/rust/expand/rust-macro-builtins-asm.cc @@ -25,18 +25,6 @@ #include "rust-parse.h" namespace Rust { -std::map InlineAsmOptionMap{ - {AST::InlineAsmOption::PURE, "pure"}, - {AST::InlineAsmOption::NOMEM, "nomem"}, - {AST::InlineAsmOption::READONLY, "readonly"}, - {AST::InlineAsmOption::PRESERVES_FLAGS, "preserves_flags"}, - {AST::InlineAsmOption::NORETURN, "noreturn"}, - {AST::InlineAsmOption::NOSTACK, "nostack"}, - {AST::InlineAsmOption::MAY_UNWIND, "may_unwind"}, - {AST::InlineAsmOption::ATT_SYNTAX, "att_syntax"}, - {AST::InlineAsmOption::RAW, "raw"}, -}; - std::set potentially_nonpromoted_keywords = {"in", "out", "lateout", "inout", "inlateout", "const", "sym", "label"}; @@ -500,7 +488,7 @@ parse_reg_operand_unexpected (InlineAsmContext inline_asm_ctx) } void -check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option) +check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsm::Option option) { auto &parser = inline_asm_ctx.parser; auto &inline_asm = inline_asm_ctx.inline_asm; @@ -509,7 +497,7 @@ check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option) // TODO: report an error of duplication rust_error_at (parser.peek_current_token ()->get_locus (), "the %qs option was already provided", - InlineAsmOptionMap[option].c_str ()); + AST::InlineAsm::option_to_string (option).c_str ()); return; } else @@ -536,39 +524,40 @@ parse_options (InlineAsmContext &inline_asm_ctx) { if (!is_global_asm && check_identifier (parser, "pure")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::PURE); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::PURE); } else if (!is_global_asm && check_identifier (parser, "nomem")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::NOMEM); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NOMEM); } else if (!is_global_asm && check_identifier (parser, "readonly")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::READONLY); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::READONLY); } else if (!is_global_asm && check_identifier (parser, "preserves_flags")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::PRESERVES_FLAGS); + check_and_set (inline_asm_ctx, + AST::InlineAsm::Option::PRESERVES_FLAGS); } else if (!is_global_asm && check_identifier (parser, "noreturn")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::NORETURN); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NORETURN); } else if (!is_global_asm && check_identifier (parser, "nostack")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::NOSTACK); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NOSTACK); } else if (!is_global_asm && check_identifier (parser, "may_unwind")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::MAY_UNWIND); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::MAY_UNWIND); } else if (check_identifier (parser, "att_syntax")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::ATT_SYNTAX); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::ATT_SYNTAX); } else if (check_identifier (parser, "raw")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::RAW); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::RAW); } else { diff --git a/gcc/rust/expand/rust-macro-builtins-asm.h b/gcc/rust/expand/rust-macro-builtins-asm.h index bd64a7f4dd62..2bdaed5e08fb 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.h +++ b/gcc/rust/expand/rust-macro-builtins-asm.h @@ -151,7 +151,7 @@ bool check_identifier (Parser &parser, std::string ident); void -check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option); +check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsm::Option option); // From rustc WARN_UNUSED_RESULT diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc b/gcc/rust/hir/tree/rust-hir-expr.cc index 266c79c2fe89..5df9253aae21 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.cc +++ b/gcc/rust/hir/tree/rust-hir-expr.cc @@ -1476,7 +1476,7 @@ InlineAsm::InlineAsm (location_t locus, bool is_global_asm, std::vector template_strs, std::vector operands, std::vector clobber_abi, - std::set options, + std::set options, Analysis::NodeMapping mappings, AST::AttrVec outer_attribs) : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 375f47402f01..6fbe1e48e1b0 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -3059,7 +3059,7 @@ class InlineAsm : public ExprWithoutBlock std::vector template_strs; std::vector operands; std::vector clobber_abi; - std::set options; + std::set options; std::vector line_spans; @@ -3094,7 +3094,7 @@ class InlineAsm : public ExprWithoutBlock std::vector get_clobber_abi () { return clobber_abi; } - std::set get_options () { return options; } + std::set get_options () { return options; } bool is_simple_asm () { @@ -3113,7 +3113,7 @@ class InlineAsm : public ExprWithoutBlock std::vector template_strs, std::vector operands, std::vector clobber_abi, - std::set options, + std::set options, Analysis::NodeMapping mappings, AST::AttrVec outer_attribs = AST::AttrVec ()); }; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index cbf529a77eb9..7283d01d5a3c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -837,7 +837,7 @@ TypeCheckExpr::visit (HIR::InlineAsm &expr) // NOTE: Hoise out if we have noreturn as an option // to return a never type // TODO : new keyword for memory seems sooooo shaky - if (expr.options.count (AST::InlineAsmOption::NORETURN) == 1) + if (expr.options.count (AST::InlineAsm::Option::NORETURN) == 1) infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ()); else infered = TyTy::TupleType::get_unit_type (); From 3e0d11a77907794dd3c07b3bfd1759f2bd494bec Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 25 Apr 2025 18:06:41 -0400 Subject: [PATCH 015/161] nr2.0: Adjust resolution of impl items gcc/rust/ChangeLog: * ast/rust-path.cc (TypePath::make_debug_string): Add definition. * ast/rust-path.h (TypePath::make_debug_string): Add declaration. * resolve/rust-default-resolver.cc (DefaultResolver::visit): Adjust InherentImpl and TraitImpl visitors to better handle associated item scope. * resolve/rust-default-resolver.h (DefaultResolver::maybe_insert_big_self): Add. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Adjust type path resolution errors. * resolve/rust-rib.h (Rib::Kind): Add Generics kind. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Remove InherentImpl and TraitImpl visitor overrides. (TopLevel::maybe_insert_big_self): Add override in order to add a definition of 'Self'. * resolve/rust-toplevel-name-resolver-2.0.h (TopLevel::visit): Remove InherentImpl and TraitImpl visitor overrides. (TopLevel::maybe_insert_big_self): Add override. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove entries. Signed-off-by: Owen Avery --- gcc/rust/ast/rust-path.cc | 21 +++++++++ gcc/rust/ast/rust-path.h | 2 + gcc/rust/resolve/rust-default-resolver.cc | 45 +++++++++++++++++-- gcc/rust/resolve/rust-default-resolver.h | 2 + .../resolve/rust-late-name-resolver-2.0.cc | 7 +-- gcc/rust/resolve/rust-rib.h | 2 + .../rust-toplevel-name-resolver-2.0.cc | 29 ++---------- .../resolve/rust-toplevel-name-resolver-2.0.h | 3 +- gcc/testsuite/rust/compile/nr2/exclude | 2 - 9 files changed, 76 insertions(+), 37 deletions(-) diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc index 8e43ddf648a9..793423aa6ee8 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -266,6 +266,27 @@ TypePath::as_simple_path () const locus); } +std::string +TypePath::make_debug_string () const +{ + rust_assert (!segments.empty ()); + + std::string output; + + for (const auto &segment : segments) + { + if (segment != nullptr && !segment->is_lang_item () + && !segment->is_error ()) + { + if (!output.empty () || has_opening_scope_resolution_op ()) + output.append ("::"); + output.append (segment->get_ident_segment ().as_string ()); + } + } + + return output; +} + // hopefully definition here will prevent circular dependency issue TraitBound * TypePath::to_trait_bound (bool in_parens) const diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 73e2f83104b3..11f72480fe07 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -1211,6 +1211,8 @@ class TypePath : public TypeNoBounds std::string as_string () const override; + std::string make_debug_string () const; + /* Converts TypePath to SimplePath if possible (i.e. no generic or function * arguments). Otherwise returns an empty SimplePath. */ SimplePath as_simple_path () const; diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 480034c89741..dce5aaa6a11a 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -72,17 +72,54 @@ DefaultResolver::visit (AST::Trait &trait) void DefaultResolver::visit (AST::InherentImpl &impl) { - auto inner_fn = [this, &impl] () { AST::DefaultASTVisitor::visit (impl); }; + visit_outer_attrs (impl); + visit (impl.get_visibility ()); + visit_inner_attrs (impl); - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn); + auto inner_fn_inner = [this, &impl] () { + for (auto &item : impl.get_impl_items ()) + visit (item); + }; + + auto inner_fn_outer = [this, &impl, &inner_fn_inner] () { + maybe_insert_big_self (impl); + for (auto &generic : impl.get_generic_params ()) + visit (generic); + if (impl.has_where_clause ()) + visit (impl.get_where_clause ()); + visit (impl.get_type ()); + + ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_inner); + }; + + ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_outer); } void DefaultResolver::visit (AST::TraitImpl &impl) { - auto inner_fn = [this, &impl] () { AST::DefaultASTVisitor::visit (impl); }; + visit_outer_attrs (impl); + visit (impl.get_visibility ()); + visit_inner_attrs (impl); + + auto inner_fn_inner = [this, &impl] () { + for (auto &item : impl.get_impl_items ()) + visit (item); + }; + + auto inner_fn_outer = [this, &impl, &inner_fn_inner] () { + maybe_insert_big_self (impl); + for (auto &generic : impl.get_generic_params ()) + visit (generic); + if (impl.has_where_clause ()) + visit (impl.get_where_clause ()); + visit (impl.get_type ()); + visit (impl.get_trait_path ()); + + ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_inner); + }; - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn); + ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_outer); } void diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 2a987efdf5c4..87281377d70f 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -47,6 +47,8 @@ class DefaultResolver : public AST::DefaultASTVisitor void visit (AST::Function &) override; void visit (AST::ForLoopExpr &expr) override; void visit (AST::Trait &) override; + // used to handle Self insertion in TopLevel + virtual void maybe_insert_big_self (AST::Impl &) {} void visit (AST::InherentImpl &) override; void visit (AST::TraitImpl &) override; diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 821c61d6cc52..dd2a8f37df06 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -495,15 +495,16 @@ Late::visit (AST::TypePath &type) if (!resolved.has_value ()) { if (!ctx.lookup (type.get_segments ().front ()->get_node_id ())) - rust_error_at (type.get_locus (), "could not resolve type path %qs", - type.as_string ().c_str ()); + rust_error_at (type.get_locus (), ErrorCode::E0412, + "could not resolve type path %qs", + type.make_debug_string ().c_str ()); return; } if (resolved->is_ambiguous ()) { rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous", - type.as_string ().c_str ()); + type.make_debug_string ().c_str ()); return; } diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h index c498328a8087..62189f7a6d10 100644 --- a/gcc/rust/resolve/rust-rib.h +++ b/gcc/rust/resolve/rust-rib.h @@ -188,6 +188,8 @@ class Rib * restriction that you cannot `use` items from the Prelude */ Prelude, + /* Generic rib, used to store generics */ + Generics, } kind; static std::string kind_to_string (Rib::Kind kind) diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index dad9205cc26f..122436bb22fe 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -141,33 +141,10 @@ TopLevel::visit (AST::Trait &trait) } void -TopLevel::visit (AST::InherentImpl &impl) +TopLevel::maybe_insert_big_self (AST::Impl &impl) { - auto inner_fn = [this, &impl] () { - insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()), - impl.get_type (), Namespace::Types); - - // We do want to visit with the default visitor instead of default resolver - // because we don't want to insert the scope twice. - AST::DefaultASTVisitor::visit (impl); - }; - - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn); -} - -void -TopLevel::visit (AST::TraitImpl &impl) -{ - auto inner_fn = [this, &impl] () { - insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()), - impl.get_type (), Namespace::Types); - - // We do want to visit using the default visitor instead of default resolver - // because we don't want to insert the scope twice. - AST::DefaultASTVisitor::visit (impl); - }; - - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn); + insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()), + impl.get_type (), Namespace::Types); } void diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h index 3ff37eda16d1..0dfd654861b3 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -160,8 +160,7 @@ class TopLevel : public DefaultResolver void visit (AST::Module &module) override; void visit (AST::Trait &trait) override; - void visit (AST::InherentImpl &impl) override; - void visit (AST::TraitImpl &impl) override; + void maybe_insert_big_self (AST::Impl &impl) override; void visit (AST::TraitItemType &trait_item) override; void visit (AST::MacroRulesDefinition ¯o) override; void visit (AST::Function &function) override; diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index b9b9e39aa82c..312964c6b144 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -10,10 +10,8 @@ derive-default1.rs derive-eq-invalid.rs torture/alt_patterns1.rs torture/name_resolve1.rs -issue-3663.rs issue-3671.rs issue-3652.rs -issue-3649.rs issue-1487.rs issue-2015.rs issue-3454.rs From fff49cca1ec4364964aa463cb27d2251b4ac7974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Poulhi=C3=A8s?= Date: Fri, 9 May 2025 11:09:58 +0200 Subject: [PATCH 016/161] gccrs: Adapt attribute lang hook and do some cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since r14-6076, the LANG_HOOKS_COMMON_ATTRIBUTE_TABLE should not be used and LANG_HOOKS_ATTRIBUTE_TABLE replaces it. Add the "cold" attribute to fix PR120018 (and the matching "hot" attribute). Replace some gcc_assert() by explicit warnings (same as D frontend). Add some clang-format off/on comment around code that's not correctly formatted. gcc/rust/ChangeLog: PR rust/120018 * rust-attribs.cc (handle_noreturn_attribute): Reindent declaration. (handle_leaf_attribute): Likewise. (handle_const_attribute): Likewise. (handle_malloc_attribute): Likewise. (handle_pure_attribute): Likewise. (handle_novops_attribute): Likewise. (handle_nonnull_attribute): Likewise. (handle_nothrow_attribute): Likewise. (handle_type_generic_attribute): Likewise. (handle_transaction_pure_attribute): Likewise. (handle_returns_twice_attribute): Likewise. (handle_fnspec_attribute): Likewise. (handle_omp_declare_simd_attribute): Likewise. (handle_cold_attribute): New. (handle_hot_attribute): New. (attribute_spec::exclusions attr_cold_hot_exclusions): New. (grs_langhook_common_attributes): Make it static. (grs_langhook_common_attribute_table): New. (grs_langhook_gnu_attributes): New. (grs_langhook_gnu_attribute_table): New. (handle_malloc_attribute): Make it static. (handle_fnspec_attribute): Likewise. (handle_pure_attribute): Replace gcc_assert by explicit warning. (handle_novops_attribute): Likewise. (handle_nothrow_attribute): Likewise. (handle_returns_twice_attribute): Likewise. (handle_omp_declare_simd_attribute): Likewise and make it static. * rust-lang.cc (grs_langhook_gnu_attribute_table): New. (grs_langhook_common_attribute_table): Adjust type to new hook. (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Remove. (LANG_HOOKS_ATTRIBUTE_TABLE): New. Signed-off-by: Marc Poulhiès --- gcc/rust/rust-attribs.cc | 168 +++++++++++++++++++++++++++++---------- gcc/rust/rust-lang.cc | 13 ++- 2 files changed, 134 insertions(+), 47 deletions(-) diff --git a/gcc/rust/rust-attribs.cc b/gcc/rust/rust-attribs.cc index 74cb2aff90fc..195dfbd57887 100644 --- a/gcc/rust/rust-attribs.cc +++ b/gcc/rust/rust-attribs.cc @@ -38,35 +38,33 @@ along with GCC; see the file COPYING3. If not see * future. */ -extern const attribute_spec grs_langhook_common_attribute_table[]; +extern const struct scoped_attribute_specs grs_langhook_gnu_attribute_table; +extern const struct scoped_attribute_specs grs_langhook_common_attribute_table; + +/* clang-format off */ +/* Disable clang-format because it insists in having the return type on a + single line (that's for definitions) */ /* Internal attribute handlers for built-in functions. */ -static tree -handle_noreturn_attribute (tree *, tree, tree, int, bool *); -static tree -handle_leaf_attribute (tree *, tree, tree, int, bool *); -static tree -handle_const_attribute (tree *, tree, tree, int, bool *); -static tree -handle_malloc_attribute (tree *, tree, tree, int, bool *); -static tree -handle_pure_attribute (tree *, tree, tree, int, bool *); -static tree -handle_novops_attribute (tree *, tree, tree, int, bool *); -static tree -handle_nonnull_attribute (tree *, tree, tree, int, bool *); -static tree -handle_nothrow_attribute (tree *, tree, tree, int, bool *); -static tree -handle_type_generic_attribute (tree *, tree, tree, int, bool *); -static tree -handle_transaction_pure_attribute (tree *, tree, tree, int, bool *); -static tree -handle_returns_twice_attribute (tree *, tree, tree, int, bool *); -static tree -handle_fnspec_attribute (tree *, tree, tree, int, bool *); -static tree -handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); +static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); +static tree handle_leaf_attribute (tree *, tree, tree, int, bool *); +static tree handle_const_attribute (tree *, tree, tree, int, bool *); +static tree handle_malloc_attribute (tree *, tree, tree, int, bool *); +static tree handle_pure_attribute (tree *, tree, tree, int, bool *); +static tree handle_novops_attribute (tree *, tree, tree, int, bool *); +static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); +static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *); +static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); +static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *); +static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *); +static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *); +static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); + +/* Rust attribute handlers for user defined attributes. */ +static tree handle_cold_attribute (tree *, tree, tree, int, bool *); +static tree handle_hot_attribute (tree *, tree, tree, int, bool *); + +/* clang-format on */ /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ @@ -74,6 +72,10 @@ handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); name, function, type, variable \ } +// clang-format off +// Disabling clang-format because it insists in having several ATTR_EXCL() on a +// single line. + static const struct attribute_spec::exclusions attr_noreturn_exclusions[] = { // ATTR_EXCL ("alloc_size", true, true, true), ATTR_EXCL ("const", true, true, true), @@ -89,11 +91,22 @@ static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] ATTR_EXCL (NULL, false, false, false), }; +extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] = { + + ATTR_EXCL ("cold", true, true, true), + ATTR_EXCL ("hot", true, true, true), + ATTR_EXCL (NULL, false, false, false) +}; + static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = { // ATTR_EXCL ("alloc_size", true, true, true), ATTR_EXCL ("const", true, true, true), ATTR_EXCL ("noreturn", true, true, true), - ATTR_EXCL ("pure", true, true, true), ATTR_EXCL (NULL, false, false, false)}; + ATTR_EXCL ("pure", true, true, true), + ATTR_EXCL (NULL, false, false, false) +}; + +// clang-format on /* Helper to define an attribute. */ #define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \ @@ -105,7 +118,7 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = { /* Table of machine-independent attributes. For internal use (marking of built-ins) only. */ -const attribute_spec grs_langhook_common_attribute_table[] = { +static const attribute_spec grs_langhook_common_attributes[] = { ATTR_SPEC ("noreturn", 0, 0, true, false, false, false, handle_noreturn_attribute, attr_noreturn_exclusions), ATTR_SPEC ("leaf", 0, 0, true, false, false, false, handle_leaf_attribute, @@ -132,9 +145,21 @@ const attribute_spec grs_langhook_common_attribute_table[] = { NULL), ATTR_SPEC ("omp declare simd", 0, -1, true, false, false, false, handle_omp_declare_simd_attribute, NULL), - ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL), }; +const scoped_attribute_specs grs_langhook_common_attribute_table + = {"gnu", {grs_langhook_common_attributes}}; + +static const attribute_spec grs_langhook_gnu_attributes[] = { + ATTR_SPEC ("cold", 0, 0, true, false, false, false, handle_cold_attribute, + attr_cold_hot_exclusions), + ATTR_SPEC ("hot", 0, 0, true, false, false, false, handle_hot_attribute, + attr_cold_hot_exclusions), +}; + +const scoped_attribute_specs grs_langhook_gnu_attribute_table + = {"gnu", {grs_langhook_gnu_attributes}}; + /* Built-in attribute handlers. These functions take the arguments: (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */ @@ -204,7 +229,7 @@ handle_const_attribute (tree *node, tree, tree, int, bool *) /* Handle a "malloc" attribute; arguments as in struct attribute_spec.handler. */ -tree +static tree handle_malloc_attribute (tree *node, tree, tree, int, bool *) { gcc_assert (TREE_CODE (*node) == FUNCTION_DECL @@ -217,9 +242,14 @@ handle_malloc_attribute (tree *node, tree, tree, int, bool *) struct attribute_spec.handler. */ static tree -handle_pure_attribute (tree *node, tree, tree, int, bool *) +handle_pure_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + DECL_PURE_P (*node) = 1; return NULL_TREE; } @@ -228,9 +258,14 @@ handle_pure_attribute (tree *node, tree, tree, int, bool *) struct attribute_spec.handler. */ static tree -handle_novops_attribute (tree *node, tree, tree, int, bool *) +handle_novops_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + DECL_IS_NOVOPS (*node) = 1; return NULL_TREE; } @@ -301,9 +336,14 @@ handle_nonnull_attribute (tree *node, tree, tree args, int, bool *) struct attribute_spec.handler. */ static tree -handle_nothrow_attribute (tree *node, tree, tree, int, bool *) +handle_nothrow_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + TREE_NOTHROW (*node) = 1; return NULL_TREE; } @@ -339,9 +379,14 @@ handle_transaction_pure_attribute (tree *node, tree, tree, int, bool *) struct attribute_spec.handler. */ static tree -handle_returns_twice_attribute (tree *node, tree, tree, int, bool *) +handle_returns_twice_attribute (tree *node, tree name, tree, int, + bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } DECL_IS_RETURNS_TWICE (*node) = 1; @@ -351,7 +396,7 @@ handle_returns_twice_attribute (tree *node, tree, tree, int, bool *) /* Handle a "fn spec" attribute; arguments as in struct attribute_spec.handler. */ -tree +static tree handle_fnspec_attribute (tree *, tree, tree args, int, bool *) { gcc_assert (args && TREE_CODE (TREE_VALUE (args)) == STRING_CST @@ -362,9 +407,46 @@ handle_fnspec_attribute (tree *, tree, tree args, int, bool *) /* Handle an "omp declare simd" attribute; arguments as in struct attribute_spec.handler. */ -tree -handle_omp_declare_simd_attribute (tree *node, tree, tree, int, bool *) +static tree +handle_omp_declare_simd_attribute (tree *node, tree name, tree, int, + bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Language specific attribute handlers. + These functions take the arguments: + (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */ + +/* Handle a "cold" and attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_cold_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +static tree +handle_hot_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + return NULL_TREE; } diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc index f3a155dbad1f..35003ab327b7 100644 --- a/gcc/rust/rust-lang.cc +++ b/gcc/rust/rust-lang.cc @@ -373,7 +373,13 @@ rust_localize_identifier (const char *ident) return identifier_to_locale (ident); } -extern const attribute_spec grs_langhook_common_attribute_table[]; +extern const struct scoped_attribute_specs grs_langhook_gnu_attribute_table; +extern const struct scoped_attribute_specs grs_langhook_common_attribute_table; + +const scoped_attribute_specs *const grs_langhook_attribute_table[] = { + &grs_langhook_gnu_attribute_table, + &grs_langhook_common_attribute_table, +}; /* The language hooks data structure. This is the main interface between the GCC * front-end and the GCC middle-end/back-end. A list of language hooks could be @@ -394,8 +400,7 @@ extern const attribute_spec grs_langhook_common_attribute_table[]; #undef LANG_HOOKS_WRITE_GLOBALS #undef LANG_HOOKS_GIMPLIFY_EXPR #undef LANG_HOOKS_EH_PERSONALITY - -#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE +#undef LANG_HOOKS_ATTRIBUTE_TABLE #define LANG_HOOKS_NAME "GNU Rust" #define LANG_HOOKS_INIT grs_langhook_init @@ -417,7 +422,7 @@ extern const attribute_spec grs_langhook_common_attribute_table[]; #define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr #define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality -#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE grs_langhook_common_attribute_table +#define LANG_HOOKS_ATTRIBUTE_TABLE grs_langhook_attribute_table #if CHECKING_P From ee2951574c161f25388a7b39a6b668dd5c47ffa9 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sun, 11 May 2025 15:03:05 +0100 Subject: [PATCH 017/161] gccrs: We cant clone types as it will dup the node-id This patch ensuers we reuse the Builder for new type to ensure we create a new type from scratch ensuring consistent new node-ids. gcc/rust/ChangeLog: * expand/rust-derive-default.cc (DeriveDefault::visit_struct): use builder (DeriveDefault::visit_tuple): likewise * expand/rust-derive-eq.cc (DeriveEq::visit_tuple): likewise (DeriveEq::visit_struct): likewise (DeriveEq::visit_enum): likewise (DeriveEq::visit_union): likewise gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: these are fixed now Signed-off-by: Philip Herron --- gcc/rust/expand/rust-derive-default.cc | 5 +++-- gcc/rust/expand/rust-derive-eq.cc | 26 ++++++++++++++++++++------ gcc/testsuite/rust/compile/nr2/exclude | 2 -- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/gcc/rust/expand/rust-derive-default.cc b/gcc/rust/expand/rust-derive-default.cc index 2e8b45681994..1b497b5923b0 100644 --- a/gcc/rust/expand/rust-derive-default.cc +++ b/gcc/rust/expand/rust-derive-default.cc @@ -98,7 +98,8 @@ DeriveDefault::visit_struct (StructStruct &item) for (auto &field : item.get_fields ()) { auto name = field.get_field_name ().as_string (); - auto expr = default_call (field.get_field_type ().clone_type ()); + auto type = Builder::new_type (field.get_field_type ()); + auto expr = default_call (std::move (type)); cloned_fields.emplace_back ( builder.struct_expr_field (std::move (name), std::move (expr))); @@ -119,7 +120,7 @@ DeriveDefault::visit_tuple (TupleStruct &tuple_item) for (auto &field : tuple_item.get_fields ()) { - auto type = field.get_field_type ().clone_type (); + auto type = Builder::new_type (field.get_field_type ()); defaulted_fields.emplace_back (default_call (std::move (type))); } diff --git a/gcc/rust/expand/rust-derive-eq.cc b/gcc/rust/expand/rust-derive-eq.cc index 5e7a8946dfdb..04c987dc96e3 100644 --- a/gcc/rust/expand/rust-derive-eq.cc +++ b/gcc/rust/expand/rust-derive-eq.cc @@ -142,7 +142,10 @@ DeriveEq::visit_tuple (TupleStruct &item) auto types = std::vector> (); for (auto &field : item.get_fields ()) - types.emplace_back (field.get_field_type ().clone_type ()); + { + auto type = Builder::new_type (field.get_field_type ()); + types.emplace_back (std::move (type)); + } expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)), item.get_identifier ().as_string (), @@ -155,7 +158,10 @@ DeriveEq::visit_struct (StructStruct &item) auto types = std::vector> (); for (auto &field : item.get_fields ()) - types.emplace_back (field.get_field_type ().clone_type ()); + { + auto type = Builder::new_type (field.get_field_type ()); + types.emplace_back (std::move (type)); + } expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)), item.get_identifier ().as_string (), @@ -179,15 +185,20 @@ DeriveEq::visit_enum (Enum &item) auto &tuple = static_cast (*variant); for (auto &field : tuple.get_tuple_fields ()) - types.emplace_back (field.get_field_type ().clone_type ()); - + { + auto type = Builder::new_type (field.get_field_type ()); + types.emplace_back (std::move (type)); + } break; } case EnumItem::Kind::Struct: { auto &tuple = static_cast (*variant); for (auto &field : tuple.get_struct_fields ()) - types.emplace_back (field.get_field_type ().clone_type ()); + { + auto type = Builder::new_type (field.get_field_type ()); + types.emplace_back (std::move (type)); + } break; } @@ -205,7 +216,10 @@ DeriveEq::visit_union (Union &item) auto types = std::vector> (); for (auto &field : item.get_variants ()) - types.emplace_back (field.get_field_type ().clone_type ()); + { + auto type = Builder::new_type (field.get_field_type ()); + types.emplace_back (std::move (type)); + } expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)), item.get_identifier ().as_string (), diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 312964c6b144..d4e066a5f723 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -6,8 +6,6 @@ pub_restricted_1.rs pub_restricted_2.rs pub_restricted_3.rs issue-2905-2.rs -derive-default1.rs -derive-eq-invalid.rs torture/alt_patterns1.rs torture/name_resolve1.rs issue-3671.rs From 2702cd5da39ecf0f927d00e1a373ccfaefdc62ef Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 9 May 2025 18:02:29 -0400 Subject: [PATCH 018/161] nr2.0: Fix borrow checking gcc/rust/ChangeLog: * checks/errors/borrowck/rust-bir-builder-internal.h: Include "rust-immutable-name-resolution-context.h" and "options.h". (AbstractBuilder::resolve_label): Use the 2.0 name resolver when it's enabled. (AbstractBuilder::resolve_variable): Likewise. (AbstractBuilder::resolve_variable_or_fn): Likewise. Signed-off-by: Owen Avery --- .../borrowck/rust-bir-builder-internal.h | 54 +++++++++++++++---- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h index 4df0e14c0ecd..e2cc2ddb0d87 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h @@ -27,6 +27,8 @@ #include "rust-name-resolver.h" #include "rust-bir.h" #include "rust-bir-free-region.h" +#include "rust-immutable-name-resolution-context.h" +#include "options.h" namespace Rust { @@ -402,19 +404,40 @@ class AbstractBuilder template NodeId resolve_label (T &expr) { NodeId resolved_label; - bool ok - = ctx.resolver.lookup_resolved_label (expr.get_mappings ().get_nodeid (), - &resolved_label); - rust_assert (ok); + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto res = nr_ctx.lookup (expr.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + resolved_label = res.value (); + } + else + { + bool ok = ctx.resolver.lookup_resolved_label ( + expr.get_mappings ().get_nodeid (), &resolved_label); + rust_assert (ok); + } return resolved_label; } template PlaceId resolve_variable (T &variable) { NodeId variable_id; - bool ok = ctx.resolver.lookup_resolved_name ( - variable.get_mappings ().get_nodeid (), &variable_id); - rust_assert (ok); + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + variable_id = res.value (); + } + else + { + bool ok = ctx.resolver.lookup_resolved_name ( + variable.get_mappings ().get_nodeid (), &variable_id); + rust_assert (ok); + } return ctx.place_db.lookup_variable (variable_id); } @@ -425,9 +448,20 @@ class AbstractBuilder // Unlike variables, // functions do not have to be declared in PlaceDB before use. NodeId variable_id; - bool ok = ctx.resolver.lookup_resolved_name ( - variable.get_mappings ().get_nodeid (), &variable_id); - rust_assert (ok); + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + variable_id = res.value (); + } + else + { + bool ok = ctx.resolver.lookup_resolved_name ( + variable.get_mappings ().get_nodeid (), &variable_id); + rust_assert (ok); + } if (ty->is ()) return ctx.place_db.get_constant (ty); else From bbc9214973034bb96860623ce545219a87140aed Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 9 May 2025 20:48:18 -0400 Subject: [PATCH 019/161] Fix test same_field_name.rs gcc/rust/ChangeLog: * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Keep going after a duplicate field is found. gcc/testsuite/ChangeLog: * rust/execute/same_field_name.rs: Move to... * rust/compile/same_field_name.rs: ...here and adjust expected errors. Signed-off-by: Owen Avery --- gcc/rust/hir/rust-ast-lower-item.cc | 2 +- gcc/testsuite/rust/{execute => compile}/same_field_name.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename gcc/testsuite/rust/{execute => compile}/same_field_name.rs (76%) diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc index 1810d16d515d..66ccafa4f522 100644 --- a/gcc/rust/hir/rust-ast-lower-item.cc +++ b/gcc/rust/hir/rust-ast-lower-item.cc @@ -217,7 +217,7 @@ ASTLoweringItem::visit (AST::StructStruct &struct_decl) field.get_outer_attrs ()); if (struct_field_name_exists (fields, translated_field)) - break; + continue; fields.push_back (std::move (translated_field)); } diff --git a/gcc/testsuite/rust/execute/same_field_name.rs b/gcc/testsuite/rust/compile/same_field_name.rs similarity index 76% rename from gcc/testsuite/rust/execute/same_field_name.rs rename to gcc/testsuite/rust/compile/same_field_name.rs index d57562b39a64..8e5b78c74365 100644 --- a/gcc/testsuite/rust/execute/same_field_name.rs +++ b/gcc/testsuite/rust/compile/same_field_name.rs @@ -1,7 +1,7 @@ // https://doc.rust-lang.org/error_codes/E0124.html fn main() { struct Foo { - field1: i32, // { dg-error "field .field1. is already declared" } + field1: i32, field1: i32, // { dg-error "field .field1. is already declared" } field1: i32, // { dg-error "field .field1. is already declared" } } From 0611a44dd5521836bc4833e5869d5fc831b3436f Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 9 May 2025 22:17:55 -0400 Subject: [PATCH 020/161] Fix Attr metavariable binding gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_attr_input): Handle more delimeter tokens and the END_OF_FILE token. (Parser::skip_after_end_attribute): Handle the END_OF_FILE token. gcc/testsuite/ChangeLog: * rust/compile/macros/mbe/meta-param.rs: New test. Signed-off-by: Owen Avery --- gcc/rust/parse/rust-parse-impl.h | 5 ++++- gcc/testsuite/rust/compile/macros/mbe/meta-param.rs | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/rust/compile/macros/mbe/meta-param.rs diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index a0af8a3ac19b..3a2fcd214744 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -877,7 +877,10 @@ Parser::parse_attr_input () return attr_input_lit; } break; + case RIGHT_PAREN: case RIGHT_SQUARE: + case RIGHT_CURLY: + case END_OF_FILE: // means AttrInput is missing, which is allowed return nullptr; default: @@ -11911,7 +11914,7 @@ Parser::skip_after_end_attribute () { const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_SQUARE) + while (t->get_id () != RIGHT_SQUARE && t->get_id () != END_OF_FILE) { lexer.skip_token (); t = lexer.peek_token (); diff --git a/gcc/testsuite/rust/compile/macros/mbe/meta-param.rs b/gcc/testsuite/rust/compile/macros/mbe/meta-param.rs new file mode 100644 index 000000000000..ed6e100e5fd0 --- /dev/null +++ b/gcc/testsuite/rust/compile/macros/mbe/meta-param.rs @@ -0,0 +1,7 @@ +macro_rules! foo { + ($x:meta) => {0} +} + +pub fn main() -> i32 { + foo!(Clone) +} From 9a26645ddaae891495c8f0d9b0c6cffca3f7de36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Poulhi=C3=A8s?= Date: Tue, 13 May 2025 21:21:18 +0200 Subject: [PATCH 021/161] gccrs: remove unused file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc/rust/ChangeLog: * Make-lang.in (GRS_OBJS): Remove rust-macro.o. * ast/rust-macro.cc: Removed. Signed-off-by: Marc Poulhiès --- gcc/rust/Make-lang.in | 1 - gcc/rust/ast/rust-macro.cc | 25 ------------------------- 2 files changed, 26 deletions(-) delete mode 100644 gcc/rust/ast/rust-macro.cc diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 94d3365d929e..399271a3bc74 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -123,7 +123,6 @@ GRS_OBJS = \ rust/rust-keyword-values.o \ rust/rust-abi.o \ rust/rust-token-converter.o \ - rust/rust-macro.o \ rust/rust-ast-lower.o \ rust/rust-ast-lower-base.o \ rust/rust-ast-lower-pattern.o \ diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/ast/rust-macro.cc deleted file mode 100644 index 270343872933..000000000000 --- a/gcc/rust/ast/rust-macro.cc +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2020-2025 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 -// . - -#include "rust-macro.h" - -namespace Rust { -namespace AST { - -} // namespace AST -} // namespace Rust From fa6751b22f1c9a4cb53d0870fc585356941ed175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Poulhi=C3=A8s?= Date: Sat, 10 May 2025 20:51:38 +0200 Subject: [PATCH 022/161] gccrs: Reindent using last clang-format configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It changes declaration and switch case indentation to follow GNU coding style. gcc/rust/ChangeLog: * ast/rust-ast-builder-type.cc (ASTTypeBuilder::visit): Reindent. * ast/rust-ast-builder.cc (Builder::new_generic_args): Likewise. * ast/rust-ast-collector.cc (TokenCollector::visit): Likewise. * ast/rust-ast-dump.h (debug): Likewise. * ast/rust-ast-formatting.h (indent_spaces): Likewise. (get_string_in_delims): Likewise. (get_mode_dump_desc): Likewise. (append_attributes): Likewise. (unquote_string): Likewise. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. * ast/rust-ast.cc (Attribute::get_traits_to_derive): Likewise. (UseTreeGlob::as_string): Likewise. (UseTreeList::as_string): Likewise. (AttributeParser::parse_path_meta_item): Likewise. (FormatArgs::set_outer_attrs): Likewise. * ast/rust-ast.h (operator<<): Likewise. * ast/rust-cond-compilation.h: Likewise. * ast/rust-desugar-apit.cc: Likewise. * ast/rust-fmt.h (collect_pieces): Likewise. (clone_pieces): Likewise. * ast/rust-pattern.h (tokenid_to_rangekind): Likewise. * backend/rust-compile-context.cc (Context::type_hasher): Likewise. * backend/rust-compile-expr.cc (CompileExpr::visit): Likewise. * backend/rust-compile-intrinsic.cc (get_identifier): Likewise. (offset_handler): Likewise. (sizeof_handler): Likewise. (transmute_handler): Likewise. (rotate_handler): Likewise. (wrapping_op_handler_inner): Likewise. (op_with_overflow_inner): Likewise. (uninit_handler): Likewise. (move_val_init_handler): Likewise. (assume_handler): Likewise. (discriminant_value_handler): Likewise. (variant_count_handler): Likewise. (prefetch_data_handler): Likewise. (atomic_store_handler_inner): Likewise. (atomic_load_handler_inner): Likewise. (unchecked_op_inner): Likewise. (copy_handler_inner): Likewise. (expect_handler_inner): Likewise. (try_handler_inner): Likewise. * backend/rust-compile-pattern.cc (compile_range_pattern_bound): Likewise. (CompilePatternCheckExpr::visit): Likewise. (CompilePatternBindings::visit): Likewise. (CompilePatternLet::visit): Likewise. * backend/rust-compile-var-decl.h: Likewise. * backend/rust-constexpr.cc (verify_constant): Likewise. (find_array_ctor_elt): Likewise. (array_index_cmp): Likewise. (potential_constant_expression_1): Likewise. (unshare_constructor): Likewise. (maybe_save_constexpr_fundef): Likewise. (returns): Likewise. (breaks): Likewise. (continues): Likewise. (switches): Likewise. (constant_value_1): Likewise. (decl_constant_value): Likewise. (non_const_var_error): Likewise. (eval_constant_expression): Likewise. (constexpr_fn_retval): Likewise. (eval_store_expression): Likewise. (eval_call_expression): Likewise. (eval_binary_expression): Likewise. (get_function_named_in_call): Likewise. (eval_statement_list): Likewise. (extract_string_elt): Likewise. (eval_conditional_expression): Likewise. (eval_bit_field_ref): Likewise. (eval_loop_expr): Likewise. (eval_switch_expr): Likewise. (eval_unary_expression): Likewise. (get_or_insert_ctor_field): Likewise. (eval_and_check_array_index): Likewise. * backend/rust-constexpr.h (maybe_save_constexpr_fundef): Likewise. * backend/rust-mangle-v0.cc (v0_path): Likewise. (v0_complex_type_prefix): Likewise. * backend/rust-mangle.h (legacy_mangle_item): Likewise. (v0_mangle_item): Likewise. * backend/rust-tree.cc (convert_to_void): Likewise. (find_parameter_packs_r): Likewise. (rs_tree_equal): Likewise. (publicly_uniquely_derived_p): Likewise. (instantiation_dependent_expression_p): Likewise. (type_has_nontrivial_copy_init): Likewise. (is_normal_capture_proxy): Likewise. (is_bitfield_expr_with_lowered_type): Likewise. (undeduced_auto_decl): Likewise. (require_deduced_type): Likewise. (gt_pch_nx): Likewise. (lvalue_kind): Likewise. * backend/rust-tree.h (LANG_DECL_MIN_CHECK): Likewise. (LANG_DECL_FN_CHECK): Likewise. (LANG_DECL_NS_CHECK): Likewise. (LANG_DECL_PARM_CHECK): Likewise. (LANG_DECL_DECOMP_CHECK): Likewise. (resort_type_member_vec): Likewise. (convert_to_void): Likewise. (mark_discarded_use): Likewise. (mark_exp_read): Likewise. (mark_use): Likewise. (mark_rvalue_use): Likewise. (mark_lvalue_use): Likewise. (mark_lvalue_use_nonread): Likewise. (convert_from_reference): Likewise. (maybe_warn_nodiscard): Likewise. (expr_loc_or_loc): Likewise. (expr_loc_or_input_loc): Likewise. (get_fndecl_from_callee): Likewise. (pointer_offset_expression): Likewise. (is_empty_class): Likewise. (is_really_empty_class): Likewise. (rs_type_quals): Likewise. (init_modules): Likewise. (lookup_add): Likewise. (ovl_make): Likewise. (struct c_fileinfo): Likewise. (get_fileinfo): Likewise. (cxx_make_type): Likewise. (build_cplus_array_type): Likewise. (comptypes): Likewise. (rs_build_qualified_type_real): Likewise. (vector_targets_convertible_p): Likewise. (get_class_binding_direct): Likewise. (lang_check_failed): Likewise. (check_for_uninitialized_const_var): Likewise. (cp_fold_maybe_rvalue): Likewise. (fold_offsetof): Likewise. (fold_non_dependent_expr): Likewise. (in_immediate_context): Likewise. (cxx_mark_addressable): Likewise. (decl_constant_value): Likewise. (is_class_type): Likewise. (fold_builtin_is_pointer_inverconvertible_with_class): Likewise. (c_common_type_for_mode): Likewise. (next_common_initial_seqence): Likewise. (fold_builtin_is_corresponding_member): Likewise. (maybe_constant_value): Likewise. (rs_walk_subtrees): Likewise. (make_tree_vector): Likewise. (release_tree_vector): Likewise. (location_of): Likewise. (maybe_constant_init): Likewise. (explain_invalid_constexpr_fn): Likewise. (literal_type_p): Likewise. (maybe_constexpr_fn): Likewise. (fold_non_dependent_init): Likewise. * checks/errors/borrowck/polonius/rust-polonius.h (polonius_run): Likewise. (FFIVector__new): Likewise. (FFIVector__new_vec_pair): Likewise. (FFIVector__new_vec_triple): Likewise. (FFIVector__push): Likewise. (FFIVector__push_vec_triple): Likewise. * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Likewise. * checks/errors/borrowck/rust-bir-builder-pattern.cc (PatternBindingBuilder::visit): Likewise. * checks/errors/borrowck/rust-bir-dump.cc (Dump::visit): Likewise. * checks/errors/borrowck/rust-bir-fact-collector.h (points): Likewise. * checks/errors/borrowck/rust-bir-place.h: Likewise. * checks/errors/borrowck/rust-bir-visitor.h: Likewise. * checks/errors/privacy/rust-privacy-check.cc (saw_errors): Likewise. * checks/errors/privacy/rust-privacy-ctx.h (rust_privacy_ctx_test): Likewise. * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::check_for_privacy_violation): Likewise. (PrivacyReporter::check_base_type_privacy): Likewise. (PrivacyReporter::visit): Likewise. * checks/errors/privacy/rust-reachability.cc (ReachabilityVisitor::visit): Likewise. * checks/errors/privacy/rust-visibility-resolver.cc (VisibilityResolver::resolve_visibility): Likewise. * checks/errors/rust-hir-pattern-analysis.cc (Constructor::is_covered_by): Likewise. (PlaceInfo::specialize): Likewise. (WitnessPat::to_string): Likewise. (WitnessMatrix::apply_constructor): Likewise. (lower_pattern): Likewise. (lower_tuple_pattern): Likewise. (lower_struct_pattern): Likewise. * checks/errors/rust-hir-pattern-analysis.h (check_match_usefulness): Likewise. * expand/rust-cfg-strip.cc (CfgStrip::maybe_strip_generic_args): Likewise. * expand/rust-derive-eq.cc (DeriveEq::visit_enum): Likewise. * expand/rust-derive.cc: Likewise. * expand/rust-expand-format-args.cc (expand_format_args): Likewise. * expand/rust-expand-visitor.h (is_derive): Likewise. (is_builtin): Likewise. * expand/rust-macro-builtins-asm.cc (expand_inline_asm_strings): Likewise. * expand/rust-macro-builtins-asm.h (parse_asm): Likewise. (check_identifier): Likewise. (check_and_set): Likewise. (parse_label): Likewise. (parse_llvm_outputs): Likewise. (parse_llvm_inputs): Likewise. (parse_llvm_clobbers): Likewise. (parse_llvm_options): Likewise. * expand/rust-macro-builtins-helpers.h (make_macro_path_str): Likewise. (make_token): Likewise. (make_string): Likewise. (macro_end_token): Likewise. (parse_single_string_literal): Likewise. (source_relative_path): Likewise. (load_file_bytes): Likewise. * expand/rust-macro-expand.cc (MacroExpander::match_fragment): Likewise. (MacroExpander::match_matcher): Likewise. (MacroExpander::match_n_matches): Likewise. * expand/rust-macro-substitute-ctx.cc (SubstituteCtx::substitute_token): Likewise. * expand/rust-proc-macro.h (load_macros): Likewise. (generate_proc_macro_decls_symbol): Likewise. * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_generic_args): Likewise. (ASTLoweringBase::lower_range_pattern_bound): Likewise. * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise. * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit): Likewise. * hir/rust-ast-lower.h (struct_field_name_exists): Likewise. (translate_visibility): Likewise. * hir/rust-hir-dump.cc (Dump::visit): Likewise. * hir/rust-hir-dump.h (debug): Likewise. * hir/tree/rust-hir.cc (UseTreeGlob::as_string): Likewise. (UseTreeList::as_string): Likewise. * lex/rust-lex.cc (Lexer::parse_escape): Likewise. (Lexer::parse_utf8_escape): Likewise. * lex/rust-lex.h (rust_input_source_test): Likewise. * lex/rust-token.cc (RS_TOKEN_KEYWORD_2015): Likewise. * lex/rust-token.h (get_token_description): Likewise. (token_id_to_str): Likewise. (token_id_is_keyword): Likewise. (token_id_keyword_string): Likewise. (get_type_hint_string): Likewise. (nfc_normalize_token_string): Likewise. * metadata/rust-export-metadata.cc (PublicInterface::write_to_path): Likewise. * metadata/rust-import-archive.cc: Likewise. * metadata/rust-imports.h (add_search_path): Likewise. * parse/rust-cfg-parser.h (parse_cfg_option): Likewise. (rust_cfg_parser_test): Likewise. * parse/rust-parse-impl.h (Parser::skip_generics_right_angle): Likewise. (Parser::parse_attr_input): Likewise. (Parser::parse_macro_match): Likewise. (Parser::parse_visibility): Likewise. (Parser::parse_module): Likewise. (Parser::parse_use_tree): Likewise. (Parser::parse_generic_param): Likewise. (Parser::parse_struct): Likewise. (Parser::parse_enum_item): Likewise. (Parser::parse_inherent_impl_item): Likewise. (Parser::parse_external_item): Likewise. (Parser::parse_generic_arg): Likewise. (Parser::parse_type_path_segment): Likewise. (Parser::parse_expr_stmt): Likewise. (Parser::parse_if_expr): Likewise. (Parser::parse_if_let_expr): Likewise. (Parser::parse_type): Likewise. (Parser::parse_for_prefixed_type): Likewise. (Parser::parse_slice_or_array_type): Likewise. (Parser::parse_type_no_bounds): Likewise. (Parser::parse_range_pattern_bound): Likewise. (Parser::parse_pattern_no_alt): Likewise. (Parser::parse_grouped_or_tuple_pattern): Likewise. (Parser::parse_ident_leading_pattern): Likewise. (Parser::parse_tuple_struct_items): Likewise. (Parser::parse_stmt_or_expr): Likewise. (Parser::parse_struct_expr_field): Likewise. (Parser::null_denotation): Likewise. (Parser::left_denotation): Likewise. (Parser::parse_closure_expr_pratt): Likewise. * parse/rust-parse.cc (peculiar_fragment_match_compatible): Likewise. (is_match_compatible): Likewise. * parse/rust-parse.h (extract_module_path): Likewise. (is_match_compatible): Likewise. * resolve/rust-ast-resolve-expr.cc (translate_operand): Likewise. * resolve/rust-ast-resolve-item.cc (flatten_glob): Likewise. (flatten_rebind): Likewise. (flatten_list): Likewise. (flatten): Likewise. * resolve/rust-ast-resolve-item.h (rust_simple_path_resolve_test): Likewise. * resolve/rust-ast-resolve-pattern.cc (PatternDeclaration::visit): Likewise. (resolve_range_pattern_bound): Likewise. * resolve/rust-ast-resolve-type.cc (ResolveRelativeTypePath::go): Likewise. (ResolveTypeToCanonicalPath::visit): Likewise. * resolve/rust-ast-resolve.cc (saw_errors): Likewise. * resolve/rust-early-name-resolver-2.0.cc (Early::finalize_rebind_import): Likewise. * resolve/rust-ice-finalizer.h (funny_ice_text_finalizer): Likewise. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise. * resolve/rust-toplevel-name-resolver-2.0.cc (flatten_glob): Likewise. * rust-backend.h (init): Likewise. (debug): Likewise. (get_identifier_node): Likewise. (wchar_type): Likewise. (get_pointer_size): Likewise. (raw_str_type): Likewise. (integer_type): Likewise. (float_type): Likewise. (pointer_type): Likewise. (reference_type): Likewise. (immutable_type): Likewise. (function_type): Likewise. (function_type_variadic): Likewise. (function_ptr_type): Likewise. (struct_type): Likewise. (union_type): Likewise. (array_type): Likewise. (named_type): Likewise. (type_field_offset): Likewise. (var_expression): Likewise. (float_constant_expression): Likewise. (string_constant_expression): Likewise. (char_constant_expression): Likewise. (wchar_constant_expression): Likewise. (boolean_constant_expression): Likewise. (convert_expression): Likewise. (struct_field_expression): Likewise. (compound_expression): Likewise. (conditional_expression): Likewise. (negation_expression): Likewise. (arithmetic_or_logical_expression): Likewise. (arithmetic_or_logical_expression_checked): Likewise. (comparison_expression): Likewise. (lazy_boolean_expression): Likewise. (constructor_expression): Likewise. (array_constructor_expression): Likewise. (array_initializer): Likewise. (array_index_expression): Likewise. (call_expression): Likewise. (init_statement): Likewise. (assignment_statement): Likewise. (return_statement): Likewise. (if_statement): Likewise. (loop_expression): Likewise. (exit_expression): Likewise. (statement_list): Likewise. (exception_handler_statement): Likewise. (block): Likewise. (block_add_statements): Likewise. (global_variable): Likewise. (global_variable_set_init): Likewise. (local_variable): Likewise. (parameter_variable): Likewise. (static_chain_variable): Likewise. (temporary_variable): Likewise. (label): Likewise. (function): Likewise. (function_defer_statement): Likewise. (function_set_parameters): Likewise. (write_global_definitions): Likewise. (fill_in_fields): Likewise. * rust-diagnostics.cc (expand_format): Likewise. (expand_message): Likewise. (va_constructor): Likewise. * rust-diagnostics.h (RUST_ATTRIBUTE_GCC_DIAG): Likewise. (rust_open_quote): Likewise. (rust_close_quote): Likewise. (rust_debug_loc): Likewise. * rust-gcc.cc (non_zero_size_type): Likewise. * rust-object-export.h (rust_field_alignment): Likewise. (rust_read_export_data): Likewise. (rust_write_export_data): Likewise. * rust-session-manager.cc (saw_errors): Likewise. (rust_get_linemap): Likewise. (validate_crate_name): Likewise. (Session::load_extern_crate): Likewise. * rust-session-manager.h (rust_crate_name_validation_test): Likewise. * rust-system.h (rust_preserve_from_gc): Likewise. (rust_localize_identifier): Likewise. * rust-target.h (rust_add_target_info): Likewise. * typecheck/rust-autoderef.cc: * typecheck/rust-casts.cc (TypeCastRules::cast_rules): Likewise. * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Likewise. (TypeCoercionRules::coerce_unsafe_ptr): Likewise. (TypeCoercionRules::coerce_borrowed_pointer): Likewise. * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): Likewise. (TraitItemReference::is_object_safe): Likewise. * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): Likewise. * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise. (typecheck_inline_asm_operand): Likewise. * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItem::visit): Likewise. (TypeCheckImplItemWithTrait::visit): Likewise. * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): Likewise. * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::visit): Likewise. * typecheck/rust-hir-type-check-type.cc (TypeResolveGenericParam::apply_trait_bounds): Likewise. (ResolveWhereClauseItem::visit): Likewise. * typecheck/rust-hir-type-check.cc (saw_errors): Likewise. (TraitItemReference::get_type_from_fn): Likewise. * typecheck/rust-type-util.h (query_type): Likewise. (types_compatable): Likewise. (unify_site): Likewise. (unify_site_and): Likewise. (coercion_site): Likewise. (try_coercion): Likewise. (cast_site): Likewise. * typecheck/rust-tyty-bounds.cc: * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): Likewise. * typecheck/rust-tyty-cmp.h: * typecheck/rust-tyty-variance-analysis.h (query_field_regions): Likewise. * typecheck/rust-tyty.cc (BaseType::is_unit): Likewise. (BaseType::has_substitutions_defined): Likewise. (BaseType::needs_generic_substitutions): Likewise. (BaseType::get_subst_argument_mappings): Likewise. (InferType::default_type): Likewise. (InferType::apply_primitive_type_hint): Likewise. * typecheck/rust-tyty.h (is_primitive_type_kind): Likewise. * typecheck/rust-unify.cc (UnifyRules::expect_inference_variable): Likewise. (UnifyRules::expect_adt): Likewise. (UnifyRules::expect_str): Likewise. (UnifyRules::expect_reference): Likewise. (UnifyRules::expect_pointer): Likewise. (UnifyRules::expect_param): Likewise. (UnifyRules::expect_array): Likewise. (UnifyRules::expect_slice): Likewise. (UnifyRules::expect_fndef): Likewise. (UnifyRules::expect_fnptr): Likewise. (UnifyRules::expect_tuple): Likewise. (UnifyRules::expect_bool): Likewise. (UnifyRules::expect_char): Likewise. (UnifyRules::expect_int): Likewise. (UnifyRules::expect_uint): Likewise. (UnifyRules::expect_float): Likewise. (UnifyRules::expect_isize): Likewise. (UnifyRules::expect_usize): Likewise. (UnifyRules::expect_never): Likewise. (UnifyRules::expect_placeholder): Likewise. (UnifyRules::expect_projection): Likewise. (UnifyRules::expect_dyn): Likewise. (UnifyRules::expect_closure): Likewise. (UnifyRules::expect_opaque): Likewise. * util/rust-abi.h (get_abi_from_string): Likewise. (get_string_from_abi): Likewise. * util/rust-attributes.cc (check_doc_attribute): Likewise. * util/rust-base62.h (base62_integer): Likewise. * util/rust-dir-owner.h (get_file_subdir): Likewise. * util/rust-edition.h (get_rust_edition): Likewise. * util/rust-punycode.h (encode_punycode): Likewise. (rust_punycode_encode_test): Likewise. * util/rust-token-converter.cc (convert): Likewise. (from_tokenstream): Likewise. * util/rust-token-converter.h (convert): Likewise. (convert_literal): Likewise. * util/rust-unicode.h (is_alphabetic): Likewise. (is_ascii_only): Likewise. (is_numeric): Likewise. (is_nfc_qc_no): Likewise. (is_nfc_qc_maybe): Likewise. (nfc_quick_check): Likewise. (rust_nfc_qc_test): Likewise. (rust_utf8_normalize_test): Likewise. (rust_utf8_property_test): Likewise. * util/rust-unwrap-segment.h (unwrap_segment_node_id): Likewise. libgrust/ChangeLog: * libproc_macro_internal/ffistring.h (FFIString__new): Likewise. (FFIString__drop): Likewise. * libproc_macro_internal/ident.h (Ident__new): Likewise. (Ident__new_raw): Likewise. (Ident__drop): Likewise. (Ident__clone): Likewise. * libproc_macro_internal/literal.h (Literal__from_string): Likewise. * libproc_macro_internal/proc_macro.h (bridge_is_available): Likewise. * libproc_macro_internal/tokenstream.h (TokenStream__new): Likewise. (TokenStream__with_capacity): Likewise. (TokenSream__push): Likewise. (TokenStream__from_string): Likewise. (TokenStream__clone): Likewise. (TokenStream__drop): Likewise. Signed-off-by: Marc Poulhiès --- gcc/rust/ast/rust-ast-builder-type.cc | 9 +- gcc/rust/ast/rust-ast-builder.cc | 18 +- gcc/rust/ast/rust-ast-collector.cc | 48 ++- gcc/rust/ast/rust-ast-dump.h | 6 +- gcc/rust/ast/rust-ast-formatting.h | 15 +- gcc/rust/ast/rust-ast-visitor.cc | 21 +- gcc/rust/ast/rust-ast.cc | 27 +- gcc/rust/ast/rust-ast.h | 3 +- gcc/rust/ast/rust-cond-compilation.h | 4 +- gcc/rust/ast/rust-desugar-apit.cc | 12 +- gcc/rust/ast/rust-fmt.h | 7 +- gcc/rust/ast/rust-pattern.h | 3 +- gcc/rust/backend/rust-compile-context.cc | 15 +- gcc/rust/backend/rust-compile-expr.cc | 6 +- gcc/rust/backend/rust-compile-intrinsic.cc | 66 ++-- gcc/rust/backend/rust-compile-pattern.cc | 54 ++-- gcc/rust/backend/rust-compile-var-decl.h | 3 +- gcc/rust/backend/rust-constexpr.cc | 190 ++++++------ gcc/rust/backend/rust-constexpr.h | 3 +- gcc/rust/backend/rust-mangle-v0.cc | 18 +- gcc/rust/backend/rust-mangle.h | 11 +- gcc/rust/backend/rust-tree.cc | 82 +++-- gcc/rust/backend/rust-tree.h | 183 +++++------ .../errors/borrowck/polonius/rust-polonius.h | 20 +- .../borrowck/rust-bir-builder-expr-stmt.cc | 6 +- .../borrowck/rust-bir-builder-pattern.cc | 21 +- .../checks/errors/borrowck/rust-bir-dump.cc | 3 +- .../errors/borrowck/rust-bir-fact-collector.h | 27 +- .../checks/errors/borrowck/rust-bir-place.h | 8 +- .../checks/errors/borrowck/rust-bir-visitor.h | 2 +- .../errors/privacy/rust-privacy-check.cc | 3 +- .../checks/errors/privacy/rust-privacy-ctx.h | 3 +- .../errors/privacy/rust-privacy-reporter.cc | 12 +- .../errors/privacy/rust-reachability.cc | 6 +- .../privacy/rust-visibility-resolver.cc | 3 +- .../errors/rust-hir-pattern-analysis.cc | 126 +++++--- .../checks/errors/rust-hir-pattern-analysis.h | 6 +- gcc/rust/expand/rust-cfg-strip.cc | 6 +- gcc/rust/expand/rust-derive-eq.cc | 6 +- gcc/rust/expand/rust-derive.cc | 9 +- gcc/rust/expand/rust-expand-format-args.cc | 6 +- gcc/rust/expand/rust-expand-visitor.h | 6 +- gcc/rust/expand/rust-macro-builtins-asm.cc | 3 +- gcc/rust/expand/rust-macro-builtins-asm.h | 32 +- gcc/rust/expand/rust-macro-builtins-helpers.h | 35 +-- gcc/rust/expand/rust-macro-expand.cc | 45 ++- gcc/rust/expand/rust-macro-substitute-ctx.cc | 3 +- gcc/rust/expand/rust-proc-macro.h | 6 +- gcc/rust/hir/rust-ast-lower-base.cc | 15 +- gcc/rust/hir/rust-ast-lower-item.cc | 6 +- gcc/rust/hir/rust-ast-lower-pattern.cc | 21 +- gcc/rust/hir/rust-ast-lower.h | 8 +- gcc/rust/hir/rust-hir-dump.cc | 6 +- gcc/rust/hir/rust-hir-dump.h | 3 +- gcc/rust/hir/tree/rust-hir.cc | 6 +- gcc/rust/lex/rust-lex.cc | 9 +- gcc/rust/lex/rust-lex.h | 3 +- gcc/rust/lex/rust-token.cc | 3 +- gcc/rust/lex/rust-token.h | 19 +- gcc/rust/metadata/rust-export-metadata.cc | 3 +- gcc/rust/metadata/rust-import-archive.cc | 2 +- gcc/rust/metadata/rust-imports.h | 3 +- gcc/rust/parse/rust-cfg-parser.h | 7 +- gcc/rust/parse/rust-parse-impl.h | 285 +++++++++++------- gcc/rust/parse/rust-parse.cc | 31 +- gcc/rust/parse/rust-parse.h | 11 +- gcc/rust/resolve/rust-ast-resolve-expr.cc | 21 +- gcc/rust/resolve/rust-ast-resolve-item.cc | 21 +- gcc/rust/resolve/rust-ast-resolve-item.h | 3 +- gcc/rust/resolve/rust-ast-resolve-pattern.cc | 27 +- gcc/rust/resolve/rust-ast-resolve-type.cc | 9 +- gcc/rust/resolve/rust-ast-resolve.cc | 3 +- .../resolve/rust-early-name-resolver-2.0.cc | 3 +- gcc/rust/resolve/rust-ice-finalizer.h | 7 +- .../resolve/rust-late-name-resolver-2.0.cc | 3 +- .../rust-toplevel-name-resolver-2.0.cc | 22 +- gcc/rust/rust-backend.h | 257 ++++++---------- gcc/rust/rust-diagnostics.cc | 49 +-- gcc/rust/rust-diagnostics.h | 13 +- gcc/rust/rust-gcc.cc | 3 +- gcc/rust/rust-object-export.h | 13 +- gcc/rust/rust-session-manager.cc | 24 +- gcc/rust/rust-session-manager.h | 3 +- gcc/rust/rust-system.h | 6 +- gcc/rust/rust-target.h | 3 +- gcc/rust/typecheck/rust-autoderef.cc | 3 +- gcc/rust/typecheck/rust-casts.cc | 27 +- gcc/rust/typecheck/rust-coercion.cc | 24 +- gcc/rust/typecheck/rust-hir-trait-resolve.cc | 9 +- .../typecheck/rust-hir-type-check-base.cc | 30 +- .../typecheck/rust-hir-type-check-expr.cc | 42 ++- .../typecheck/rust-hir-type-check-implitem.cc | 20 +- .../typecheck/rust-hir-type-check-pattern.cc | 33 +- .../typecheck/rust-hir-type-check-struct.cc | 3 +- .../typecheck/rust-hir-type-check-type.cc | 15 +- gcc/rust/typecheck/rust-hir-type-check.cc | 6 +- gcc/rust/typecheck/rust-type-util.h | 39 ++- gcc/rust/typecheck/rust-tyty-bounds.cc | 6 +- gcc/rust/typecheck/rust-tyty-call.cc | 15 +- gcc/rust/typecheck/rust-tyty-cmp.h | 6 +- .../typecheck/rust-tyty-variance-analysis.h | 7 +- gcc/rust/typecheck/rust-tyty.cc | 57 ++-- gcc/rust/typecheck/rust-tyty.h | 7 +- gcc/rust/typecheck/rust-unify.cc | 135 ++++++--- gcc/rust/util/rust-abi.h | 6 +- gcc/rust/util/rust-attributes.cc | 3 +- gcc/rust/util/rust-base62.h | 3 +- gcc/rust/util/rust-dir-owner.h | 3 +- gcc/rust/util/rust-edition.h | 3 +- gcc/rust/util/rust-punycode.h | 6 +- gcc/rust/util/rust-token-converter.cc | 8 +- gcc/rust/util/rust-token-converter.h | 9 +- gcc/rust/util/rust-unicode.h | 27 +- gcc/rust/util/rust-unwrap-segment.h | 9 +- libgrust/libproc_macro_internal/ffistring.h | 6 +- libgrust/libproc_macro_internal/ident.h | 12 +- libgrust/libproc_macro_internal/literal.h | 3 +- libgrust/libproc_macro_internal/proc_macro.h | 3 +- libgrust/libproc_macro_internal/tokenstream.h | 18 +- 119 files changed, 1503 insertions(+), 1238 deletions(-) diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc index 13126b440571..7f8571ac89f1 100644 --- a/gcc/rust/ast/rust-ast-builder-type.cc +++ b/gcc/rust/ast/rust-ast-builder-type.cc @@ -62,7 +62,8 @@ ASTTypeBuilder::visit (TypePath &path) { switch (seg->get_type ()) { - case TypePathSegment::REG: { + case TypePathSegment::REG: + { const TypePathSegment &segment = (const TypePathSegment &) (*seg.get ()); TypePathSegment *s @@ -74,7 +75,8 @@ ASTTypeBuilder::visit (TypePath &path) } break; - case TypePathSegment::GENERIC: { + case TypePathSegment::GENERIC: + { TypePathSegmentGeneric &generic = (TypePathSegmentGeneric &) (*seg.get ()); @@ -89,7 +91,8 @@ ASTTypeBuilder::visit (TypePath &path) } break; - case TypePathSegment::FUNCTION: { + case TypePathSegment::FUNCTION: + { rust_unreachable (); // TODO // const TypePathSegmentFunction &fn diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index ef0f92f14ce0..fbc8f273d812 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -574,7 +574,8 @@ Builder::new_type_param ( { switch (b->get_bound_type ()) { - case TypeParamBound::TypeParamBoundType::TRAIT: { + case TypeParamBound::TypeParamBoundType::TRAIT: + { const TraitBound &tb = (const TraitBound &) *b.get (); const TypePath &path = tb.get_type_path (); @@ -599,7 +600,8 @@ Builder::new_type_param ( { switch (seg->get_type ()) { - case TypePathSegment::REG: { + case TypePathSegment::REG: + { const TypePathSegment &segment = (const TypePathSegment &) (*seg.get ()); TypePathSegment *s = new TypePathSegment ( @@ -611,7 +613,8 @@ Builder::new_type_param ( } break; - case TypePathSegment::GENERIC: { + case TypePathSegment::GENERIC: + { TypePathSegmentGeneric &generic = (TypePathSegmentGeneric &) (*seg.get ()); @@ -625,7 +628,8 @@ Builder::new_type_param ( } break; - case TypePathSegment::FUNCTION: { + case TypePathSegment::FUNCTION: + { rust_unreachable (); // TODO // const TypePathSegmentFunction &fn @@ -647,7 +651,8 @@ Builder::new_type_param ( } break; - case TypeParamBound::TypeParamBoundType::LIFETIME: { + case TypeParamBound::TypeParamBoundType::LIFETIME: + { const Lifetime &l = (const Lifetime &) *b.get (); auto bl = new Lifetime (l.get_lifetime_type (), @@ -700,7 +705,8 @@ Builder::new_generic_args (GenericArgs &args) { switch (arg.get_kind ()) { - case GenericArg::Kind::Type: { + case GenericArg::Kind::Type: + { std::unique_ptr ty = new_type (arg.get_type ()); GenericArg arg = GenericArg::create_type (std::move (ty)); } diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 538c6a411d1c..cab763964154 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -154,20 +154,24 @@ TokenCollector::visit (Attribute &attrib) { switch (attrib.get_attr_input ().get_attr_input_type ()) { - case AST::AttrInput::AttrInputType::LITERAL: { + case AST::AttrInput::AttrInputType::LITERAL: + { visit (static_cast (attrib.get_attr_input ())); break; } - case AST::AttrInput::AttrInputType::MACRO: { + case AST::AttrInput::AttrInputType::MACRO: + { visit (static_cast (attrib.get_attr_input ())); break; } - case AST::AttrInput::AttrInputType::META_ITEM: { + case AST::AttrInput::AttrInputType::META_ITEM: + { visit (static_cast ( attrib.get_attr_input ())); break; } - case AST::AttrInput::AttrInputType::TOKEN_TREE: { + case AST::AttrInput::AttrInputType::TOKEN_TREE: + { visit (static_cast (attrib.get_attr_input ())); break; } @@ -634,7 +638,8 @@ TokenCollector::visit (GenericArg &arg) case GenericArg::Kind::Type: visit (arg.get_type ()); break; - case GenericArg::Kind::Either: { + case GenericArg::Kind::Either: + { auto path = arg.get_path (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path))); } @@ -789,7 +794,8 @@ TokenCollector::visit (Literal &lit, location_t locus) push (Rust::Token::make_float (locus, std::move (value), lit.get_type_hint ())); break; - case Literal::LitType::BOOL: { + case Literal::LitType::BOOL: + { if (value == Values::Keywords::FALSE_LITERAL) push (Rust::Token::make (FALSE_LITERAL, locus)); else if (value == Values::Keywords::TRUE_LITERAL) @@ -1534,33 +1540,40 @@ TokenCollector::visit (InlineAsm &expr) using RegisterType = AST::InlineAsmOperand::RegisterType; switch (operand.get_register_type ()) { - case RegisterType::In: { + case RegisterType::In: + { visit (operand.get_in ().expr); break; } - case RegisterType::Out: { + case RegisterType::Out: + { visit (operand.get_out ().expr); break; } - case RegisterType::InOut: { + case RegisterType::InOut: + { visit (operand.get_in_out ().expr); break; } - case RegisterType::SplitInOut: { + case RegisterType::SplitInOut: + { auto split = operand.get_split_in_out (); visit (split.in_expr); visit (split.out_expr); break; } - case RegisterType::Const: { + case RegisterType::Const: + { visit (operand.get_const ().anon_const.expr); break; } - case RegisterType::Sym: { + case RegisterType::Sym: + { visit (operand.get_sym ().expr); break; } - case RegisterType::Label: { + case RegisterType::Label: + { visit (operand.get_label ().expr); break; } @@ -1776,7 +1789,8 @@ TokenCollector::visit (UseTreeGlob &use_tree) { switch (use_tree.get_glob_type ()) { - case UseTreeGlob::PathType::PATH_PREFIXED: { + case UseTreeGlob::PathType::PATH_PREFIXED: + { auto path = use_tree.get_path (); visit (path); push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); @@ -1796,7 +1810,8 @@ TokenCollector::visit (UseTreeList &use_tree) { switch (use_tree.get_path_type ()) { - case UseTreeList::PathType::PATH_PREFIXED: { + case UseTreeList::PathType::PATH_PREFIXED: + { auto path = use_tree.get_path (); visit (path); push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); @@ -1824,7 +1839,8 @@ TokenCollector::visit (UseTreeRebind &use_tree) visit (path); switch (use_tree.get_new_bind_type ()) { - case UseTreeRebind::NewBindType::IDENTIFIER: { + case UseTreeRebind::NewBindType::IDENTIFIER: + { push (Rust::Token::make (AS, UNDEF_LOCATION)); auto id = use_tree.get_identifier ().as_string (); push ( diff --git a/gcc/rust/ast/rust-ast-dump.h b/gcc/rust/ast/rust-ast-dump.h index 02c99b7ae1ec..0c3875e28233 100644 --- a/gcc/rust/ast/rust-ast-dump.h +++ b/gcc/rust/ast/rust-ast-dump.h @@ -49,7 +49,8 @@ class Dump { switch (item.get_kind ()) { - case AST::CollectItem::Kind::Token: { + case AST::CollectItem::Kind::Token: + { TokenPtr current = item.get_token (); if (require_spacing (previous, current)) stream << " "; @@ -90,7 +91,6 @@ class Dump } // namespace Rust // In the global namespace to make it easier to call from debugger -void -debug (Rust::AST::Visitable &v); +void debug (Rust::AST::Visitable &v); #endif // !RUST_AST_DUMP_H diff --git a/gcc/rust/ast/rust-ast-formatting.h b/gcc/rust/ast/rust-ast-formatting.h index 3dfabbcccc60..aace93f7fae8 100644 --- a/gcc/rust/ast/rust-ast-formatting.h +++ b/gcc/rust/ast/rust-ast-formatting.h @@ -35,23 +35,18 @@ enum AttrMode INNER }; -std::string -indent_spaces (enum indent_mode mode); +std::string indent_spaces (enum indent_mode mode); // Gets a string in a certain delim type. -std::string -get_string_in_delims (std::string str_input, DelimType delim_type); +std::string get_string_in_delims (std::string str_input, DelimType delim_type); -std::string -get_mode_dump_desc (AttrMode mode); +std::string get_mode_dump_desc (AttrMode mode); // Adds lines below adding attributes -std::string -append_attributes (std::vector attrs, AttrMode mode); +std::string append_attributes (std::vector attrs, AttrMode mode); // Removes the beginning and end quotes of a quoted string. -std::string -unquote_string (std::string input); +std::string unquote_string (std::string input); } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 3dfcf5ace025..8c1d9ff61356 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -680,33 +680,40 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr) { switch (operand.get_register_type ()) { - case RegisterType::In: { + case RegisterType::In: + { visit (operand.get_in ().expr); break; } - case RegisterType::Out: { + case RegisterType::Out: + { visit (operand.get_out ().expr); break; } - case RegisterType::InOut: { + case RegisterType::InOut: + { visit (operand.get_in_out ().expr); break; } - case RegisterType::SplitInOut: { + case RegisterType::SplitInOut: + { auto split = operand.get_split_in_out (); visit (split.in_expr); visit (split.out_expr); break; } - case RegisterType::Const: { + case RegisterType::Const: + { visit (operand.get_const ().anon_const.expr); break; } - case RegisterType::Sym: { + case RegisterType::Sym: + { visit (operand.get_sym ().expr); break; } - case RegisterType::Label: { + case RegisterType::Label: + { visit (operand.get_label ().expr); break; } diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index d921353bf6ab..86e700091f36 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -249,27 +249,31 @@ Attribute::get_traits_to_derive () auto &input = get_attr_input (); switch (input.get_attr_input_type ()) { - case AST::AttrInput::META_ITEM: { + case AST::AttrInput::META_ITEM: + { auto &meta = static_cast (input); for (auto ¤t : meta.get_items ()) { // HACK: Find a better way to achieve the downcast. switch (current->get_kind ()) { - case AST::MetaItemInner::Kind::MetaItem: { + case AST::MetaItemInner::Kind::MetaItem: + { // Let raw pointer go out of scope without freeing, it doesn't // own the data anyway auto meta_item = static_cast (current.get ()); switch (meta_item->get_item_kind ()) { - case AST::MetaItem::ItemKind::Path: { + case AST::MetaItem::ItemKind::Path: + { auto path = static_cast (meta_item); result.push_back (path->get_path ()); } break; - case AST::MetaItem::ItemKind::Word: { + case AST::MetaItem::ItemKind::Word: + { auto word = static_cast (meta_item); // Convert current word to path current = std::make_unique ( @@ -782,7 +786,8 @@ UseTreeGlob::as_string () const return "*"; case GLOBAL: return "::*"; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { std::string path_str = path.as_string (); return path_str + "::*"; } @@ -805,7 +810,8 @@ UseTreeList::as_string () const case GLOBAL: path_str = "::{"; break; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { path_str = path.as_string () + "::{"; break; } @@ -3653,14 +3659,16 @@ AttributeParser::parse_path_meta_item () switch (peek_token ()->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { std::vector> meta_items = parse_meta_item_seq (); return std::unique_ptr ( new MetaItemSeq (std::move (path), std::move (meta_items))); } - case EQUAL: { + case EQUAL: + { skip_token (); location_t locus = peek_token ()->get_locus (); @@ -5047,7 +5055,8 @@ FormatArgs::get_outer_attrs () rust_unreachable (); } -void FormatArgs::set_outer_attrs (std::vector) +void +FormatArgs::set_outer_attrs (std::vector) { rust_unreachable (); } diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index aa6ad5066aa1..5ce92231434d 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -67,8 +67,7 @@ class Identifier location_t loc; }; -std::ostream & -operator<< (std::ostream &os, Identifier const &i); +std::ostream &operator<< (std::ostream &os, Identifier const &i); namespace AST { // foward decl: ast visitor diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h index 610b9046f455..56a5646704a8 100644 --- a/gcc/rust/ast/rust-cond-compilation.h +++ b/gcc/rust/ast/rust-cond-compilation.h @@ -42,8 +42,8 @@ class ConfigurationPredicate protected: // Clone function impl to be overriden in base classes - virtual ConfigurationPredicate * - clone_configuration_predicate_impl () const = 0; + virtual ConfigurationPredicate *clone_configuration_predicate_impl () const + = 0; }; // A configuration option - true if option is set, false if option is not set. diff --git a/gcc/rust/ast/rust-desugar-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc index 5b9486ea6714..bca14eef1eab 100644 --- a/gcc/rust/ast/rust-desugar-apit.cc +++ b/gcc/rust/ast/rust-desugar-apit.cc @@ -297,7 +297,8 @@ class ApitBoundProcessor { switch (implicit_generic->get_kind ()) { - case GenericParam::Kind::Type: { + case GenericParam::Kind::Type: + { TypeParam &p = *static_cast (implicit_generic.get ()); @@ -326,7 +327,8 @@ class ApitBoundProcessor auto &tb = bounds[i]; switch (tb->get_bound_type ()) { - case TypeParamBound::TypeParamBoundType::TRAIT: { + case TypeParamBound::TypeParamBoundType::TRAIT: + { TraitBound &ttb = *static_cast (tb.get ()); TypePath &path = ttb.get_type_path (); bool deusgared = process_type_path (p, ttb, path); @@ -350,7 +352,8 @@ class ApitBoundProcessor { switch (segment->get_type ()) { - case TypePathSegment::SegmentType::GENERIC: { + case TypePathSegment::SegmentType::GENERIC: + { TypePathSegmentGeneric &seg = *static_cast (segment.get ()); desugared |= process_generic_segment (p, parent, path, seg); @@ -397,7 +400,8 @@ class ApitBoundProcessor { switch (implicit_generic->get_kind ()) { - case GenericParam::Kind::Type: { + case GenericParam::Kind::Type: + { TypeParam &tp = *static_cast (implicit_generic.get ()); diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h index a54faec6381a..3722db291ab8 100644 --- a/gcc/rust/ast/rust-fmt.h +++ b/gcc/rust/ast/rust-fmt.h @@ -266,11 +266,10 @@ enum ParseMode extern "C" { -FormatArgsHandle -collect_pieces (const char *input, bool append_newline, ParseMode parse_mode); +FormatArgsHandle collect_pieces (const char *input, bool append_newline, + ParseMode parse_mode); -FormatArgsHandle -clone_pieces (const FormatArgsHandle &); +FormatArgsHandle clone_pieces (const FormatArgsHandle &); void destroy_pieces (FormatArgsHandle); diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 69dbd98a1d32..e6cd8f1eb047 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -375,8 +375,7 @@ enum class RangeKind EXCLUDED, }; -RangeKind -tokenid_to_rangekind (TokenId id); +RangeKind tokenid_to_rangekind (TokenId id); // AST node for matching within a certain range (range pattern) class RangePattern : public Pattern { diff --git a/gcc/rust/backend/rust-compile-context.cc b/gcc/rust/backend/rust-compile-context.cc index 86f089440ac0..284a5aa4ca7c 100644 --- a/gcc/rust/backend/rust-compile-context.cc +++ b/gcc/rust/backend/rust-compile-context.cc @@ -70,7 +70,8 @@ Context::type_hasher (tree type) hstate.add_object (TYPE_HASH (TYPE_OFFSET_BASETYPE (type))); break; - case ARRAY_TYPE: { + case ARRAY_TYPE: + { if (TYPE_DOMAIN (type)) hstate.add_object (TYPE_HASH (TYPE_DOMAIN (type))); if (!AGGREGATE_TYPE_P (TREE_TYPE (type))) @@ -81,7 +82,8 @@ Context::type_hasher (tree type) } break; - case INTEGER_TYPE: { + case INTEGER_TYPE: + { tree t = TYPE_MAX_VALUE (type); if (!t) t = TYPE_MIN_VALUE (type); @@ -91,7 +93,8 @@ Context::type_hasher (tree type) } case REAL_TYPE: - case FIXED_POINT_TYPE: { + case FIXED_POINT_TYPE: + { unsigned prec = TYPE_PRECISION (type); hstate.add_object (prec); break; @@ -103,7 +106,8 @@ Context::type_hasher (tree type) case RECORD_TYPE: case UNION_TYPE: - case QUAL_UNION_TYPE: { + case QUAL_UNION_TYPE: + { for (tree t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t)) { hashval_t name_hash = IDENTIFIER_HASH_VALUE (DECL_NAME (t)); @@ -118,7 +122,8 @@ Context::type_hasher (tree type) break; case REFERENCE_TYPE: - case POINTER_TYPE: { + case POINTER_TYPE: + { hashval_t type_hash = type_hasher (TREE_TYPE (type)); hstate.add_object (type_hash); } diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index dd3420f9f2fa..cace059f7426 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -1883,7 +1883,8 @@ CompileExpr::visit (HIR::ArrayExpr &expr) HIR::ArrayElems &elements = expr.get_internal_elements (); switch (elements.get_array_expr_type ()) { - case HIR::ArrayElems::ArrayExprType::VALUES: { + case HIR::ArrayElems::ArrayExprType::VALUES: + { HIR::ArrayElemsValues &elems = static_cast (elements); translated @@ -2032,7 +2033,8 @@ HIRCompileBase::resolve_adjustements ( return error_mark_node; case Resolver::Adjustment::AdjustmentType::IMM_REF: - case Resolver::Adjustment::AdjustmentType::MUT_REF: { + case Resolver::Adjustment::AdjustmentType::MUT_REF: + { if (!RS_DST_FLAG (TREE_TYPE (e))) { e = address_expression (e, locus); diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index 4888e23ed1ef..7627620c4713 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -32,8 +32,7 @@ // declaration taken from "stringpool.h" // the get_identifier macro causes compilation issues -extern tree -get_identifier (const char *); +extern tree get_identifier (const char *); namespace Rust { namespace Compile { @@ -70,28 +69,19 @@ check_for_basic_integer_type (const std::string &intrinsic_str, return is_basic_integer; } -static tree -offset_handler (Context *ctx, TyTy::FnType *fntype); -static tree -sizeof_handler (Context *ctx, TyTy::FnType *fntype); -static tree -transmute_handler (Context *ctx, TyTy::FnType *fntype); -static tree -rotate_handler (Context *ctx, TyTy::FnType *fntype, tree_code op); -static tree -wrapping_op_handler_inner (Context *ctx, TyTy::FnType *fntype, tree_code op); -static tree -op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, tree_code op); -static tree -uninit_handler (Context *ctx, TyTy::FnType *fntype); -static tree -move_val_init_handler (Context *ctx, TyTy::FnType *fntype); -static tree -assume_handler (Context *ctx, TyTy::FnType *fntype); -static tree -discriminant_value_handler (Context *ctx, TyTy::FnType *fntype); -static tree -variant_count_handler (Context *ctx, TyTy::FnType *fntype); +static tree offset_handler (Context *ctx, TyTy::FnType *fntype); +static tree sizeof_handler (Context *ctx, TyTy::FnType *fntype); +static tree transmute_handler (Context *ctx, TyTy::FnType *fntype); +static tree rotate_handler (Context *ctx, TyTy::FnType *fntype, tree_code op); +static tree wrapping_op_handler_inner (Context *ctx, TyTy::FnType *fntype, + tree_code op); +static tree op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, + tree_code op); +static tree uninit_handler (Context *ctx, TyTy::FnType *fntype); +static tree move_val_init_handler (Context *ctx, TyTy::FnType *fntype); +static tree assume_handler (Context *ctx, TyTy::FnType *fntype); +static tree discriminant_value_handler (Context *ctx, TyTy::FnType *fntype); +static tree variant_count_handler (Context *ctx, TyTy::FnType *fntype); enum class Prefetch { @@ -99,8 +89,8 @@ enum class Prefetch Write }; -static tree -prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind); +static tree prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, + Prefetch kind); static inline tree rotate_left_handler (Context *ctx, TyTy::FnType *fntype) @@ -140,10 +130,10 @@ prefetch_write_data (Context *ctx, TyTy::FnType *fntype) return prefetch_data_handler (ctx, fntype, Prefetch::Write); } -static tree -atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering); -static tree -atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering); +static tree atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, + int ordering); +static tree atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, + int ordering); static inline std::function atomic_store_handler (int ordering) @@ -161,8 +151,8 @@ atomic_load_handler (int ordering) }; } -static inline tree -unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, tree_code op); +static inline tree unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, + tree_code op); const static std::function unchecked_op_handler (tree_code op) @@ -172,8 +162,8 @@ unchecked_op_handler (tree_code op) }; } -static inline tree -copy_handler_inner (Context *ctx, TyTy::FnType *fntype, bool overlaps); +static inline tree copy_handler_inner (Context *ctx, TyTy::FnType *fntype, + bool overlaps); const static std::function copy_handler (bool overlaps) @@ -183,8 +173,8 @@ copy_handler (bool overlaps) }; } -static inline tree -expect_handler_inner (Context *ctx, TyTy::FnType *fntype, bool likely); +static inline tree expect_handler_inner (Context *ctx, TyTy::FnType *fntype, + bool likely); const static std::function expect_handler (bool likely) @@ -194,8 +184,8 @@ expect_handler (bool likely) }; } -static tree -try_handler_inner (Context *ctx, TyTy::FnType *fntype, bool is_new_api); +static tree try_handler_inner (Context *ctx, TyTy::FnType *fntype, + bool is_new_api); const static std::function try_handler (bool is_new_api) diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index afde2a61f82d..7b937c766e2a 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -112,7 +112,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound, tree result = NULL_TREE; switch (bound.get_bound_type ()) { - case HIR::RangePatternBound::RangePatternBoundType::LITERAL: { + case HIR::RangePatternBound::RangePatternBoundType::LITERAL: + { auto &ref = static_cast (bound); HIR::LiteralExpr litexpr (mappings, ref.get_literal (), locus, @@ -122,7 +123,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound, } break; - case HIR::RangePatternBound::RangePatternBoundType::PATH: { + case HIR::RangePatternBound::RangePatternBoundType::PATH: + { auto &ref = static_cast (bound); result = ResolvePathRef::Compile (ref.get_path (), ctx); @@ -132,7 +134,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound, } break; - case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: { + case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: + { auto &ref = static_cast (bound); result = ResolvePathRef::Compile (ref.get_qualified_path (), ctx); @@ -261,13 +264,15 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) { switch (field->get_item_type ()) { - case HIR::StructPatternField::ItemType::TUPLE_PAT: { + case HIR::StructPatternField::ItemType::TUPLE_PAT: + { // TODO rust_unreachable (); } break; - case HIR::StructPatternField::ItemType::IDENT_PAT: { + case HIR::StructPatternField::ItemType::IDENT_PAT: + { HIR::StructPatternFieldIdentPat &ident = static_cast (*field.get ()); @@ -289,7 +294,8 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) } break; - case HIR::StructPatternField::ItemType::IDENT: { + case HIR::StructPatternField::ItemType::IDENT: + { // ident pattern always matches - do nothing } break; @@ -348,13 +354,15 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern) HIR::TupleStructItems &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: { + case HIR::TupleStructItems::RANGED: + { // TODO rust_unreachable (); } break; - case HIR::TupleStructItems::MULTIPLE: { + case HIR::TupleStructItems::MULTIPLE: + { HIR::TupleStructItemsNoRange &items_no_range = static_cast (items); @@ -396,13 +404,15 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::RANGED: { + case HIR::TuplePatternItems::RANGED: + { // TODO gcc_unreachable (); } break; - case HIR::TuplePatternItems::MULTIPLE: { + case HIR::TuplePatternItems::MULTIPLE: + { auto &items = static_cast ( pattern.get_items ()); size_t tuple_field_index = 0; @@ -459,13 +469,15 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) HIR::TupleStructItems &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: { + case HIR::TupleStructItems::RANGED: + { // TODO rust_unreachable (); } break; - case HIR::TupleStructItems::MULTIPLE: { + case HIR::TupleStructItems::MULTIPLE: + { HIR::TupleStructItemsNoRange &items_no_range = static_cast (items); @@ -666,7 +678,8 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::RANGED: { + case HIR::TuplePatternItems::ItemType::RANGED: + { size_t tuple_idx = 0; auto &items = static_cast (pattern.get_items ()); @@ -709,7 +722,8 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) return; } - case HIR::TuplePatternItems::ItemType::MULTIPLE: { + case HIR::TuplePatternItems::ItemType::MULTIPLE: + { size_t tuple_idx = 0; auto &items = static_cast ( pattern.get_items ()); @@ -730,7 +744,8 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) return; } - default: { + default: + { rust_unreachable (); } } @@ -790,7 +805,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::RANGED: { + case HIR::TuplePatternItems::ItemType::RANGED: + { size_t tuple_idx = 0; auto &items = static_cast (pattern.get_items ()); @@ -834,7 +850,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) return; } - case HIR::TuplePatternItems::ItemType::MULTIPLE: { + case HIR::TuplePatternItems::ItemType::MULTIPLE: + { size_t tuple_idx = 0; auto &items = static_cast ( pattern.get_items ()); @@ -856,7 +873,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) return; } - default: { + default: + { rust_unreachable (); } } diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index 4c46a7b17d6d..5c6d1459c39b 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -70,7 +70,8 @@ class CompileVarDecl : public HIRCompileBase, public HIR::HIRPatternVisitor { switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::MULTIPLE: { + case HIR::TuplePatternItems::ItemType::MULTIPLE: + { rust_assert (TREE_CODE (translated_type) == RECORD_TYPE); auto &items = static_cast ( pattern.get_items ()); diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index 0ed56c71ad30..d524d09f88ec 100644 --- a/gcc/rust/backend/rust-constexpr.cc +++ b/gcc/rust/backend/rust-constexpr.cc @@ -68,32 +68,24 @@ literal_type_p (tree t) return false; } -static bool -verify_constant (tree, bool, bool *, bool *); - -static HOST_WIDE_INT -find_array_ctor_elt (tree ary, tree dindex, bool insert = false); -static int -array_index_cmp (tree key, tree index); -static bool -potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, - tsubst_flags_t flags, tree *jump_target); -bool -potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, - tsubst_flags_t flags); -tree -unshare_constructor (tree t MEM_STAT_DECL); -void -maybe_save_constexpr_fundef (tree fun); - -static bool -returns (tree *jump_target); -static bool -breaks (tree *jump_target); -static bool -continues (tree *jump_target); -static bool -switches (tree *jump_target); +static bool verify_constant (tree, bool, bool *, bool *); + +static HOST_WIDE_INT find_array_ctor_elt (tree ary, tree dindex, + bool insert = false); +static int array_index_cmp (tree key, tree index); +static bool potential_constant_expression_1 (tree t, bool want_rval, + bool strict, bool now, + tsubst_flags_t flags, + tree *jump_target); +bool potential_constant_expression_1 (tree t, bool want_rval, bool strict, + bool now, tsubst_flags_t flags); +tree unshare_constructor (tree t MEM_STAT_DECL); +void maybe_save_constexpr_fundef (tree fun); + +static bool returns (tree *jump_target); +static bool breaks (tree *jump_target); +static bool continues (tree *jump_target); +static bool switches (tree *jump_target); struct constexpr_global_ctx { @@ -463,60 +455,52 @@ save_fundef_copy (tree fun, tree copy) *slot = copy; } -static tree -constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p, - bool unshare_p); -tree -decl_constant_value (tree decl, bool unshare_p); +static tree constant_value_1 (tree decl, bool strict_p, + bool return_aggregate_cst_ok_p, bool unshare_p); +tree decl_constant_value (tree decl, bool unshare_p); -static void -non_const_var_error (location_t loc, tree r); +static void non_const_var_error (location_t loc, tree r); -static tree -eval_constant_expression (const constexpr_ctx *ctx, tree, bool, bool *, bool *, - tree * = NULL); +static tree eval_constant_expression (const constexpr_ctx *ctx, tree, bool, + bool *, bool *, tree * = NULL); -static tree -constexpr_fn_retval (const constexpr_ctx *ctx, tree r); +static tree constexpr_fn_retval (const constexpr_ctx *ctx, tree r); -static tree -eval_store_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *); +static tree eval_store_expression (const constexpr_ctx *ctx, tree r, bool, + bool *, bool *); -static tree -eval_call_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *); +static tree eval_call_expression (const constexpr_ctx *ctx, tree r, bool, + bool *, bool *); -static tree -eval_binary_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *); +static tree eval_binary_expression (const constexpr_ctx *ctx, tree r, bool, + bool *, bool *); -static tree -get_function_named_in_call (tree t); +static tree get_function_named_in_call (tree t); -static tree -eval_statement_list (const constexpr_ctx *ctx, tree t, bool *non_constant_p, - bool *overflow_p, tree *jump_target); -static tree -extract_string_elt (tree string, unsigned chars_per_elt, unsigned index); +static tree eval_statement_list (const constexpr_ctx *ctx, tree t, + bool *non_constant_p, bool *overflow_p, + tree *jump_target); +static tree extract_string_elt (tree string, unsigned chars_per_elt, + unsigned index); -static tree -eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p, - tree *jump_target); +static tree eval_conditional_expression (const constexpr_ctx *ctx, tree t, + bool lval, bool *non_constant_p, + bool *overflow_p, tree *jump_target); -static tree -eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p); +static tree eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval, + bool *non_constant_p, bool *overflow_p); -static tree -eval_loop_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, - bool *overflow_p, tree *jump_target); +static tree eval_loop_expr (const constexpr_ctx *ctx, tree t, + bool *non_constant_p, bool *overflow_p, + tree *jump_target); -static tree -eval_switch_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, - bool *overflow_p, tree *jump_target); +static tree eval_switch_expr (const constexpr_ctx *ctx, tree t, + bool *non_constant_p, bool *overflow_p, + tree *jump_target); -static tree -eval_unary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/, - bool *non_constant_p, bool *overflow_p); +static tree eval_unary_expression (const constexpr_ctx *ctx, tree t, + bool /*lval*/, bool *non_constant_p, + bool *overflow_p); /* Variables and functions to manage constexpr call expansion context. These do not need to be marked for PCH or GC. */ @@ -1235,7 +1219,8 @@ get_or_insert_ctor_field (tree ctor, tree index, int pos_hint = -1) /* We fell off the end of the CONSTRUCTOR, so insert a new entry at the end. */ - insert : { + insert: + { constructor_elt ce = {index, NULL_TREE}; vec_safe_insert (CONSTRUCTOR_ELTS (ctor), idx, ce); @@ -1568,10 +1553,9 @@ free_constructor (tree t) } } -static tree -eval_and_check_array_index (const constexpr_ctx *ctx, tree t, - bool allow_one_past, bool *non_constant_p, - bool *overflow_p); +static tree eval_and_check_array_index (const constexpr_ctx *ctx, tree t, + bool allow_one_past, + bool *non_constant_p, bool *overflow_p); // forked from gcc/cp/constexpr.cc cxx_eval_array_reference @@ -1939,8 +1923,9 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, return eval_constant_expression (ctx, r, lval, non_constant_p, overflow_p); } - /* fall through */ - case CONST_DECL: { + /* fall through */ + case CONST_DECL: + { /* We used to not check lval for CONST_DECL, but darwin.cc uses CONST_DECL for aggregate constants. */ if (lval) @@ -2048,7 +2033,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, overflow_p); break; - case TARGET_EXPR: { + case TARGET_EXPR: + { tree type = TREE_TYPE (t); if (!literal_type_p (type)) @@ -2132,7 +2118,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, } break; - case DECL_EXPR: { + case DECL_EXPR: + { r = DECL_EXPR_DECL (t); if (AGGREGATE_TYPE_P (TREE_TYPE (r)) || VECTOR_TYPE_P (TREE_TYPE (r))) @@ -2204,7 +2191,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, return eval_constant_expression (ctx, OBJ_TYPE_REF_EXPR (t), lval, non_constant_p, overflow_p); - case EXIT_EXPR: { + case EXIT_EXPR: + { tree cond = TREE_OPERAND (t, 0); cond = eval_constant_expression (ctx, cond, /*lval*/ false, non_constant_p, overflow_p); @@ -2246,7 +2234,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, } break; - case ADDR_EXPR: { + case ADDR_EXPR: + { tree oldop = TREE_OPERAND (t, 0); tree op = eval_constant_expression (ctx, oldop, /*lval*/ true, non_constant_p, @@ -2264,7 +2253,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, break; } - case COMPOUND_EXPR: { + case COMPOUND_EXPR: + { /* check_return_expr sometimes wraps a TARGET_EXPR in a COMPOUND_EXPR; don't get confused. Also handle EMPTY_CLASS_EXPR introduced by build_call_a. */ @@ -2404,7 +2394,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, non_constant_p, overflow_p, jump_target); break; - case CLEANUP_POINT_EXPR: { + case CLEANUP_POINT_EXPR: + { auto_vec cleanups; vec *prev_cleanups = ctx->global->cleanups; ctx->global->cleanups = &cleanups; @@ -2444,7 +2435,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, /* FALLTHROUGH. */ case NOP_EXPR: case CONVERT_EXPR: - case VIEW_CONVERT_EXPR: { + case VIEW_CONVERT_EXPR: + { tree oldop = TREE_OPERAND (t, 0); tree op = eval_constant_expression (ctx, oldop, lval, non_constant_p, @@ -2691,7 +2683,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, { case BIT_FIELD_REF: case COMPONENT_REF: - case ARRAY_REF: { + case ARRAY_REF: + { tree ob = TREE_OPERAND (probe, 0); tree elt = TREE_OPERAND (probe, 1); if (TREE_CODE (elt) == FIELD_DECL /*&& DECL_MUTABLE_P (elt)*/) @@ -3943,7 +3936,8 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body) { switch (TREE_CODE (body)) { - case STATEMENT_LIST: { + case STATEMENT_LIST: + { tree expr = NULL_TREE; for (tree stmt : tsi_range (body)) { @@ -3961,13 +3955,15 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body) return expr; } - case RETURN_EXPR: { + case RETURN_EXPR: + { bool non_constant_p = false; bool overflow_p = false; return eval_constant_expression (ctx, body, false, &non_constant_p, &overflow_p); } - case DECL_EXPR: { + case DECL_EXPR: + { tree decl = DECL_EXPR_DECL (body); if (TREE_CODE (decl) == USING_DECL /* Accept __func__, __FUNCTION__, and __PRETTY_FUNCTION__. */ @@ -3979,7 +3975,8 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body) case CLEANUP_POINT_EXPR: return constexpr_fn_retval (ctx, TREE_OPERAND (body, 0)); - case BIND_EXPR: { + case BIND_EXPR: + { tree b = BIND_EXPR_BODY (body); return constexpr_fn_retval (ctx, b); } @@ -4139,7 +4136,8 @@ array_index_cmp (tree key, tree index) { case INTEGER_CST: return tree_int_cst_compare (key, index); - case RANGE_EXPR: { + case RANGE_EXPR: + { tree lo = TREE_OPERAND (index, 0); tree hi = TREE_OPERAND (index, 1); if (tree_int_cst_lt (key, lo)) @@ -5946,7 +5944,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case BIT_FIELD_REF: return RECUR (TREE_OPERAND (t, 0), want_rval); - case INDIRECT_REF: { + case INDIRECT_REF: + { tree x = TREE_OPERAND (t, 0); STRIP_NOPS (x); return RECUR (x, rval); @@ -6217,7 +6216,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case INIT_EXPR: return RECUR (TREE_OPERAND (t, 1), rval); - case CONSTRUCTOR: { + case CONSTRUCTOR: + { vec *v = CONSTRUCTOR_ELTS (t); constructor_elt *ce; for (i = 0; vec_safe_iterate (v, i, &ce); ++i) @@ -6226,7 +6226,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, return true; } - case TREE_LIST: { + case TREE_LIST: + { gcc_assert (TREE_PURPOSE (t) == NULL_TREE || DECL_P (TREE_PURPOSE (t))); if (!RECUR (TREE_VALUE (t), want_rval)) return false; @@ -6241,7 +6242,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case ROUND_DIV_EXPR: case TRUNC_MOD_EXPR: case CEIL_MOD_EXPR: - case ROUND_MOD_EXPR: { + case ROUND_MOD_EXPR: + { tree denom = TREE_OPERAND (t, 1); if (!RECUR (denom, rval)) return false; @@ -6261,7 +6263,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, } } - case COMPOUND_EXPR: { + case COMPOUND_EXPR: + { /* check_return_expr sometimes wraps a TARGET_EXPR in a COMPOUND_EXPR; don't get confused. */ tree op0 = TREE_OPERAND (t, 0); @@ -6283,7 +6286,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case TRUTH_OR_EXPR: case TRUTH_ORIF_EXPR: tmp = boolean_false_node; - truth : { + truth: + { tree op0 = TREE_OPERAND (t, 0); tree op1 = TREE_OPERAND (t, 1); if (!RECUR (op0, rval)) diff --git a/gcc/rust/backend/rust-constexpr.h b/gcc/rust/backend/rust-constexpr.h index 77a0797a019d..27f0a2e7fc5e 100644 --- a/gcc/rust/backend/rust-constexpr.h +++ b/gcc/rust/backend/rust-constexpr.h @@ -24,8 +24,7 @@ namespace Rust { namespace Compile { extern tree fold_expr (tree); -extern void -maybe_save_constexpr_fundef (tree fun); +extern void maybe_save_constexpr_fundef (tree fun); } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-mangle-v0.cc b/gcc/rust/backend/rust-mangle-v0.cc index d0df4aba27c3..f6b1a4cb54e6 100644 --- a/gcc/rust/backend/rust-mangle-v0.cc +++ b/gcc/rust/backend/rust-mangle-v0.cc @@ -62,9 +62,9 @@ struct V0Path } }; -static std::string -v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path); +static std::string v0_path (Rust::Compile::Context *ctx, + const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); static std::string v0_tuple_prefix (const TyTy::BaseType *ty) @@ -148,7 +148,8 @@ v0_complex_type_prefix (Context *ctx, const TyTy::BaseType *ty) // TODO: generics switch (ty->get_kind ()) { - case TyTy::TypeKind::ADT: { + case TyTy::TypeKind::ADT: + { const TyTy::ADTType *adt = static_cast (ty); return v0_path (ctx, ty, adt->get_ident ().path); } @@ -387,7 +388,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, { switch (impl_item->first->get_impl_item_type ()) { - case HIR::ImplItem::FUNCTION: { + case HIR::ImplItem::FUNCTION: + { HIR::Function *fn = static_cast (impl_item->first); v0path @@ -408,7 +410,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, { switch (trait_item.value ()->get_item_kind ()) { - case HIR::TraitItem::FUNC: { + case HIR::TraitItem::FUNC: + { auto fn = static_cast (*trait_item); rust_unreachable (); v0path = v0_function_path (v0path, ctx, ty, @@ -428,7 +431,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, else if (auto item = mappings.lookup_hir_item (hir_id)) switch (item.value ()->get_item_kind ()) { - case HIR::Item::ItemKind::Function: { + case HIR::Item::ItemKind::Function: + { HIR::Function *fn = static_cast (*item); v0path = v0_function_path (v0path, ctx, ty, fn->get_generic_params (), diff --git a/gcc/rust/backend/rust-mangle.h b/gcc/rust/backend/rust-mangle.h index 2a84b6b1deaa..418f2bdca881 100644 --- a/gcc/rust/backend/rust-mangle.h +++ b/gcc/rust/backend/rust-mangle.h @@ -49,13 +49,12 @@ class Mangler static enum MangleVersion version; }; -std::string -legacy_mangle_item (const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path); +std::string legacy_mangle_item (const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); -std::string -v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path); +std::string v0_mangle_item (Rust::Compile::Context *ctx, + const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc index 6cba04b3c277..a3d605cab4b8 100644 --- a/gcc/rust/backend/rust-tree.cc +++ b/gcc/rust/backend/rust-tree.cc @@ -268,7 +268,8 @@ convert_to_void (tree expr, impl_conv_void implicit) return expr; switch (TREE_CODE (expr)) { - case COND_EXPR: { + case COND_EXPR: + { /* The two parts of a cond expr might be separate lvalues. */ tree op1 = TREE_OPERAND (expr, 1); tree op2 = TREE_OPERAND (expr, 2); @@ -294,7 +295,8 @@ convert_to_void (tree expr, impl_conv_void implicit) break; } - case COMPOUND_EXPR: { + case COMPOUND_EXPR: + { /* The second part of a compound expr contains the value. */ tree op1 = TREE_OPERAND (expr, 1); tree new_op1; @@ -323,7 +325,8 @@ convert_to_void (tree expr, impl_conv_void implicit) maybe_warn_nodiscard (expr, implicit); break; - case INDIRECT_REF: { + case INDIRECT_REF: + { tree type = TREE_TYPE (expr); int is_reference = TYPE_REF_P (TREE_TYPE (TREE_OPERAND (expr, 0))); int is_volatile = TYPE_VOLATILE (type); @@ -518,7 +521,8 @@ convert_to_void (tree expr, impl_conv_void implicit) break; } - case VAR_DECL: { + case VAR_DECL: + { /* External variables might be incomplete. */ tree type = TREE_TYPE (expr); int is_complete = COMPLETE_TYPE_P (type); @@ -1485,7 +1489,8 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void *data) parameter pack. ??? Should some of these be in cp_walk_subtrees? */ switch (TREE_CODE (t)) { - case DECL_EXPR: { + case DECL_EXPR: + { tree decl = DECL_EXPR_DECL (t); if (is_typedef_decl (decl)) /* Since we stop at typedefs above, we need to look through them at @@ -1506,7 +1511,8 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void *data) *walk_subtrees = 0; return NULL_TREE; - case DECLTYPE_TYPE: { + case DECLTYPE_TYPE: + { /* When traversing a DECLTYPE_TYPE_EXPR, we need to set type_pack_expansion_p to false so that any placeholders within the expression don't get marked as parameter packs. */ @@ -1970,7 +1976,8 @@ rs_tree_equal (tree t1, tree t2) case SAVE_EXPR: return rs_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); - case CALL_EXPR: { + case CALL_EXPR: + { if (KOENIG_LOOKUP_P (t1) != KOENIG_LOOKUP_P (t2)) return false; @@ -1996,7 +2003,8 @@ rs_tree_equal (tree t1, tree t2) return true; } - case TARGET_EXPR: { + case TARGET_EXPR: + { tree o1 = TREE_OPERAND (t1, 0); tree o2 = TREE_OPERAND (t2, 0); @@ -2067,7 +2075,8 @@ rs_tree_equal (tree t1, tree t2) case tcc_expression: case tcc_vl_exp: case tcc_reference: - case tcc_statement: { + case tcc_statement: + { int n = rs_tree_operand_length (t1); if (TREE_CODE_CLASS (code1) == tcc_vl_exp && n != TREE_OPERAND_LENGTH (t2)) @@ -2095,7 +2104,11 @@ rs_tree_equal (tree t1, tree t2) /* TRUE iff TYPE is publicly & uniquely derived from PARENT. */ -bool publicly_uniquely_derived_p (tree, tree) { return false; } +bool +publicly_uniquely_derived_p (tree, tree) +{ + return false; +} // forked from gcc/cp/typeck.cc comp_except_types @@ -3375,7 +3388,11 @@ release_tree_vector (vec *vec) /* As above, but also check value-dependence of the expression as a whole. */ -bool instantiation_dependent_expression_p (tree) { return false; } +bool +instantiation_dependent_expression_p (tree) +{ + return false; +} // forked from gcc/cp/cvt.cc cp_get_callee @@ -3425,7 +3442,11 @@ scalarish_type_p (const_tree t) constructors are deleted. This function implements the ABI notion of non-trivial copy, which has diverged from the one in the standard. */ -bool type_has_nontrivial_copy_init (const_tree) { return false; } +bool +type_has_nontrivial_copy_init (const_tree) +{ + return false; +} // forked from gcc/cp/tree.cc build_local_temp @@ -3448,7 +3469,11 @@ build_local_temp (tree type) /* Returns true iff DECL is a capture proxy for a normal capture (i.e. without explicit initializer). */ -bool is_normal_capture_proxy (tree) { return false; } +bool +is_normal_capture_proxy (tree) +{ + return false; +} // forked from gcc/cp/c-common.cc reject_gcc_builtin @@ -3522,7 +3547,8 @@ is_bitfield_expr_with_lowered_type (const_tree exp) case BIT_NOT_EXPR: return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0)); - case COMPONENT_REF: { + case COMPONENT_REF: + { tree field; field = TREE_OPERAND (exp, 1); @@ -3907,7 +3933,8 @@ cxx_incomplete_type_diagnostic (location_t loc, const_tree value, break; case OFFSET_TYPE: - bad_member : { + bad_member: + { tree member = TREE_OPERAND (value, 1); if (is_overloaded_fn (member)) member = get_first_fn (member); @@ -3992,13 +4019,21 @@ decl_constant_var_p (tree decl) /* Returns true iff DECL is a variable or function declared with an auto type that has not yet been deduced to a real type. */ -bool undeduced_auto_decl (tree) { return false; } +bool +undeduced_auto_decl (tree) +{ + return false; +} // forked from gcc/cp/decl.cc require_deduced_type /* Complain if DECL has an undeduced return type. */ -bool require_deduced_type (tree, tsubst_flags_t) { return true; } +bool +require_deduced_type (tree, tsubst_flags_t) +{ + return true; +} /* Return the location of a tree passed to %+ formats. */ @@ -4288,10 +4323,9 @@ struct GTY ((for_user)) source_location_table_entry } // namespace Rust -extern void -gt_pch_nx (Rust::source_location_table_entry &); -extern void -gt_pch_nx (Rust::source_location_table_entry *, gt_pointer_operator, void *); +extern void gt_pch_nx (Rust::source_location_table_entry &); +extern void gt_pch_nx (Rust::source_location_table_entry *, gt_pointer_operator, + void *); namespace Rust { @@ -4419,7 +4453,8 @@ lvalue_kind (const_tree ref) case VIEW_CONVERT_EXPR: return lvalue_kind (TREE_OPERAND (ref, 0)); - case ARRAY_REF: { + case ARRAY_REF: + { tree op1 = TREE_OPERAND (ref, 0); if (TREE_CODE (TREE_TYPE (op1)) == ARRAY_TYPE) { @@ -4516,7 +4551,8 @@ lvalue_kind (const_tree ref) op2_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 1)); break; - case COND_EXPR: { + case COND_EXPR: + { tree op1 = TREE_OPERAND (ref, 1); if (!op1) op1 = TREE_OPERAND (ref, 0); diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h index bb99684b2bf8..28d93565ac4b 100644 --- a/gcc/rust/backend/rust-tree.h +++ b/gcc/rust/backend/rust-tree.h @@ -1543,7 +1543,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; #if defined ENABLE_TREE_CHECKING #define LANG_DECL_MIN_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (!LANG_DECL_HAS_MIN (NODE)) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -1554,7 +1554,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; template, not just on a FUNCTION_DECL. So when looking for things in lang_decl_fn, look down through a TEMPLATE_DECL into its result. */ #define LANG_DECL_FN_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (!DECL_DECLARES_FUNCTION_P (NODE) || lt->u.base.selector != lds_fn) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -1562,7 +1562,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; }) #define LANG_DECL_NS_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (TREE_CODE (NODE) != NAMESPACE_DECL || lt->u.base.selector != lds_ns) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -1570,7 +1570,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; }) #define LANG_DECL_PARM_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (TREE_CODE (NODE) != PARM_DECL || lt->u.base.selector != lds_parm) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -1578,7 +1578,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; }) #define LANG_DECL_DECOMP_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (!VAR_P (NODE) || lt->u.base.selector != lds_decomp) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -2060,8 +2060,8 @@ struct GTY (()) rust_cxx_saved_binding // forked from gcc/cp/name-lookup.h resort_type_member_vec /* needed for GTY annotation */ -extern void -resort_type_member_vec (void *, void *, gt_pointer_operator, void *); +extern void resort_type_member_vec (void *, void *, gt_pointer_operator, + void *); // forked from gcc/cp/cp-tree.h saved_scope @@ -2895,8 +2895,7 @@ enum compare_bounds_t bounds_first }; -extern tree -convert_to_void (tree expr, impl_conv_void implicit); +extern tree convert_to_void (tree expr, impl_conv_void implicit); // The lvalue-to-rvalue conversion (7.1) is applied if and only if the // expression is a glvalue of volatile-qualified type and it is one of the @@ -2911,63 +2910,52 @@ convert_to_void (tree expr, impl_conv_void implicit); // operands are one of these expressions, or // * comma expression (8.19) where the right operand is one of these // expressions. -extern tree -mark_discarded_use (tree expr); +extern tree mark_discarded_use (tree expr); // Mark EXP as read, not just set, for set but not used -Wunused warning // purposes. -extern void -mark_exp_read (tree exp); +extern void mark_exp_read (tree exp); // We've seen an actual use of EXPR. Possibly replace an outer variable // reference inside with its constant value or a lambda capture. -extern tree -mark_use (tree expr, bool rvalue_p, bool read_p, location_t loc, - bool reject_builtin); +extern tree mark_use (tree expr, bool rvalue_p, bool read_p, location_t loc, + bool reject_builtin); // Called whenever the expression EXPR is used in an rvalue context. // When REJECT_BUILTIN is true the expression is checked to make sure // it doesn't make it possible to obtain the address of a GCC built-in // function with no library fallback (or any of its bits, such as in // a conversion to bool). -extern tree -mark_rvalue_use (tree, location_t = UNKNOWN_LOCATION, - bool reject_builtin = true); +extern tree mark_rvalue_use (tree, location_t = UNKNOWN_LOCATION, + bool reject_builtin = true); // Called whenever an expression is used in an lvalue context. -extern tree -mark_lvalue_use (tree expr); +extern tree mark_lvalue_use (tree expr); // As above, but don't consider this use a read. -extern tree -mark_lvalue_use_nonread (tree expr); +extern tree mark_lvalue_use_nonread (tree expr); // We are using a reference VAL for its value. Bash that reference all the way // down to its lowest form. -extern tree -convert_from_reference (tree val); +extern tree convert_from_reference (tree val); // Subroutine of convert_to_void. Warn if we're discarding something with // attribute [[nodiscard]]. -extern void -maybe_warn_nodiscard (tree expr, impl_conv_void implicit); +extern void maybe_warn_nodiscard (tree expr, impl_conv_void implicit); -extern location_t -expr_loc_or_loc (const_tree t, location_t or_loc); +extern location_t expr_loc_or_loc (const_tree t, location_t or_loc); -extern location_t -expr_loc_or_input_loc (const_tree t); +extern location_t expr_loc_or_input_loc (const_tree t); // FN is the callee of a CALL_EXPR or AGGR_INIT_EXPR; return the FUNCTION_DECL // if we can. -extern tree -get_fndecl_from_callee (tree fn); +extern tree get_fndecl_from_callee (tree fn); // FIXME some helpers from HIRCompileBase could probably be moved here over time // Return an expression for the address of BASE[INDEX], used in offset intrinsic -extern tree -pointer_offset_expression (tree base_tree, tree index_tree, location_t locus); +extern tree pointer_offset_expression (tree base_tree, tree index_tree, + location_t locus); /* A tree node, together with a location, so that we can track locations (and ranges) during parsing. @@ -2978,11 +2966,9 @@ pointer_offset_expression (tree base_tree, tree index_tree, location_t locus); extern location_t rs_expr_location (const_tree); -extern int -is_empty_class (tree type); +extern int is_empty_class (tree type); -extern bool -is_really_empty_class (tree, bool); +extern bool is_really_empty_class (tree, bool); extern bool builtin_valid_in_constant_expr_p (const_tree); @@ -2990,15 +2976,13 @@ extern bool maybe_constexpr_fn (tree); extern bool var_in_maybe_constexpr_fn (tree); -extern int -rs_type_quals (const_tree type); +extern int rs_type_quals (const_tree type); inline bool type_unknown_p (const_tree); extern bool decl_maybe_constant_var_p (tree); -extern void -init_modules (); +extern void init_modules (); extern bool var_in_constexpr_fn (tree); @@ -3006,11 +2990,9 @@ inline tree ovl_first (tree) ATTRIBUTE_PURE; inline bool type_unknown_p (const_tree); -extern tree -lookup_add (tree fns, tree lookup); +extern tree lookup_add (tree fns, tree lookup); -extern tree -ovl_make (tree fn, tree next = NULL_TREE); +extern tree ovl_make (tree fn, tree next = NULL_TREE); extern int is_overloaded_fn (tree) ATTRIBUTE_PURE; @@ -3024,19 +3006,15 @@ extern tree make_conv_op_name (tree); extern int type_memfn_quals (const_tree); -struct c_fileinfo * -get_fileinfo (const char *); +struct c_fileinfo *get_fileinfo (const char *); -extern tree -cxx_make_type (enum tree_code CXX_MEM_STAT_INFO); +extern tree cxx_make_type (enum tree_code CXX_MEM_STAT_INFO); -extern tree -build_cplus_array_type (tree, tree, int is_dep = -1); +extern tree build_cplus_array_type (tree, tree, int is_dep = -1); extern bool is_byte_access_type (tree); -extern bool -comptypes (tree, tree, int); +extern bool comptypes (tree, tree, int); extern tree canonical_eh_spec (tree); @@ -3046,8 +3024,7 @@ extern bool rs_tree_equal (tree, tree); extern bool compparms (const_tree, const_tree); -extern tree -rs_build_qualified_type_real (tree, int, tsubst_flags_t); +extern tree rs_build_qualified_type_real (tree, int, tsubst_flags_t); #define rs_build_qualified_type(TYPE, QUALS) \ rs_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error) extern bool cv_qualified_p (const_tree); @@ -3056,21 +3033,18 @@ extern bool similar_type_p (tree, tree); extern bool rs_tree_equal (tree, tree); -extern bool -vector_targets_convertible_p (const_tree t1, const_tree t2); +extern bool vector_targets_convertible_p (const_tree t1, const_tree t2); extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree); extern bool comp_ptr_ttypes_const (tree, tree, compare_bounds_t); -extern tree -get_class_binding_direct (tree, tree, bool want_type = false); +extern tree get_class_binding_direct (tree, tree, bool want_type = false); extern tree skip_artificial_parms_for (const_tree, tree); -extern void -lang_check_failed (const char *, int, - const char *) ATTRIBUTE_NORETURN ATTRIBUTE_COLD; +extern void lang_check_failed (const char *, int, + const char *) ATTRIBUTE_NORETURN ATTRIBUTE_COLD; extern tree default_init_uninitialized_part (tree); @@ -3088,8 +3062,7 @@ extern tree in_class_defaulted_default_constructor (tree); extern bool is_instantiation_of_constexpr (tree); -extern bool -check_for_uninitialized_const_var (tree, bool, tsubst_flags_t); +extern bool check_for_uninitialized_const_var (tree, bool, tsubst_flags_t); extern bool reduced_constant_expression_p (tree); @@ -3108,19 +3081,17 @@ extern tree is_bitfield_expr_with_lowered_type (const_tree); extern tree convert_bitfield_to_declared_type (tree); -extern tree -cp_fold_maybe_rvalue (tree, bool); +extern tree cp_fold_maybe_rvalue (tree, bool); extern tree maybe_undo_parenthesized_ref (tree); -extern tree -fold_offsetof (tree, tree = size_type_node, tree_code ctx = ERROR_MARK); +extern tree fold_offsetof (tree, tree = size_type_node, + tree_code ctx = ERROR_MARK); extern tree cp_truthvalue_conversion (tree, tsubst_flags_t); -extern tree -fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error, - bool = false, tree = NULL_TREE); +extern tree fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error, + bool = false, tree = NULL_TREE); extern int char_type_p (tree); @@ -3163,13 +3134,11 @@ extern tree build_new_constexpr_heap_type (tree, tree, tree); extern bool is_empty_field (tree); -extern bool -in_immediate_context (); +extern bool in_immediate_context (); extern tree cp_get_callee_fndecl_nofold (tree); -extern bool -cxx_mark_addressable (tree, bool = false); +extern bool cxx_mark_addressable (tree, bool = false); extern tree fold_builtin_source_location (location_t); @@ -3183,25 +3152,22 @@ extern bool glvalue_p (const_tree); extern cp_lvalue_kind lvalue_kind (const_tree); -extern tree -decl_constant_value (tree, bool); +extern tree decl_constant_value (tree, bool); extern tree lookup_enumerator (tree, tree); -extern int -is_class_type (tree, int); +extern int is_class_type (tree, int); extern tree braced_lists_to_strings (tree, tree); -extern tree -fold_builtin_is_pointer_inverconvertible_with_class (location_t, int, tree *); +extern tree fold_builtin_is_pointer_inverconvertible_with_class (location_t, + int, tree *); extern bool layout_compatible_type_p (tree, tree); extern tree finish_underlying_type (tree); -extern tree -c_common_type_for_mode (machine_mode, int); +extern tree c_common_type_for_mode (machine_mode, int); extern bool std_layout_type_p (const_tree); @@ -3213,25 +3179,21 @@ extern void note_failed_type_completion_for_satisfaction (tree); extern tree complete_type_or_maybe_complain (tree, tree, tsubst_flags_t); -extern bool -next_common_initial_seqence (tree &, tree &); +extern bool next_common_initial_seqence (tree &, tree &); extern bool null_member_pointer_value_p (tree); -extern tree -fold_builtin_is_corresponding_member (location_t, int, tree *); +extern tree fold_builtin_is_corresponding_member (location_t, int, tree *); extern tree cp_fold_rvalue (tree); -extern tree -maybe_constant_value (tree, tree = NULL_TREE, bool = false); +extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false); extern tree lvalue_type (tree); extern void lvalue_error (location_t, enum lvalue_use); -extern tree -cp_fold_maybe_rvalue (tree, bool); +extern tree cp_fold_maybe_rvalue (tree, bool); extern tree get_first_fn (tree) ATTRIBUTE_PURE; @@ -3253,13 +3215,12 @@ enum ce_exact }; -extern tree -rs_build_qualified_type_real (tree, int, tsubst_flags_t); +extern tree rs_build_qualified_type_real (tree, int, tsubst_flags_t); #define rs_build_qualified_type(TYPE, QUALS) \ rs_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error) -extern tree -rs_walk_subtrees (tree *, int *, walk_tree_fn, void *, hash_set *); +extern tree rs_walk_subtrees (tree *, int *, walk_tree_fn, void *, + hash_set *); #define rs_walk_tree(tp, func, data, pset) \ walk_tree_1 (tp, func, data, pset, rs_walk_subtrees) #define rs_walk_tree_without_duplicates(tp, func, data) \ @@ -3351,11 +3312,9 @@ gnu_vector_type_p (const_tree type) return TREE_CODE (type) == VECTOR_TYPE && !TYPE_INDIVISIBLE_P (type); } -extern vec * -make_tree_vector (void); +extern vec *make_tree_vector (void); -extern void -release_tree_vector (vec *); +extern void release_tree_vector (vec *); /* Simplified unique_ptr clone to release a tree vec on exit. */ @@ -3373,7 +3332,7 @@ class releasing_vec releasing_vec &operator= (const releasing_vec &); vec_t &operator* () const { return *v; } - vec_t *operator-> () const { return v; } + vec_t *operator->() const { return v; } vec_t *get () const { return v; } operator vec_t * () const { return v; } vec_t **operator& () { return &v; } @@ -3442,8 +3401,7 @@ cxx_incomplete_type_error (const_tree value, const_tree type) cxx_incomplete_type_diagnostic (value, type, DK_ERROR); } -extern location_t -location_of (tree t); +extern location_t location_of (tree t); /* Helpers for IMPLICIT_RVALUE_P to look through automatic dereference. */ @@ -3465,23 +3423,18 @@ set_implicit_rvalue_p (tree ot) } namespace Compile { -extern tree -maybe_constant_init (tree, tree = NULL_TREE, bool = false); +extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false); -extern void -explain_invalid_constexpr_fn (tree fun); +extern void explain_invalid_constexpr_fn (tree fun); extern bool potential_constant_expression (tree); -extern bool -literal_type_p (tree t); +extern bool literal_type_p (tree t); -extern bool -maybe_constexpr_fn (tree t); +extern bool maybe_constexpr_fn (tree t); -extern tree -fold_non_dependent_init (tree, tsubst_flags_t = tf_warning_or_error, - bool = false, tree = NULL_TREE); +extern tree fold_non_dependent_init (tree, tsubst_flags_t = tf_warning_or_error, + bool = false, tree = NULL_TREE); } // namespace Compile } // namespace Rust diff --git a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h index 0ce214218212..0434bcfed034 100644 --- a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h +++ b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h @@ -239,31 +239,25 @@ struct Facts * * Output is not yet implemented and is only dumped to stdout. */ -extern "C" FFI::Output -polonius_run (FFI::FactsView input, bool dump_enabled); +extern "C" FFI::Output polonius_run (FFI::FactsView input, bool dump_enabled); // Helper functions for FFIVector to be used on Rust side extern "C" { -FFI::FFIVector * -FFIVector__new (); +FFI::FFIVector *FFIVector__new (); -FFI::FFIVectorPair * -FFIVector__new_vec_pair (); +FFI::FFIVectorPair *FFIVector__new_vec_pair (); -FFI::FFIVectorTriple * -FFIVector__new_vec_triple (); +FFI::FFIVectorTriple *FFIVector__new_vec_triple (); -void -FFIVector__push (FFI::FFIVector *vector, size_t element); +void FFIVector__push (FFI::FFIVector *vector, size_t element); void FFIVector__push_vec_pair (FFI::FFIVectorPair *vector, FFI::Pair *> element); -void -FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector, - FFI::Triple element); +void FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector, + FFI::Triple element); } } // namespace Polonius diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc index 6b8b2e97ba74..c59aba40d1cf 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc @@ -240,7 +240,8 @@ ExprStmtBuilder::visit (HIR::ArrayExpr &expr) auto &elems = expr.get_internal_elements (); switch (elems.get_array_expr_type ()) { - case HIR::ArrayElems::VALUES: { + case HIR::ArrayElems::VALUES: + { auto &elem_vals = (static_cast (elems)); auto init_values = visit_list (elem_vals.get_values ()); // collect locations @@ -254,7 +255,8 @@ ExprStmtBuilder::visit (HIR::ArrayExpr &expr) lookup_type (expr), expr.get_locus ()); break; } - case HIR::ArrayElems::COPIED: { + case HIR::ArrayElems::COPIED: + { auto &elem_copied = (static_cast (elems)); auto init = visit_expr (elem_copied.get_elem_to_copy ()); return_expr (new InitializerExpr ({init}), lookup_type (expr), diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc index ee37bb09bc43..2d655f910342 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc @@ -101,7 +101,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern) { switch (field->get_item_type ()) { - case HIR::StructPatternField::TUPLE_PAT: { + case HIR::StructPatternField::TUPLE_PAT: + { auto tuple = static_cast (field.get ()); @@ -123,7 +124,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern) tuple->get_tuple_pattern ().accept_vis (*this); break; } - case HIR::StructPatternField::IDENT_PAT: { + case HIR::StructPatternField::IDENT_PAT: + { auto ident_field = static_cast (field.get ()); TyTy::StructFieldType *field_ty = nullptr; @@ -139,7 +141,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern) ident_field->get_pattern ().accept_vis (*this); break; } - case HIR::StructPatternField::IDENT: { + case HIR::StructPatternField::IDENT: + { auto ident_field = static_cast (field.get ()); TyTy::StructFieldType *field_ty = nullptr; @@ -199,13 +202,15 @@ PatternBindingBuilder::visit (HIR::TuplePattern &pattern) size_t index = 0; switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::MULTIPLE: { + case HIR::TuplePatternItems::MULTIPLE: + { auto &items = static_cast ( pattern.get_items ()); visit_tuple_fields (items.get_patterns (), saved, index); break; } - case HIR::TuplePatternItems::RANGED: { + case HIR::TuplePatternItems::RANGED: + { auto &items = static_cast (pattern.get_items ()); @@ -244,7 +249,8 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern) size_t index = 0; switch (pattern.get_items ().get_item_type ()) { - case HIR::TupleStructItems::RANGED: { + case HIR::TupleStructItems::RANGED: + { auto &items = static_cast (pattern.get_items ()); @@ -261,7 +267,8 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern) visit_tuple_fields (items.get_upper_patterns (), saved, index); break; } - case HIR::TupleStructItems::MULTIPLE: { + case HIR::TupleStructItems::MULTIPLE: + { auto &items = static_cast (pattern.get_items ()); visit_tuple_fields (items.get_patterns (), saved, index); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc index 3864b81a4d9e..9a7bb2054aeb 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc @@ -182,7 +182,8 @@ Dump::visit (const Statement &stmt) statement_place = stmt.get_place (); switch (stmt.get_kind ()) { - case Statement::Kind::ASSIGNMENT: { + case Statement::Kind::ASSIGNMENT: + { visit_place (stmt.get_place ()); stream << " = "; stmt.get_expr ().accept_vis (*this); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h index 32a4cd7b76c8..e3a1247206d6 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h @@ -232,42 +232,50 @@ class FactCollector : public Visitor { switch (stmt.get_kind ()) { - case Statement::Kind::ASSIGNMENT: { + case Statement::Kind::ASSIGNMENT: + { // TODO: for unwind, must had hadning for non-panic-only assignements issue_write_deep (stmt.get_place ()); visit_assignment_expr (stmt.get_place (), stmt.get_expr ()); break; } - case Statement::Kind::SWITCH: { + case Statement::Kind::SWITCH: + { issue_read_move (stmt.get_place ()); issue_jumps (); } break; - case Statement::Kind::GOTO: { + case Statement::Kind::GOTO: + { issue_jumps (); } break; - case Statement::Kind::RETURN: { + case Statement::Kind::RETURN: + { issue_place_access (RETURN_VALUE_PLACE); issue_locals_dealloc (); break; } - case Statement::Kind::STORAGE_DEAD: { + case Statement::Kind::STORAGE_DEAD: + { facts.path_moved_at_base.emplace_back (stmt.get_place ().value, get_current_point_mid ()); facts.var_defined_at.emplace_back (stmt.get_place ().value, get_current_point_mid ()); break; } - case Statement::Kind::STORAGE_LIVE: { + case Statement::Kind::STORAGE_LIVE: + { issue_write_deep (stmt.get_place (), true); break; } - case Statement::Kind::USER_TYPE_ASCRIPTION: { + case Statement::Kind::USER_TYPE_ASCRIPTION: + { issue_user_type_constraints (stmt.get_place (), stmt.get_type ()); break; } - case Statement::Kind::FAKE_READ: { + case Statement::Kind::FAKE_READ: + { issue_place_access (stmt.get_place ()); break; } @@ -791,7 +799,8 @@ class FactCollector : public Visitor type->as ()->get_element_type (), region_start, regions); case TyTy::FNDEF: - case TyTy::TUPLE: { + case TyTy::TUPLE: + { for (auto &field : type->as ()->get_fields ()) sanitize_constraints (field.get_tyty (), region_start, regions); } diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h index dd9e672f4120..14f1dd660b0e 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h @@ -217,7 +217,7 @@ template class IndexVec const T &operator[] (I pid) const { return internal_vector[pid.value]; } void push_back (T &¶m) { internal_vector.push_back (std::move (param)); } - template void emplace_back (Args &&... args) + template void emplace_back (Args &&...args) { internal_vector.emplace_back (std::forward (args)...); } @@ -471,14 +471,16 @@ class PlaceDB case TyTy::FNDEF: case TyTy::NEVER: return true; - case TyTy::TUPLE: { + case TyTy::TUPLE: + { auto &fields = ty->as ()->get_fields (); return std::all_of (fields.begin (), fields.end (), [] (const TyTy::TyVar &field) { return is_type_copy (field.get_tyty ()); }); } - case TyTy::ARRAY: { + case TyTy::ARRAY: + { return is_type_copy (ty->as ()->get_element_type ()); } case TyTy::INFER: diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h index 5dac89e51170..d405569b566d 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h @@ -51,7 +51,7 @@ template class VisitableImpl : public BASE { public: template - explicit VisitableImpl (Args &&... args) : BASE (std::forward (args)...) + explicit VisitableImpl (Args &&...args) : BASE (std::forward (args)...) {} void accept_vis (Visitor &visitor) override diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc index 3d25459d9cfd..5291276a7a37 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc @@ -25,8 +25,7 @@ #include "rust-pub-restricted-visitor.h" #include "rust-privacy-reporter.h" -extern bool -saw_errors (void); +extern bool saw_errors (void); namespace Rust { namespace Privacy { diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h b/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h index a506613f64e8..9699ac4f98c7 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h +++ b/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h @@ -71,8 +71,7 @@ class PrivacyContext #if CHECKING_P namespace selftest { -void -rust_privacy_ctx_test (void); +void rust_privacy_ctx_test (void); } #endif // !CHECKING_P diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc index 2a1005343a15..3faa3b404e69 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc @@ -157,7 +157,8 @@ PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, { case ModuleVisibility::Public: break; - case ModuleVisibility::Restricted: { + case ModuleVisibility::Restricted: + { // If we are in the crate, everything is restricted correctly, but we // can't get a module for it if (!current_module.has_value ()) @@ -215,7 +216,8 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings, case TyTy::USIZE: case TyTy::ISIZE: case TyTy::ADT: - case TyTy::STR: { + case TyTy::STR: + { auto ref_id = ty->get_ref (); if (auto lookup_id = mappings.lookup_hir_to_node (ref_id)) return check_for_privacy_violation (*lookup_id, locus); @@ -243,7 +245,8 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings, static_cast (ty)->get_fields ()) recursive_check (param.get_tyty ()); return; - case TyTy::PLACEHOLDER: { + case TyTy::PLACEHOLDER: + { const auto p = static_cast (ty); if (!p->can_resolve ()) return; @@ -413,7 +416,8 @@ PrivacyReporter::visit (HIR::ArrayExpr &expr) HIR::ArrayElems &elements = expr.get_internal_elements (); switch (elements.get_array_expr_type ()) { - case HIR::ArrayElems::ArrayExprType::VALUES: { + case HIR::ArrayElems::ArrayExprType::VALUES: + { auto &elems = static_cast (elements); for (auto &value : elems.get_values ()) value->accept_vis (*this); diff --git a/gcc/rust/checks/errors/privacy/rust-reachability.cc b/gcc/rust/checks/errors/privacy/rust-reachability.cc index 1e57674b4024..223c77b5f71f 100644 --- a/gcc/rust/checks/errors/privacy/rust-reachability.cc +++ b/gcc/rust/checks/errors/privacy/rust-reachability.cc @@ -158,7 +158,8 @@ ReachabilityVisitor::visit (HIR::Enum &enum_item) switch (variant->get_enum_item_kind ()) { - case HIR::EnumItem::Tuple: { + case HIR::EnumItem::Tuple: + { // Should we update the fields only if they are public? Similarly to // what we do in the ReachabilityVisitor for HIR::TupleStruct? auto tuple_variant @@ -167,7 +168,8 @@ ReachabilityVisitor::visit (HIR::Enum &enum_item) ctx.update_reachability (field.get_mappings (), variant_reach); break; } - case HIR::EnumItem::Struct: { + case HIR::EnumItem::Struct: + { // Should we update the fields only if they are public? Similarly to // what we do in the ReachabilityVisitor for HIR::StructStruct? auto struct_variant diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc index f0da74560768..c59763d73782 100644 --- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc +++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc @@ -127,7 +127,8 @@ VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility, case HIR::Visibility::PUBLIC: to_resolve = ModuleVisibility::create_public (); return true; - case HIR::Visibility::RESTRICTED: { + case HIR::Visibility::RESTRICTED: + { // FIXME: We also need to handle 2015 vs 2018 edition conflicts auto id = UNKNOWN_DEFID; auto result = resolve_module_path (visibility.get_path (), id); diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc index 648bc07762db..6db769f2f63a 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc @@ -728,23 +728,27 @@ Constructor::is_covered_by (const Constructor &o) const switch (kind) { - case ConstructorKind::VARIANT: { + case ConstructorKind::VARIANT: + { rust_assert (kind == ConstructorKind::VARIANT); return variant_idx == o.variant_idx; } break; - case ConstructorKind::INT_RANGE: { + case ConstructorKind::INT_RANGE: + { rust_assert (kind == ConstructorKind::INT_RANGE); return int_range.lo >= o.int_range.lo && int_range.hi <= o.int_range.hi; } break; - case ConstructorKind::WILDCARD: { + case ConstructorKind::WILDCARD: + { // TODO: wildcard is covered by a variant of enum with a single // variant return false; } break; - case ConstructorKind::STRUCT: { + case ConstructorKind::STRUCT: + { // Struct pattern is always covered by a other struct constructor. return true; } @@ -900,19 +904,22 @@ PlaceInfo::specialize (const Constructor &c) const switch (c.get_kind ()) { case Constructor::ConstructorKind::WILDCARD: - case Constructor::ConstructorKind::INT_RANGE: { + case Constructor::ConstructorKind::INT_RANGE: + { return {}; } break; case Constructor::ConstructorKind::STRUCT: - case Constructor::ConstructorKind::VARIANT: { + case Constructor::ConstructorKind::VARIANT: + { rust_assert (ty->get_kind () == TyTy::TypeKind::ADT); TyTy::ADTType *adt = static_cast (ty); switch (adt->get_adt_kind ()) { case TyTy::ADTType::ADTKind::ENUM: case TyTy::ADTType::ADTKind::STRUCT_STRUCT: - case TyTy::ADTType::ADTKind::TUPLE_STRUCT: { + case TyTy::ADTType::ADTKind::TUPLE_STRUCT: + { TyTy::VariantDef *variant = adt->get_variants ().at (c.get_variant_index ()); if (variant->get_variant_type () @@ -926,14 +933,16 @@ PlaceInfo::specialize (const Constructor &c) const return new_place_infos; } break; - case TyTy::ADTType::ADTKind::UNION: { + case TyTy::ADTType::ADTKind::UNION: + { // TODO: support unions rust_unreachable (); } } } break; - default: { + default: + { rust_unreachable (); } break; @@ -991,7 +1000,8 @@ WitnessPat::to_string () const { switch (ctor.get_kind ()) { - case Constructor::ConstructorKind::STRUCT: { + case Constructor::ConstructorKind::STRUCT: + { TyTy::ADTType *adt = static_cast (ty); TyTy::VariantDef *variant = adt->get_variants ().at (ctor.get_variant_index ()); @@ -1016,7 +1026,8 @@ WitnessPat::to_string () const return buf; } break; - case Constructor::ConstructorKind::VARIANT: { + case Constructor::ConstructorKind::VARIANT: + { std::string buf; TyTy::ADTType *adt = static_cast (ty); buf += adt->get_identifier (); @@ -1026,11 +1037,13 @@ WitnessPat::to_string () const switch (variant->get_variant_type ()) { - case TyTy::VariantDef::VariantType::NUM: { + case TyTy::VariantDef::VariantType::NUM: + { return buf; } break; - case TyTy::VariantDef::VariantType::TUPLE: { + case TyTy::VariantDef::VariantType::TUPLE: + { buf += "("; for (size_t i = 0; i < fields.size (); i++) { @@ -1042,7 +1055,8 @@ WitnessPat::to_string () const return buf; } break; - case TyTy::VariantDef::VariantType::STRUCT: { + case TyTy::VariantDef::VariantType::STRUCT: + { buf += " {"; if (!fields.empty ()) buf += " "; @@ -1061,7 +1075,8 @@ WitnessPat::to_string () const buf += "}"; } break; - default: { + default: + { rust_unreachable (); } break; @@ -1069,21 +1084,25 @@ WitnessPat::to_string () const return buf; } break; - case Constructor::ConstructorKind::INT_RANGE: { + case Constructor::ConstructorKind::INT_RANGE: + { // TODO: implement rust_unreachable (); } break; - case Constructor::ConstructorKind::WILDCARD: { + case Constructor::ConstructorKind::WILDCARD: + { return "_"; } break; - case Constructor::ConstructorKind::REFERENCE: { + case Constructor::ConstructorKind::REFERENCE: + { // TODO: implement rust_unreachable (); } break; - default: { + default: + { rust_unreachable (); } break; @@ -1100,12 +1119,14 @@ WitnessMatrix::apply_constructor (const Constructor &ctor, // TODO: only support struct and variant ctor for now. switch (ctor.get_kind ()) { - case Constructor::ConstructorKind::WILDCARD: { + case Constructor::ConstructorKind::WILDCARD: + { arity = 0; } break; case Constructor::ConstructorKind::STRUCT: - case Constructor::ConstructorKind::VARIANT: { + case Constructor::ConstructorKind::VARIANT: + { if (ty->get_kind () == TyTy::TypeKind::ADT) { TyTy::ADTType *adt = static_cast (ty); @@ -1118,7 +1139,8 @@ WitnessMatrix::apply_constructor (const Constructor &ctor, } } break; - default: { + default: + { rust_unreachable (); } } @@ -1160,9 +1182,9 @@ WitnessMatrix::extend (const WitnessMatrix &other) } // forward declarations -static DeconstructedPat -lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern, - TyTy::BaseType *scrutinee_ty); +static DeconstructedPat lower_pattern (Resolver::TypeCheckContext *ctx, + HIR::Pattern &pattern, + TyTy::BaseType *scrutinee_ty); static DeconstructedPat lower_tuple_pattern (Resolver::TypeCheckContext *ctx, @@ -1175,7 +1197,8 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx, std::vector fields; switch (elems.get_item_type ()) { - case HIR::TupleStructItems::ItemType::MULTIPLE: { + case HIR::TupleStructItems::ItemType::MULTIPLE: + { HIR::TupleStructItemsNoRange &multiple = static_cast (elems); @@ -1191,12 +1214,14 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx, return DeconstructedPat (ctor, arity, fields, pattern.get_locus ()); } break; - case HIR::TupleStructItems::ItemType::RANGED: { + case HIR::TupleStructItems::ItemType::RANGED: + { // TODO: ranged tuple struct items rust_unreachable (); } break; - default: { + default: + { rust_unreachable (); } } @@ -1227,7 +1252,8 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx, { switch (elem->get_item_type ()) { - case HIR::StructPatternField::ItemType::IDENT: { + case HIR::StructPatternField::ItemType::IDENT: + { HIR::StructPatternFieldIdent *ident = static_cast (elem.get ()); int field_idx @@ -1236,7 +1262,8 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx, = DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::StructPatternField::ItemType::IDENT_PAT: { + case HIR::StructPatternField::ItemType::IDENT_PAT: + { HIR::StructPatternFieldIdentPat *ident_pat = static_cast (elem.get ()); int field_idx @@ -1246,12 +1273,14 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx, variant->get_fields ().at (field_idx)->get_field_type ()); } break; - case HIR::StructPatternField::ItemType::TUPLE_PAT: { + case HIR::StructPatternField::ItemType::TUPLE_PAT: + { // TODO: tuple: pat rust_unreachable (); } break; - default: { + default: + { rust_unreachable (); } } @@ -1268,11 +1297,13 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern, switch (pat_type) { case HIR::Pattern::PatternType::WILDCARD: - case HIR::Pattern::PatternType::IDENTIFIER: { + case HIR::Pattern::PatternType::IDENTIFIER: + { return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::PATH: { + case HIR::Pattern::PatternType::PATH: + { // TODO: support constants, associated constants, enum variants and // structs // https://doc.rust-lang.org/reference/patterns.html#path-patterns @@ -1280,13 +1311,15 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern, return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::REFERENCE: { + case HIR::Pattern::PatternType::REFERENCE: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; case HIR::Pattern::PatternType::STRUCT: - case HIR::Pattern::PatternType::TUPLE_STRUCT: { + case HIR::Pattern::PatternType::TUPLE_STRUCT: + { HirId path_id = UNKNOWN_HIRID; if (pat_type == HIR::Pattern::PatternType::STRUCT) { @@ -1343,37 +1376,44 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern, } } break; - case HIR::Pattern::PatternType::TUPLE: { + case HIR::Pattern::PatternType::TUPLE: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::SLICE: { + case HIR::Pattern::PatternType::SLICE: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::ALT: { + case HIR::Pattern::PatternType::ALT: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::LITERAL: { + case HIR::Pattern::PatternType::LITERAL: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::RANGE: { + case HIR::Pattern::PatternType::RANGE: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::GROUPED: { + case HIR::Pattern::PatternType::GROUPED: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - default: { + default: + { rust_unreachable (); } } diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h index 6d60ceda5384..62107e1d27f5 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h @@ -33,9 +33,9 @@ namespace Analysis { using namespace HIR; -void -check_match_usefulness (Resolver::TypeCheckContext *ctx, - TyTy::BaseType *scrutinee_ty, HIR::MatchExpr &expr); +void check_match_usefulness (Resolver::TypeCheckContext *ctx, + TyTy::BaseType *scrutinee_ty, + HIR::MatchExpr &expr); class PatternChecker : public HIR::HIRFullVisitor { diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index a8c3ca5bfc98..f761f9916c9a 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -289,7 +289,8 @@ CfgStrip::maybe_strip_generic_args (AST::GenericArgs &args) { switch (arg.get_kind ()) { - case AST::GenericArg::Kind::Type: { + case AST::GenericArg::Kind::Type: + { auto &type = arg.get_type (); type.accept_vis (*this); @@ -298,7 +299,8 @@ CfgStrip::maybe_strip_generic_args (AST::GenericArgs &args) "cannot strip type in this position"); break; } - case AST::GenericArg::Kind::Const: { + case AST::GenericArg::Kind::Const: + { auto &expr = arg.get_expression (); expr.accept_vis (*this); diff --git a/gcc/rust/expand/rust-derive-eq.cc b/gcc/rust/expand/rust-derive-eq.cc index 04c987dc96e3..97651270bc55 100644 --- a/gcc/rust/expand/rust-derive-eq.cc +++ b/gcc/rust/expand/rust-derive-eq.cc @@ -181,7 +181,8 @@ DeriveEq::visit_enum (Enum &item) case EnumItem::Kind::Discriminant: // nothing to do as they contain no inner types continue; - case EnumItem::Kind::Tuple: { + case EnumItem::Kind::Tuple: + { auto &tuple = static_cast (*variant); for (auto &field : tuple.get_tuple_fields ()) @@ -191,7 +192,8 @@ DeriveEq::visit_enum (Enum &item) } break; } - case EnumItem::Kind::Struct: { + case EnumItem::Kind::Struct: + { auto &tuple = static_cast (*variant); for (auto &field : tuple.get_struct_fields ()) diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc index 015b81e90df2..0e8a67c17a34 100644 --- a/gcc/rust/expand/rust-derive.cc +++ b/gcc/rust/expand/rust-derive.cc @@ -79,7 +79,8 @@ DeriveVisitor::setup_impl_generics ( { switch (generic->get_kind ()) { - case GenericParam::Kind::Lifetime: { + case GenericParam::Kind::Lifetime: + { LifetimeParam &lifetime_param = (LifetimeParam &) *generic.get (); Lifetime l = builder.new_lifetime (lifetime_param.get_lifetime ()); @@ -91,7 +92,8 @@ DeriveVisitor::setup_impl_generics ( } break; - case GenericParam::Kind::Type: { + case GenericParam::Kind::Type: + { TypeParam &type_param = (TypeParam &) *generic.get (); std::unique_ptr associated_type = builder.single_type_path ( @@ -113,7 +115,8 @@ DeriveVisitor::setup_impl_generics ( } break; - case GenericParam::Kind::Const: { + case GenericParam::Kind::Const: + { rust_unreachable (); // TODO diff --git a/gcc/rust/expand/rust-expand-format-args.cc b/gcc/rust/expand/rust-expand-format-args.cc index af6182f627f8..bda28dd61ce8 100644 --- a/gcc/rust/expand/rust-expand-format-args.cc +++ b/gcc/rust/expand/rust-expand-format-args.cc @@ -85,11 +85,13 @@ expand_format_args (AST::FormatArgs &fmt, static_pieces.emplace_back ( builder.literal_string (node.string._0.to_string ())); break; - case ffi::Piece::Tag::NextArgument: { + case ffi::Piece::Tag::NextArgument: + { auto next_argument = node.next_argument._0; switch (node.next_argument._0.position.tag) { - case ffi::Position::Tag::ArgumentImplicitlyIs: { + case ffi::Position::Tag::ArgumentImplicitlyIs: + { auto idx = next_argument.position.argument_implicitly_is._0; auto trait = next_argument.format; auto arg = arguments.at (idx); diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h index ad237c07c2f4..b82040c0878a 100644 --- a/gcc/rust/expand/rust-expand-visitor.h +++ b/gcc/rust/expand/rust-expand-visitor.h @@ -28,14 +28,12 @@ namespace Rust { /** * Whether or not an attribute is a derive attribute */ -bool -is_derive (AST::Attribute &attr); +bool is_derive (AST::Attribute &attr); /** * Whether or not an attribute is builtin */ -bool -is_builtin (AST::Attribute &attr); +bool is_builtin (AST::Attribute &attr); class ExpandVisitor : public AST::DefaultASTVisitor { diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc index ca3c22e7f8b0..850c8ddb753b 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.cc +++ b/gcc/rust/expand/rust-macro-builtins-asm.cc @@ -796,7 +796,8 @@ expand_inline_asm_strings (InlineAsmContext inline_asm_ctx) auto next_argument = piece.next_argument._0; switch (piece.next_argument._0.position.tag) { - case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs: { + case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs: + { auto idx = next_argument.position.argument_implicitly_is._0; /*auto trait = next_argument.format;*/ /*auto arg = arguments.at (idx);*/ diff --git a/gcc/rust/expand/rust-macro-builtins-asm.h b/gcc/rust/expand/rust-macro-builtins-asm.h index 2bdaed5e08fb..3196a5ae184c 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.h +++ b/gcc/rust/expand/rust-macro-builtins-asm.h @@ -142,16 +142,16 @@ tl::expected parse_reg_operand_unexpected (InlineAsmContext inline_asm_ctx); WARN_UNUSED_RESULT -tl::optional -parse_asm (location_t invoc_locus, AST::MacroInvocData &invoc, - AST::InvocKind semicolon, AST::AsmKind is_global_asm); +tl::optional parse_asm (location_t invoc_locus, + AST::MacroInvocData &invoc, + AST::InvocKind semicolon, + AST::AsmKind is_global_asm); WARN_UNUSED_RESULT -bool -check_identifier (Parser &parser, std::string ident); +bool check_identifier (Parser &parser, std::string ident); -void -check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsm::Option option); +void check_and_set (InlineAsmContext &inline_asm_ctx, + AST::InlineAsm::Option option); // From rustc WARN_UNUSED_RESULT @@ -168,9 +168,9 @@ tl::optional parse_format_string (InlineAsmContext &inline_asm_ctx); WARN_UNUSED_RESULT -tl::optional -parse_label (Parser &parser, TokenId last_token_id, - InlineAsmContext &inline_asm_ctx); +tl::optional parse_label (Parser &parser, + TokenId last_token_id, + InlineAsmContext &inline_asm_ctx); // LLVM ASM bits @@ -188,17 +188,13 @@ class LlvmAsmContext {} }; -void -parse_llvm_outputs (LlvmAsmContext &ctx); +void parse_llvm_outputs (LlvmAsmContext &ctx); -void -parse_llvm_inputs (LlvmAsmContext &ctx); +void parse_llvm_inputs (LlvmAsmContext &ctx); -void -parse_llvm_clobbers (LlvmAsmContext &ctx); +void parse_llvm_clobbers (LlvmAsmContext &ctx); -void -parse_llvm_options (LlvmAsmContext &ctx); +void parse_llvm_options (LlvmAsmContext &ctx); WARN_UNUSED_RESULT tl::optional parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc, diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.h b/gcc/rust/expand/rust-macro-builtins-helpers.h index 429537e210a8..32cf58fd1bed 100644 --- a/gcc/rust/expand/rust-macro-builtins-helpers.h +++ b/gcc/rust/expand/rust-macro-builtins-helpers.h @@ -33,29 +33,23 @@ #include "rust-token.h" namespace Rust { -std::string -make_macro_path_str (BuiltinMacro kind); +std::string make_macro_path_str (BuiltinMacro kind); -std::vector> -check_for_eager_invocations ( +std::vector> check_for_eager_invocations ( std::vector> &expressions); // Shorthand function for creating unique_ptr tokens -std::unique_ptr -make_token (const TokenPtr tok); +std::unique_ptr make_token (const TokenPtr tok); -std::unique_ptr -make_string (location_t locus, std::string value); +std::unique_ptr make_string (location_t locus, std::string value); // TODO: Is this correct? -AST::Fragment -make_eager_builtin_invocation ( +AST::Fragment make_eager_builtin_invocation ( BuiltinMacro kind, location_t locus, AST::DelimTokenTree arguments, std::vector> &&pending_invocations); // Match the end token of a macro given the start delimiter of the macro -TokenId -macro_end_token (AST::DelimTokenTree &invoc_token_tree, - Parser &parser); +TokenId macro_end_token (AST::DelimTokenTree &invoc_token_tree, + Parser &parser); // Expand and then extract a string literal from the macro std::unique_ptr try_extract_string_literal_from_fragment (const location_t &parent_locus, @@ -70,21 +64,18 @@ try_expand_many_expr (Parser &parser, // and return the LiteralExpr for it. Allow for an optional trailing comma, // but otherwise enforce that these are the only tokens. -std::unique_ptr -parse_single_string_literal (BuiltinMacro kind, - AST::DelimTokenTree &invoc_token_tree, - location_t invoc_locus, MacroExpander *expander, - bool is_semicoloned = false); +std::unique_ptr parse_single_string_literal ( + BuiltinMacro kind, AST::DelimTokenTree &invoc_token_tree, + location_t invoc_locus, MacroExpander *expander, bool is_semicoloned = false); // Treat PATH as a path relative to the source file currently being // compiled, and return the absolute path for it. -std::string -source_relative_path (std::string path, location_t locus); +std::string source_relative_path (std::string path, location_t locus); // Read the full contents of the file FILENAME and return them in a vector. // FIXME: platform specific. -tl::optional> -load_file_bytes (location_t invoc_locus, const char *filename); +tl::optional> load_file_bytes (location_t invoc_locus, + const char *filename); } // namespace Rust #endif // GCCRS_RUST_MACRO_BUILTINS_HELPERS_H diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 673b8fb20fa3..475ad56a3640 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -430,7 +430,8 @@ MacroExpander::match_fragment (Parser &parser, parser.parse_visibility (); break; - case AST::MacroFragSpec::STMT: { + case AST::MacroFragSpec::STMT: + { auto restrictions = ParseRestrictions (); restrictions.consume_semi = false; parser.parse_stmt (restrictions); @@ -480,19 +481,22 @@ MacroExpander::match_matcher (Parser &parser, // this is used so we can check that we delimit the stream correctly. switch (delimiter->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { if (!check_delim (AST::DelimType::PARENS)) return false; } break; - case LEFT_SQUARE: { + case LEFT_SQUARE: + { if (!check_delim (AST::DelimType::SQUARE)) return false; } break; - case LEFT_CURLY: { + case LEFT_CURLY: + { if (!check_delim (AST::DelimType::CURLY)) return false; } @@ -510,7 +514,8 @@ MacroExpander::match_matcher (Parser &parser, switch (match->get_macro_match_type ()) { - case AST::MacroMatch::MacroMatchType::Fragment: { + case AST::MacroMatch::MacroMatchType::Fragment: + { AST::MacroMatchFragment *fragment = static_cast (match.get ()); if (!match_fragment (parser, *fragment)) @@ -524,14 +529,16 @@ MacroExpander::match_matcher (Parser &parser, } break; - case AST::MacroMatch::MacroMatchType::Tok: { + case AST::MacroMatch::MacroMatchType::Tok: + { AST::Token *tok = static_cast (match.get ()); if (!match_token (parser, *tok)) return false; } break; - case AST::MacroMatch::MacroMatchType::Repetition: { + case AST::MacroMatch::MacroMatchType::Repetition: + { AST::MacroMatchRepetition *rep = static_cast (match.get ()); if (!match_repetition (parser, *rep)) @@ -539,7 +546,8 @@ MacroExpander::match_matcher (Parser &parser, } break; - case AST::MacroMatch::MacroMatchType::Matcher: { + case AST::MacroMatch::MacroMatchType::Matcher: + { AST::MacroMatcher *m = static_cast (match.get ()); expansion_depth++; @@ -556,19 +564,22 @@ MacroExpander::match_matcher (Parser &parser, switch (delimiter->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { if (!parser.skip_token (RIGHT_PAREN)) return false; } break; - case LEFT_SQUARE: { + case LEFT_SQUARE: + { if (!parser.skip_token (RIGHT_SQUARE)) return false; } break; - case LEFT_CURLY: { + case LEFT_CURLY: + { if (!parser.skip_token (RIGHT_CURLY)) return false; } @@ -617,7 +628,8 @@ MacroExpander::match_n_matches (Parser &parser, size_t offs_begin = source.get_offs (); switch (match->get_macro_match_type ()) { - case AST::MacroMatch::MacroMatchType::Fragment: { + case AST::MacroMatch::MacroMatchType::Fragment: + { AST::MacroMatchFragment *fragment = static_cast (match.get ()); valid_current_match = match_fragment (parser, *fragment); @@ -632,20 +644,23 @@ MacroExpander::match_n_matches (Parser &parser, } break; - case AST::MacroMatch::MacroMatchType::Tok: { + case AST::MacroMatch::MacroMatchType::Tok: + { AST::Token *tok = static_cast (match.get ()); valid_current_match = match_token (parser, *tok); } break; - case AST::MacroMatch::MacroMatchType::Repetition: { + case AST::MacroMatch::MacroMatchType::Repetition: + { AST::MacroMatchRepetition *rep = static_cast (match.get ()); valid_current_match = match_repetition (parser, *rep); } break; - case AST::MacroMatch::MacroMatchType::Matcher: { + case AST::MacroMatch::MacroMatchType::Matcher: + { AST::MacroMatcher *m = static_cast (match.get ()); valid_current_match = match_matcher (parser, *m, true); diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc index 02e4e3b1c5ae..ac36ed8b0451 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.cc +++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc @@ -273,7 +273,8 @@ SubstituteCtx::substitute_token (size_t token_idx) // don't substitute, dollar sign is alone/metavar is unknown return {std::vector> (), 0}; - case LEFT_PAREN: { + case LEFT_PAREN: + { // We need to parse up until the closing delimiter and expand this // fragment->n times. rust_debug ("expanding repetition"); diff --git a/gcc/rust/expand/rust-proc-macro.h b/gcc/rust/expand/rust-proc-macro.h index 6ffaaf6c099f..058c93aa434b 100644 --- a/gcc/rust/expand/rust-proc-macro.h +++ b/gcc/rust/expand/rust-proc-macro.h @@ -82,11 +82,9 @@ class CustomDeriveProcMacro * * @param The path to the shared object file to load. */ -const std::vector -load_macros (std::string path); +const std::vector load_macros (std::string path); -std::string -generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id); +std::string generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id); } // namespace Rust diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index 2d9a4450c901..b7d3224f2c22 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -648,12 +648,14 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args) { switch (arg.get_kind ()) { - case AST::GenericArg::Kind::Type: { + case AST::GenericArg::Kind::Type: + { auto type = ASTLoweringType::translate (arg.get_type ()); type_args.emplace_back (std::unique_ptr (type)); break; } - case AST::GenericArg::Kind::Const: { + case AST::GenericArg::Kind::Const: + { auto expr = ASTLoweringExpr::translate (arg.get_expression ()); const_args.emplace_back ( HIR::ConstGenericArg (std::unique_ptr (expr), @@ -887,7 +889,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound) std::unique_ptr hir_bound = nullptr; switch (bound.get_bound_type ()) { - case AST::RangePatternBound::RangePatternBoundType::LITERAL: { + case AST::RangePatternBound::RangePatternBoundType::LITERAL: + { AST::RangePatternBoundLiteral &ref = static_cast (bound); @@ -898,7 +901,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound) ref.get_has_minus ())); } break; - case AST::RangePatternBound::RangePatternBoundType::PATH: { + case AST::RangePatternBound::RangePatternBoundType::PATH: + { auto &ref = static_cast (bound); HIR::PathInExpression *path @@ -908,7 +912,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound) new HIR::RangePatternBoundPath (*path)); } break; - case AST::RangePatternBound::RangePatternBoundType::QUALPATH: { + case AST::RangePatternBound::RangePatternBoundType::QUALPATH: + { auto &ref = static_cast (bound); HIR::QualifiedPathInExpression *qualpath diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc index 66ccafa4f522..acec008c8923 100644 --- a/gcc/rust/hir/rust-ast-lower-item.cc +++ b/gcc/rust/hir/rust-ast-lower-item.cc @@ -495,7 +495,8 @@ ASTLoweringItem::visit (AST::InherentImpl &impl_block) { switch (generic_param->get_kind ()) { - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { const HIR::TypeParam &t = static_cast (*generic_param); @@ -652,7 +653,8 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block) { switch (generic_param->get_kind ()) { - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { const HIR::TypeParam &t = static_cast (*generic_param); diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc index b7a4c564782b..9be36c8f2a09 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.cc +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -74,13 +74,15 @@ ASTLoweringPattern::visit (AST::TupleStructPattern &pattern) auto &items = pattern.get_items (); switch (items.get_item_type ()) { - case AST::TupleStructItems::RANGE: { + case AST::TupleStructItems::RANGE: + { // TODO rust_unreachable (); } break; - case AST::TupleStructItems::NO_RANGE: { + case AST::TupleStructItems::NO_RANGE: + { AST::TupleStructItemsNoRange &items_no_range = static_cast (items); @@ -120,7 +122,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) HIR::StructPatternField *f = nullptr; switch (field->get_item_type ()) { - case AST::StructPatternField::ItemType::TUPLE_PAT: { + case AST::StructPatternField::ItemType::TUPLE_PAT: + { auto &tuple = static_cast (*field); @@ -140,7 +143,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) } break; - case AST::StructPatternField::ItemType::IDENT_PAT: { + case AST::StructPatternField::ItemType::IDENT_PAT: + { AST::StructPatternFieldIdentPat &ident = static_cast (*field); @@ -160,7 +164,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) } break; - case AST::StructPatternField::ItemType::IDENT: { + case AST::StructPatternField::ItemType::IDENT: + { AST::StructPatternFieldIdent &ident = static_cast (*field.get ()); @@ -213,7 +218,8 @@ ASTLoweringPattern::visit (AST::TuplePattern &pattern) std::unique_ptr items; switch (pattern.get_items ().get_pattern_type ()) { - case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: { + case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: + { AST::TuplePatternItemsMultiple &ref = static_cast ( pattern.get_items ()); @@ -221,7 +227,8 @@ ASTLoweringPattern::visit (AST::TuplePattern &pattern) } break; - case AST::TuplePatternItems::TuplePatternItemType::RANGED: { + case AST::TuplePatternItems::TuplePatternItemType::RANGED: + { AST::TuplePatternItemsRanged &ref = static_cast (pattern.get_items ()); items = lower_tuple_pattern_ranged (ref); diff --git a/gcc/rust/hir/rust-ast-lower.h b/gcc/rust/hir/rust-ast-lower.h index cc7408277a31..0787ddfd0a32 100644 --- a/gcc/rust/hir/rust-ast-lower.h +++ b/gcc/rust/hir/rust-ast-lower.h @@ -28,16 +28,14 @@ namespace HIR { /* Checks whether the name of a field already exists. Returns true and produces an error if so. */ -bool -struct_field_name_exists (std::vector &fields, - HIR::StructField &new_field); +bool struct_field_name_exists (std::vector &fields, + HIR::StructField &new_field); /** * Lowers a Visibility from the AST into an HIR Visibility, desugaring it in * the process */ -Visibility -translate_visibility (const AST::Visibility &vis); +Visibility translate_visibility (const AST::Visibility &vis); /** * Main base class used for lowering AST to HIR. diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index cb32f68ab965..96cd65640572 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -1602,7 +1602,8 @@ Dump::visit (UseTreeGlob &e) case UseTreeGlob::PathType::GLOBAL: glob = "::*"; break; - case UseTreeGlob::PathType::PATH_PREFIXED: { + case UseTreeGlob::PathType::PATH_PREFIXED: + { path = e.get_path ().as_string (); glob = "::*"; break; @@ -1630,7 +1631,8 @@ Dump::visit (UseTreeList &e) case UseTreeList::PathType::GLOBAL: path_type = "::*"; break; - case UseTreeList::PathType::PATH_PREFIXED: { + case UseTreeList::PathType::PATH_PREFIXED: + { path = e.get_path ().as_string (); path_type = "::*"; break; diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h index 45b17080e696..a1b89ca58741 100644 --- a/gcc/rust/hir/rust-hir-dump.h +++ b/gcc/rust/hir/rust-hir-dump.h @@ -252,7 +252,6 @@ class Dump : public HIRFullVisitor } // namespace Rust // In the global namespace to make it easier to call from debugger -void -debug (Rust::HIR::FullVisitable &v); +void debug (Rust::HIR::FullVisitable &v); #endif // !RUST_HIR_DUMP_H diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index 093d8d50146e..9c8293bd6036 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -577,7 +577,8 @@ UseTreeGlob::as_string () const return "*"; case GLOBAL: return "::*"; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { std::string path_str = path.as_string (); return path_str + "::*"; } @@ -600,7 +601,8 @@ UseTreeList::as_string () const case GLOBAL: path_str = "::{"; break; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { path_str = path.as_string () + "::{"; break; } diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index b143e70c9464..8a5668f38589 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -1317,7 +1317,8 @@ Lexer::parse_escape (char opening_char) switch (current_char.value) { - case 'x': { + case 'x': + { auto hex_escape_pair = parse_partial_hex_escape (); long hexLong = hex_escape_pair.first; additional_length_offset += hex_escape_pair.second; @@ -1400,7 +1401,8 @@ Lexer::parse_utf8_escape () switch (current_char.value) { - case 'x': { + case 'x': + { auto hex_escape_pair = parse_partial_hex_escape (); long hexLong = hex_escape_pair.first; additional_length_offset += hex_escape_pair.second; @@ -1438,7 +1440,8 @@ Lexer::parse_utf8_escape () case '"': output_char = '"'; break; - case 'u': { + case 'u': + { auto unicode_escape_pair = parse_partial_unicode_escape (); output_char = unicode_escape_pair.first; additional_length_offset += unicode_escape_pair.second; diff --git a/gcc/rust/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h index 10293e0a8122..383ffac22558 100644 --- a/gcc/rust/lex/rust-lex.h +++ b/gcc/rust/lex/rust-lex.h @@ -263,8 +263,7 @@ class Lexer #if CHECKING_P namespace selftest { -void -rust_input_source_test (); +void rust_input_source_test (); } // namespace selftest diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc index 8493889db9f1..783638b41717 100644 --- a/gcc/rust/lex/rust-token.cc +++ b/gcc/rust/lex/rust-token.cc @@ -88,7 +88,8 @@ token_id_keyword_string (TokenId id) switch (id) { #define RS_TOKEN_KEYWORD_2015(id, str_ptr) \ - case id: { \ + case id: \ + { \ static const std::string str (str_ptr); \ return str; \ } \ diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index c683ecd446ee..2abdf27f6c3b 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -221,25 +221,20 @@ typedef std::shared_ptr TokenPtr; typedef std::shared_ptr const_TokenPtr; // Hackily defined way to get token description for enum value using x-macros -const char * -get_token_description (TokenId id); +const char *get_token_description (TokenId id); /* Hackily defined way to get token description as a string for enum value using * x-macros */ -const char * -token_id_to_str (TokenId id); +const char *token_id_to_str (TokenId id); /* checks if a token is a keyword */ -bool -token_id_is_keyword (TokenId id); +bool token_id_is_keyword (TokenId id); /* gets the string associated with a keyword */ -const std::string & -token_id_keyword_string (TokenId id); +const std::string &token_id_keyword_string (TokenId id); // Get type hint description as a string. -const char * -get_type_hint_string (PrimitiveCoreType type); +const char *get_type_hint_string (PrimitiveCoreType type); /* Normalize string if a token is a identifier */ -std::string -nfc_normalize_token_string (location_t loc, TokenId id, const std::string &str); +std::string nfc_normalize_token_string (location_t loc, TokenId id, + const std::string &str); // Represents a single token. Create using factory static methods. class Token diff --git a/gcc/rust/metadata/rust-export-metadata.cc b/gcc/rust/metadata/rust-export-metadata.cc index 771bec6e6378..1829a85d2e47 100644 --- a/gcc/rust/metadata/rust-export-metadata.cc +++ b/gcc/rust/metadata/rust-export-metadata.cc @@ -263,8 +263,7 @@ PublicInterface::write_to_path (const std::string &path) const FILE *nfd = fopen (path.c_str (), "wb"); if (nfd == NULL) { - rust_error_at (UNDEF_LOCATION, - "failed to open file %qs for writing: %s", + rust_error_at (UNDEF_LOCATION, "failed to open file %qs for writing: %s", path.c_str (), xstrerror (errno)); return; } diff --git a/gcc/rust/metadata/rust-import-archive.cc b/gcc/rust/metadata/rust-import-archive.cc index cf24607f099c..f64de4e061ce 100644 --- a/gcc/rust/metadata/rust-import-archive.cc +++ b/gcc/rust/metadata/rust-import-archive.cc @@ -683,7 +683,7 @@ class Archive_iterator const Header &operator* () const { return this->header_; } - const Header *operator-> () const { return &this->header_; } + const Header *operator->() const { return &this->header_; } Archive_iterator &operator++ () { diff --git a/gcc/rust/metadata/rust-imports.h b/gcc/rust/metadata/rust-imports.h index a497c6745174..65a2af11c0da 100644 --- a/gcc/rust/metadata/rust-imports.h +++ b/gcc/rust/metadata/rust-imports.h @@ -11,8 +11,7 @@ namespace Rust { -extern void -add_search_path (const std::string &path); +extern void add_search_path (const std::string &path); class Import { diff --git a/gcc/rust/parse/rust-cfg-parser.h b/gcc/rust/parse/rust-cfg-parser.h index 0d64016f86dc..61db240a3672 100644 --- a/gcc/rust/parse/rust-cfg-parser.h +++ b/gcc/rust/parse/rust-cfg-parser.h @@ -36,15 +36,14 @@ namespace Rust { * * @return false if the given input was invalid, true otherwise */ -bool -parse_cfg_option (std::string &input, std::string &key, std::string &value); +bool parse_cfg_option (std::string &input, std::string &key, + std::string &value); } // namespace Rust #if CHECKING_P namespace selftest { -extern void -rust_cfg_parser_test (void); +extern void rust_cfg_parser_test (void); } // namespace selftest #endif // CHECKING_P diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 3a2fcd214744..b661040a7159 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -227,19 +227,22 @@ Parser::skip_generics_right_angle () // this is good - skip token lexer.skip_token (); return true; - case RIGHT_SHIFT: { + case RIGHT_SHIFT: + { // new implementation that should be better lexer.split_current_token (RIGHT_ANGLE, RIGHT_ANGLE); lexer.skip_token (); return true; } - case GREATER_OR_EQUAL: { + case GREATER_OR_EQUAL: + { // new implementation that should be better lexer.split_current_token (RIGHT_ANGLE, EQUAL); lexer.skip_token (); return true; } - case RIGHT_SHIFT_EQ: { + case RIGHT_SHIFT_EQ: + { // new implementation that should be better lexer.split_current_token (RIGHT_ANGLE, GREATER_OR_EQUAL); lexer.skip_token (); @@ -790,7 +793,8 @@ Parser::parse_attr_input () { case LEFT_PAREN: case LEFT_SQUARE: - case LEFT_CURLY: { + case LEFT_CURLY: + { // must be a delimited token tree, so parse that std::unique_ptr input_tree ( new AST::DelimTokenTree (parse_delim_token_tree ())); @@ -799,7 +803,8 @@ Parser::parse_attr_input () return input_tree; } - case EQUAL: { + case EQUAL: + { // = LiteralExpr lexer.skip_token (); @@ -2120,7 +2125,8 @@ Parser::parse_macro_match () { case LEFT_PAREN: case LEFT_SQUARE: - case LEFT_CURLY: { + case LEFT_CURLY: + { // must be macro matcher as delimited AST::MacroMatcher matcher = parse_macro_matcher (); if (matcher.is_error ()) @@ -2134,7 +2140,8 @@ Parser::parse_macro_match () return std::unique_ptr ( new AST::MacroMatcher (std::move (matcher))); } - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { // have to do more lookahead to determine if fragment or repetition const_TokenPtr t2 = lexer.peek_token (1); switch (t2->get_id ()) @@ -2405,7 +2412,8 @@ Parser::parse_visibility () skip_token (RIGHT_PAREN); return AST::Visibility::create_super (path_loc, vis_loc); - case IN: { + case IN: + { lexer.skip_token (); // parse the "in" path as well @@ -2469,7 +2477,8 @@ Parser::parse_module (AST::Visibility vis, new AST::Module (std::move (name), std::move (vis), std::move (outer_attrs), locus, safety, lexer.get_filename (), inline_module_stack)); - case LEFT_CURLY: { + case LEFT_CURLY: + { lexer.skip_token (); // parse inner attributes @@ -2733,7 +2742,8 @@ Parser::parse_use_tree () return std::unique_ptr ( new AST::UseTreeGlob (AST::UseTreeGlob::NO_PATH, AST::SimplePath::create_empty (), locus)); - case LEFT_CURLY: { + case LEFT_CURLY: + { // nested tree UseTree type lexer.skip_token (); @@ -2811,7 +2821,8 @@ Parser::parse_use_tree () return std::unique_ptr ( new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED, std::move (path), locus)); - case LEFT_CURLY: { + case LEFT_CURLY: + { // nested tree UseTree type lexer.skip_token (); @@ -2848,7 +2859,8 @@ Parser::parse_use_tree () std::move (path), std::move (use_trees), locus)); } - case AS: { + case AS: + { // rebind UseTree type lexer.skip_token (); @@ -3103,7 +3115,8 @@ Parser::parse_generic_param (EndTokenPred is_end_token) switch (token->get_id ()) { - case LIFETIME: { + case LIFETIME: + { auto lifetime = parse_lifetime (false); if (!lifetime) { @@ -3129,7 +3142,8 @@ Parser::parse_generic_param (EndTokenPred is_end_token) std::move (outer_attrs), token->get_locus ())); break; } - case IDENTIFIER: { + case IDENTIFIER: + { auto type_ident = token->get_str (); lexer.skip_token (); @@ -3164,7 +3178,8 @@ Parser::parse_generic_param (EndTokenPred is_end_token) std::move (outer_attrs))); break; } - case CONST: { + case CONST: + { lexer.skip_token (); auto name_token = expect_token (IDENTIFIER); @@ -4359,7 +4374,8 @@ Parser::parse_struct (AST::Visibility vis, const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case LEFT_CURLY: { + case LEFT_CURLY: + { // struct with body // skip curly bracket @@ -4762,7 +4778,8 @@ Parser::parse_enum_item () const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { // tuple enum item lexer.skip_token (); @@ -4783,7 +4800,8 @@ Parser::parse_enum_item () std::move (item_name), std::move (vis), std::move (tuple_fields), std::move (outer_attrs), item_name_tok->get_locus ())); } - case LEFT_CURLY: { + case LEFT_CURLY: + { // struct enum item lexer.skip_token (); @@ -4800,7 +4818,8 @@ Parser::parse_enum_item () std::move (item_name), std::move (vis), std::move (struct_fields), std::move (outer_attrs), item_name_tok->get_locus ())); } - case EQUAL: { + case EQUAL: + { // discriminant enum item lexer.skip_token (); @@ -5453,7 +5472,8 @@ Parser::parse_inherent_impl_item () case SUPER: case SELF: case CRATE: - case PUB: { + case PUB: + { // visibility, so not a macro invocation semi - must be constant, // function, or method AST::Visibility vis = parse_visibility (); @@ -5967,7 +5987,8 @@ Parser::parse_external_item () { case IDENTIFIER: return parse_macro_invocation_semi (outer_attrs); - case STATIC_KW: { + case STATIC_KW: + { // parse extern static item lexer.skip_token (); @@ -6264,7 +6285,8 @@ Parser::parse_generic_arg () switch (tok->get_id ()) { - case IDENTIFIER: { + case IDENTIFIER: + { // This is a bit of a weird situation: With an identifier token, we // could either have a valid type or a macro (FIXME: anything else?). So // we need one bit of lookahead to differentiate if this is really @@ -6312,9 +6334,10 @@ Parser::parse_generic_arg () case FALSE_LITERAL: expr = parse_literal_expr (); break; - // FIXME: Because of this, error reporting is garbage for const generic - // parameter's default values - default: { + // FIXME: Because of this, error reporting is garbage for const generic + // parameter's default values + default: + { auto type = parse_type (); // FIXME: Find a better way to do this? if (type) @@ -6513,7 +6536,8 @@ Parser::parse_type_path_segment () switch (t->get_id ()) { case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // parse generic args AST::GenericArgs generic_args = parse_path_generic_args (); @@ -6522,7 +6546,8 @@ Parser::parse_type_path_segment () has_separating_scope_resolution, std::move (generic_args), locus)); } - case LEFT_PAREN: { + case LEFT_PAREN: + { // parse type path function AST::TypePathFunction type_path_function = parse_type_path_function (locus); @@ -7071,7 +7096,8 @@ Parser::parse_expr_stmt (AST::AttrVec outer_attrs, case SELF: case SELF_ALIAS: case DOLLAR_SIGN: - case SCOPE_RESOLUTION: { + case SCOPE_RESOLUTION: + { AST::PathInExpression path = parse_path_in_expression (); std::unique_ptr null_denotation; @@ -7678,7 +7704,8 @@ Parser::parse_if_expr (AST::AttrVec outer_attrs, const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case LEFT_CURLY: { + case LEFT_CURLY: + { // double selection - else // parse else block expr (required) std::unique_ptr else_body = parse_block_expr (); @@ -7699,7 +7726,8 @@ Parser::parse_if_expr (AST::AttrVec outer_attrs, std::move (else_body), std::move (outer_attrs), locus)); } - case IF: { + case IF: + { // multiple selection - else if or else if let // branch on whether next token is 'let' or not if (lexer.peek_token (1)->get_id () == LET) @@ -7860,7 +7888,8 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case LEFT_CURLY: { + case LEFT_CURLY: + { // double selection - else // parse else block expr (required) std::unique_ptr else_body = parse_block_expr (); @@ -7882,7 +7911,8 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, std::move (else_body), std::move (outer_attrs), locus)); } - case IF: { + case IF: + { // multiple selection - else if or else if let // branch on whether next token is 'let' or not if (lexer.peek_token (1)->get_id () == LET) @@ -8934,7 +8964,8 @@ Parser::parse_type (bool save_errors) // slice type or array type - requires further disambiguation return parse_slice_or_array_type (); case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path in type AST::QualifiedPathInType path = parse_qualified_path_in_type (); if (path.is_error ()) @@ -8963,7 +8994,8 @@ Parser::parse_type (bool save_errors) case LOGICAL_AND: // reference type return parse_reference_type (); - case LIFETIME: { + case LIFETIME: + { /* probably a lifetime bound, so probably type param bounds in * TraitObjectType */ std::vector> bounds @@ -8979,7 +9011,8 @@ Parser::parse_type (bool save_errors) case SELF_ALIAS: case CRATE: case DOLLAR_SIGN: - case SCOPE_RESOLUTION: { + case SCOPE_RESOLUTION: + { // macro invocation or type path - requires further disambiguation. /* for parsing path component of each rule, perhaps parse it as a * typepath and attempt conversion to simplepath if a trailing '!' is @@ -9009,7 +9042,8 @@ Parser::parse_type (bool save_errors) t = lexer.peek_token (); switch (t->get_id ()) { - case EXCLAM: { + case EXCLAM: + { // macro invocation // convert to simple path AST::SimplePath macro_path = path.as_simple_path (); @@ -9035,7 +9069,8 @@ Parser::parse_type (bool save_errors) std::move (tok_tree)), {}, locus); } - case PLUS: { + case PLUS: + { // type param bounds std::vector> bounds; @@ -9149,7 +9184,8 @@ Parser::parse_type (bool save_errors) new AST::ImplTraitType (std::move (bounds), locus)); } case DYN: - case QUESTION_MARK: { + case QUESTION_MARK: + { // either TraitObjectType or TraitObjectTypeOneBound bool has_dyn = false; if (t->get_id () == DYN) @@ -9402,7 +9438,8 @@ Parser::parse_for_prefixed_type () case SELF: case SELF_ALIAS: case CRATE: - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { // path, so trait type // parse type path to finish parsing trait bound @@ -9748,7 +9785,8 @@ Parser::parse_slice_or_array_type () return std::unique_ptr ( new AST::SliceType (std::move (inner_type), locus)); - case SEMICOLON: { + case SEMICOLON: + { // array type lexer.skip_token (); @@ -9799,7 +9837,8 @@ Parser::parse_type_no_bounds () // slice type or array type - requires further disambiguation return parse_slice_or_array_type (); case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path in type AST::QualifiedPathInType path = parse_qualified_path_in_type (); if (path.is_error ()) @@ -9840,7 +9879,8 @@ Parser::parse_type_no_bounds () case SELF_ALIAS: case CRATE: case DOLLAR_SIGN: - case SCOPE_RESOLUTION: { + case SCOPE_RESOLUTION: + { // macro invocation or type path - requires further disambiguation. /* for parsing path component of each rule, perhaps parse it as a * typepath and attempt conversion to simplepath if a trailing '!' is @@ -9868,7 +9908,8 @@ Parser::parse_type_no_bounds () t = lexer.peek_token (); switch (t->get_id ()) { - case EXCLAM: { + case EXCLAM: + { // macro invocation // convert to simple path AST::SimplePath macro_path = path.as_simple_path (); @@ -9956,7 +9997,8 @@ Parser::parse_type_no_bounds () new AST::ImplTraitTypeOneBound (std::move (initial_bound), locus)); } case DYN: - case QUESTION_MARK: { + case QUESTION_MARK: + { // either TraitObjectTypeOneBound bool has_dyn = false; if (t->get_id () == DYN) @@ -10297,7 +10339,8 @@ Parser::parse_range_pattern_bound () case SELF_ALIAS: case CRATE: case SCOPE_RESOLUTION: - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { // path in expression AST::PathInExpression path = parse_path_in_expression (); if (path.is_error ()) @@ -10313,7 +10356,8 @@ Parser::parse_range_pattern_bound () new AST::RangePatternBoundPath (std::move (path))); } case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path in expression AST::QualifiedPathInExpression path = parse_qualified_path_in_expression (); @@ -10458,7 +10502,8 @@ Parser::parse_pattern_no_alt () // slice pattern return parse_slice_pattern (); case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path in expression or qualified range pattern bound AST::QualifiedPathInExpression path = parse_qualified_path_in_expression (); @@ -10494,7 +10539,8 @@ Parser::parse_pattern_no_alt () case SELF_ALIAS: case CRATE: case SCOPE_RESOLUTION: - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { // path in expression or range pattern bound AST::PathInExpression path = parse_path_in_expression (); @@ -10503,7 +10549,8 @@ Parser::parse_pattern_no_alt () { case DOT_DOT_EQ: case DOT_DOT: - case ELLIPSIS: { + case ELLIPSIS: + { // qualified range pattern bound, so parse rest of range pattern AST::RangeKind kind = AST::tokenid_to_rangekind (next->get_id ()); lexer.skip_token (); @@ -10521,7 +10568,8 @@ Parser::parse_pattern_no_alt () case EXCLAM: return parse_macro_invocation_partial (std::move (path), AST::AttrVec ()); - case LEFT_PAREN: { + case LEFT_PAREN: + { // tuple struct lexer.skip_token (); @@ -10546,7 +10594,8 @@ Parser::parse_pattern_no_alt () new AST::TupleStructPattern (std::move (path), std::move (items))); } - case LEFT_CURLY: { + case LEFT_CURLY: + { // struct lexer.skip_token (); @@ -10716,7 +10765,8 @@ Parser::parse_grouped_or_tuple_pattern () return std::unique_ptr ( new AST::GroupedPattern (std::move (initial_pattern), paren_locus)); - case COMMA: { + case COMMA: + { // tuple pattern lexer.skip_token (); @@ -10973,7 +11023,8 @@ Parser::parse_ident_leading_pattern () { case EXCLAM: return parse_macro_invocation_partial (std::move (path), AST::AttrVec ()); - case LEFT_PAREN: { + case LEFT_PAREN: + { // tuple struct lexer.skip_token (); @@ -11006,7 +11057,8 @@ Parser::parse_ident_leading_pattern () return std::unique_ptr ( new AST::TupleStructPattern (std::move (path), std::move (items))); } - case LEFT_CURLY: { + case LEFT_CURLY: + { // struct lexer.skip_token (); @@ -11027,7 +11079,8 @@ Parser::parse_ident_leading_pattern () } case DOT_DOT_EQ: case DOT_DOT: - case ELLIPSIS: { + case ELLIPSIS: + { // range AST::RangeKind kind = AST::tokenid_to_rangekind (lexer.peek_token ()->get_id ()); @@ -11044,7 +11097,8 @@ Parser::parse_ident_leading_pattern () std::move (upper_bound), kind, t->get_locus ())); } - case PATTERN_BIND: { + case PATTERN_BIND: + { // only allow on single-segment paths if (path.is_single_segment ()) { @@ -11182,7 +11236,8 @@ Parser::parse_tuple_struct_items () case RIGHT_PAREN: return std::unique_ptr ( new AST::TupleStructItemsNoRange (std::move (lower_patterns))); - case DOT_DOT: { + case DOT_DOT: + { // has an upper range that must be parsed separately lexer.skip_token (); @@ -11302,7 +11357,8 @@ Parser::parse_struct_pattern_field_partial ( const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case INT_LITERAL: { + case INT_LITERAL: + { // tuple index std::string index_str = t->get_str (); int index = atoi (index_str.c_str ()); @@ -11336,7 +11392,8 @@ Parser::parse_struct_pattern_field_partial ( // branch on next token switch (lexer.peek_token (1)->get_id ()) { - case COLON: { + case COLON: + { // identifier-pattern Identifier ident{t}; lexer.skip_token (); @@ -11361,7 +11418,8 @@ Parser::parse_struct_pattern_field_partial ( t->get_locus ())); } case COMMA: - case RIGHT_CURLY: { + case RIGHT_CURLY: + { // identifier only Identifier ident = {t}; lexer.skip_token (); @@ -11380,7 +11438,8 @@ Parser::parse_struct_pattern_field_partial ( return nullptr; } case REF: - case MUT: { + case MUT: + { // only identifier bool has_ref = false; if (t->get_id () == REF) @@ -11452,7 +11511,8 @@ Parser::parse_stmt_or_expr () t = lexer.peek_token (); switch (t->get_id ()) { - case LET: { + case LET: + { // let statement std::unique_ptr stmt ( parse_let_stmt (std::move (outer_attrs))); @@ -11470,42 +11530,48 @@ Parser::parse_stmt_or_expr () case STATIC_KW: case AUTO: case TRAIT: - case IMPL: { + case IMPL: + { std::unique_ptr item ( parse_vis_item (std::move (outer_attrs))); return ExprOrStmt (std::move (item)); } - /* TODO: implement union keyword but not really because of - * context-dependence crappy hack way to parse a union written below to - * separate it from the good code. */ - // case UNION: - case UNSAFE: { // maybe - unsafe traits are a thing + /* TODO: implement union keyword but not really because of + * context-dependence crappy hack way to parse a union written below to + * separate it from the good code. */ + // case UNION: + case UNSAFE: + { // maybe - unsafe traits are a thing /* if any of these (should be all possible VisItem prefixes), parse a * VisItem - can't parse item because would require reparsing outer * attributes */ const_TokenPtr t2 = lexer.peek_token (1); switch (t2->get_id ()) { - case LEFT_CURLY: { + case LEFT_CURLY: + { // unsafe block: parse as expression expr = parse_expr (std::move (outer_attrs), restrictions); break; } case AUTO: - case TRAIT: { + case TRAIT: + { // unsafe trait std::unique_ptr item ( parse_vis_item (std::move (outer_attrs))); return ExprOrStmt (std::move (item)); } case EXTERN_KW: - case FN_KW: { + case FN_KW: + { // unsafe function std::unique_ptr item ( parse_vis_item (std::move (outer_attrs))); return ExprOrStmt (std::move (item)); } - case IMPL: { + case IMPL: + { // unsafe trait impl std::unique_ptr item ( parse_vis_item (std::move (outer_attrs))); @@ -11550,7 +11616,8 @@ Parser::parse_stmt_or_expr () case SELF_ALIAS: case CRATE: case SCOPE_RESOLUTION: - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { AST::PathInExpression path = parse_path_in_expression (); std::unique_ptr null_denotation; @@ -11674,7 +11741,8 @@ Parser::parse_struct_expr_field () std::move (outer_attrs), t->get_locus ())); } - case INT_LITERAL: { + case INT_LITERAL: + { // parse tuple index field int index = atoi (t->get_str ().c_str ()); lexer.skip_token (); @@ -12044,7 +12112,8 @@ Parser::null_denotation (const_TokenPtr tok, case SELF_ALIAS: case DOLLAR_SIGN: case CRATE: - case SUPER: { + case SUPER: + { // DEBUG rust_debug ("beginning null denotation identifier handling"); @@ -12055,7 +12124,8 @@ Parser::null_denotation (const_TokenPtr tok, return null_denotation_path (std::move (path), std::move (outer_attrs), restrictions); } - case SCOPE_RESOLUTION: { + case SCOPE_RESOLUTION: + { // TODO: fix: this is for global paths, i.e. std::string::whatever Error error (tok->get_locus (), "found null denotation scope resolution operator, and " @@ -12097,7 +12167,8 @@ Parser::null_denotation_path ( // macro return parse_macro_invocation_partial (std::move (path), std::move (outer_attrs)); - case LEFT_CURLY: { + case LEFT_CURLY: + { bool not_a_block = lexer.peek_token (1)->get_id () == IDENTIFIER && (lexer.peek_token (2)->get_id () == COMMA || (lexer.peek_token (2)->get_id () == COLON @@ -12173,7 +12244,8 @@ Parser::null_denotation_not_path ( { // FIXME: Handle in null_denotation_path? case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path // HACK: add outer attrs to path AST::QualifiedPathInExpression path @@ -12231,23 +12303,24 @@ Parser::null_denotation_not_path ( return parse_grouped_or_tuple_expr (std::move (outer_attrs), tok->get_locus ()); - /*case PLUS: { // unary plus operator - // invoke parse_expr recursively with appropriate priority, etc. for - below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS); + /*case PLUS: { // unary plus operator + // invoke parse_expr recursively with appropriate priority, etc. for + below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS); - if (expr == nullptr) - return nullptr; - // can only apply to integer and float expressions - if (expr->get_type() != integer_type_node || expr->get_type() != - float_type_node) { rust_error_at(tok->get_locus(), "operand of unary - plus must be int or float but it is %s", print_type(expr->get_type())); - return nullptr; - } + if (expr == nullptr) + return nullptr; + // can only apply to integer and float expressions + if (expr->get_type() != integer_type_node || expr->get_type() != + float_type_node) { rust_error_at(tok->get_locus(), "operand of unary + plus must be int or float but it is %s", print_type(expr->get_type())); + return nullptr; + } - return Tree(expr, tok->get_locus()); - }*/ - // Rust has no unary plus operator - case MINUS: { // unary minus + return Tree(expr, tok->get_locus()); + }*/ + // Rust has no unary plus operator + case MINUS: + { // unary minus ParseRestrictions entered_from_unary; entered_from_unary.entered_from_unary = true; if (!restrictions.can_be_struct_expr) @@ -12274,7 +12347,8 @@ Parser::null_denotation_not_path ( new AST::NegationExpr (std::move (expr), NegationOperator::NEGATE, std::move (outer_attrs), tok->get_locus ())); } - case EXCLAM: { // logical or bitwise not + case EXCLAM: + { // logical or bitwise not ParseRestrictions entered_from_unary; entered_from_unary.entered_from_unary = true; if (!restrictions.can_be_struct_expr) @@ -12299,7 +12373,8 @@ Parser::null_denotation_not_path ( new AST::NegationExpr (std::move (expr), NegationOperator::NOT, std::move (outer_attrs), tok->get_locus ())); } - case ASTERISK: { + case ASTERISK: + { /* pointer dereference only - HACK: as struct expressions should * always be value expressions, cannot be dereferenced */ ParseRestrictions entered_from_unary; @@ -12312,7 +12387,8 @@ Parser::null_denotation_not_path ( new AST::DereferenceExpr (std::move (expr), std::move (outer_attrs), tok->get_locus ())); } - case AMP: { + case AMP: + { // (single) "borrow" expression - shared (mutable) or immutable std::unique_ptr expr = nullptr; Mutability mutability = Mutability::Imm; @@ -12369,7 +12445,8 @@ Parser::null_denotation_not_path ( new AST::BorrowExpr (std::move (expr), mutability, raw_borrow, false, std::move (outer_attrs), tok->get_locus ())); } - case LOGICAL_AND: { + case LOGICAL_AND: + { // (double) "borrow" expression - shared (mutable) or immutable std::unique_ptr expr = nullptr; Mutability mutability = Mutability::Imm; @@ -12485,8 +12562,9 @@ Parser::left_denotation (const_TokenPtr tok, // Token passed in has already been skipped, so peek gives "next" token switch (tok->get_id ()) { - // FIXME: allow for outer attributes to be applied - case QUESTION_MARK: { + // FIXME: allow for outer attributes to be applied + case QUESTION_MARK: + { location_t left_locus = left->get_locus (); // error propagation expression - unary postfix return std::unique_ptr ( @@ -12740,7 +12818,8 @@ Parser::left_denotation (const_TokenPtr tok, "function - this should probably be handled elsewhere")); return nullptr; - case DOT: { + case DOT: + { /* field expression or method call - relies on parentheses after next * identifier or await if token after is "await" (unary postfix) or * tuple index if token after is a decimal int literal */ @@ -14056,7 +14135,8 @@ Parser::parse_struct_expr_struct_partial ( * algorithm should work too. As such, AST type not happening. */ case IDENTIFIER: case HASH: - case INT_LITERAL: { + case INT_LITERAL: + { // struct with struct expr fields // parse struct expr fields @@ -14353,7 +14433,8 @@ Parser::parse_closure_expr_pratt (const_TokenPtr tok, case OR: // no parameters, don't skip token break; - case PIPE: { + case PIPE: + { // actually may have parameters // don't skip token const_TokenPtr t = lexer.peek_token (); diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc index 43d15aa2bb9e..4895c6afdaa0 100644 --- a/gcc/rust/parse/rust-parse.cc +++ b/gcc/rust/parse/rust-parse.cc @@ -144,10 +144,9 @@ peculiar_fragment_match_compatible_fragment ( = contains (fragment_follow_set[last_spec.get_kind ()], spec.get_kind ()); if (!is_valid) - rust_error_at ( - match_locus, - "fragment specifier %qs is not allowed after %qs fragments", - spec.as_string ().c_str (), last_spec.as_string ().c_str ()); + rust_error_at (match_locus, + "fragment specifier %qs is not allowed after %qs fragments", + spec.as_string ().c_str (), last_spec.as_string ().c_str ()); return is_valid; } @@ -244,7 +243,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, // the error. switch (match.get_macro_match_type ()) { - case AST::MacroMatch::Tok: { + case AST::MacroMatch::Tok: + { auto tok = static_cast (&match); if (contains (allowed_toks, tok->get_id ())) return true; @@ -254,7 +254,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, break; } break; - case AST::MacroMatch::Repetition: { + case AST::MacroMatch::Repetition: + { auto repetition = static_cast (&match); auto &matches = repetition->get_matches (); @@ -263,7 +264,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, return peculiar_fragment_match_compatible (last_match, *first_frag); break; } - case AST::MacroMatch::Matcher: { + case AST::MacroMatch::Matcher: + { auto matcher = static_cast (&match); auto first_token = matcher->get_delim_type (); TokenId delim_id; @@ -289,7 +291,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, error_locus = matcher->get_match_locus (); break; } - case AST::MacroMatch::Fragment: { + case AST::MacroMatch::Fragment: + { auto last_spec = last_match.get_frag_spec (); auto fragment = static_cast (&match); if (last_spec.has_follow_set_fragment_restrictions ()) @@ -328,10 +331,11 @@ is_match_compatible (const AST::MacroMatch &last_match, switch (last_match.get_macro_match_type ()) { - // This is our main stop condition: When we are finally looking at the - // last match (or its actual last component), and it is a fragment, it - // may contain some follow up restrictions. - case AST::MacroMatch::Fragment: { + // This is our main stop condition: When we are finally looking at the + // last match (or its actual last component), and it is a fragment, it + // may contain some follow up restrictions. + case AST::MacroMatch::Fragment: + { auto fragment = static_cast (&last_match); if (fragment->get_frag_spec ().has_follow_set_restrictions ()) @@ -339,7 +343,8 @@ is_match_compatible (const AST::MacroMatch &last_match, else return true; } - case AST::MacroMatch::Repetition: { + case AST::MacroMatch::Repetition: + { // A repetition on the left hand side means we want to make sure the // last match of the repetition is compatible with the new match auto repetition diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 827d91d6cbb1..c8ee5f109b0c 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -764,9 +764,9 @@ template class Parser }; }; -std::string -extract_module_path (const AST::AttrVec &inner_attrs, - const AST::AttrVec &outer_attrs, const std::string &name); +std::string extract_module_path (const AST::AttrVec &inner_attrs, + const AST::AttrVec &outer_attrs, + const std::string &name); /** * Check if a MacroMatch is allowed to follow the last parsed MacroMatch. @@ -776,9 +776,8 @@ extract_module_path (const AST::AttrVec &inner_attrs, * * @return true if the follow-up is valid, false otherwise */ -bool -is_match_compatible (const AST::MacroMatch &last_match, - const AST::MacroMatch ¤t_match); +bool is_match_compatible (const AST::MacroMatch &last_match, + const AST::MacroMatch ¤t_match); } // namespace Rust // as now template, include implementations of all methods diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc index 6242235a1bb1..8580f4b1575c 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc @@ -324,38 +324,45 @@ translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix, { switch (operand.get_register_type ()) { - case RegisterType::In: { + case RegisterType::In: + { auto in = operand.get_in (); ResolveExpr::go (*in.expr, prefix, canonical_prefix); break; } - case RegisterType::Out: { + case RegisterType::Out: + { auto out = operand.get_out (); ResolveExpr::go (*out.expr, prefix, canonical_prefix); break; } - case RegisterType::InOut: { + case RegisterType::InOut: + { auto in_out = operand.get_in_out (); ResolveExpr::go (*in_out.expr, prefix, canonical_prefix); break; } - case RegisterType::SplitInOut: { + case RegisterType::SplitInOut: + { auto split_in_out = operand.get_split_in_out (); ResolveExpr::go (*split_in_out.in_expr, prefix, canonical_prefix); ResolveExpr::go (*split_in_out.out_expr, prefix, canonical_prefix); break; } - case RegisterType::Const: { + case RegisterType::Const: + { auto anon_const = operand.get_const ().anon_const; ResolveExpr::go (*anon_const.expr, prefix, canonical_prefix); break; } - case RegisterType::Sym: { + case RegisterType::Sym: + { auto sym = operand.get_sym (); ResolveExpr::go (*sym.expr, prefix, canonical_prefix); break; } - case RegisterType::Label: { + case RegisterType::Label: + { auto label = operand.get_label (); ResolveExpr::go (*label.expr, prefix, canonical_prefix); break; diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index 9f95f517187e..0937d6577c8b 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -829,29 +829,32 @@ ResolveItem::resolve_extern_item (AST::ExternalItem &item) ResolveExternItem::go (item, prefix, canonical_prefix); } -static void -flatten_glob (const AST::UseTreeGlob &glob, std::vector &imports); -static void -flatten_rebind (const AST::UseTreeRebind &glob, std::vector &imports); -static void -flatten_list (const AST::UseTreeList &glob, std::vector &imports); +static void flatten_glob (const AST::UseTreeGlob &glob, + std::vector &imports); +static void flatten_rebind (const AST::UseTreeRebind &glob, + std::vector &imports); +static void flatten_list (const AST::UseTreeList &glob, + std::vector &imports); static void flatten (const AST::UseTree *tree, std::vector &imports) { switch (tree->get_kind ()) { - case AST::UseTree::Glob: { + case AST::UseTree::Glob: + { auto glob = static_cast (tree); flatten_glob (*glob, imports); break; } - case AST::UseTree::Rebind: { + case AST::UseTree::Rebind: + { auto rebind = static_cast (tree); flatten_rebind (*rebind, imports); break; } - case AST::UseTree::List: { + case AST::UseTree::List: + { auto list = static_cast (tree); flatten_list (*list, imports); break; diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index 776dd5338a51..d31f910c4b18 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -153,8 +153,7 @@ class Import #if CHECKING_P namespace selftest { -extern void -rust_simple_path_resolve_test (void); +extern void rust_simple_path_resolve_test (void); } // namespace selftest #endif // CHECKING_P diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc index ee84be8942bc..2b5e2bf97eb9 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc @@ -94,13 +94,15 @@ PatternDeclaration::visit (AST::TupleStructPattern &pattern) AST::TupleStructItems &items = pattern.get_items (); switch (items.get_item_type ()) { - case AST::TupleStructItems::RANGE: { + case AST::TupleStructItems::RANGE: + { // TODO rust_unreachable (); } break; - case AST::TupleStructItems::NO_RANGE: { + case AST::TupleStructItems::NO_RANGE: + { auto &items_no_range = static_cast (items); @@ -123,7 +125,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern) { switch (field->get_item_type ()) { - case AST::StructPatternField::ItemType::TUPLE_PAT: { + case AST::StructPatternField::ItemType::TUPLE_PAT: + { AST::StructPatternFieldTuplePat &tuple = static_cast (*field); @@ -131,7 +134,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern) } break; - case AST::StructPatternField::ItemType::IDENT_PAT: { + case AST::StructPatternField::ItemType::IDENT_PAT: + { AST::StructPatternFieldIdentPat &ident = static_cast (*field); @@ -139,7 +143,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern) } break; - case AST::StructPatternField::ItemType::IDENT: { + case AST::StructPatternField::ItemType::IDENT: + { auto &ident = static_cast (*field); Mutability mut @@ -160,7 +165,8 @@ PatternDeclaration::visit (AST::TuplePattern &pattern) auto &items = pattern.get_items (); switch (items.get_pattern_type ()) { - case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: { + case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: + { auto &ref = static_cast ( pattern.get_items ()); @@ -169,7 +175,8 @@ PatternDeclaration::visit (AST::TuplePattern &pattern) } break; - case AST::TuplePatternItems::TuplePatternItemType::RANGED: { + case AST::TuplePatternItems::TuplePatternItemType::RANGED: + { auto &ref = static_cast (pattern.get_items ()); @@ -348,14 +355,16 @@ resolve_range_pattern_bound (AST::RangePatternBound &bound) // Nothing to resolve for a literal. break; - case AST::RangePatternBound::RangePatternBoundType::PATH: { + case AST::RangePatternBound::RangePatternBoundType::PATH: + { auto &ref = static_cast (bound); ResolvePath::go (ref.get_path ()); } break; - case AST::RangePatternBound::RangePatternBoundType::QUALPATH: { + case AST::RangePatternBound::RangePatternBoundType::QUALPATH: + { auto &ref = static_cast (bound); ResolvePath::go (ref.get_qualified_path ()); diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc index 891fcf5d9f1d..a0402289afc4 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ b/gcc/rust/resolve/rust-ast-resolve-type.cc @@ -210,7 +210,8 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) switch (segment->get_type ()) { - case AST::TypePathSegment::SegmentType::GENERIC: { + case AST::TypePathSegment::SegmentType::GENERIC: + { AST::TypePathSegmentGeneric *s = static_cast (segment.get ()); if (s->has_generic_args ()) @@ -509,7 +510,8 @@ ResolveTypeToCanonicalPath::visit (AST::TypePath &path) auto &final_seg = path.get_segments ().back (); switch (final_seg->get_type ()) { - case AST::TypePathSegment::SegmentType::GENERIC: { + case AST::TypePathSegment::SegmentType::GENERIC: + { AST::TypePathSegmentGeneric *s = static_cast (final_seg.get ()); @@ -651,7 +653,8 @@ ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &type) switch (additional_bound->get_bound_type ()) { - case AST::TypeParamBound::TRAIT: { + case AST::TypeParamBound::TRAIT: + { auto bound_path = CanonicalPath::create_empty (); auto &bound_type_path diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 3e3c992e76ac..2208f7046a7e 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -24,8 +24,7 @@ #include "rust-ast-resolve-expr.h" #include "rust-ast-resolve-struct-expr-field.h" -extern bool -saw_errors (void); +extern bool saw_errors (void); namespace Rust { namespace Resolver { diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 3390f09e2916..9d2b77a0e3ab 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -419,7 +419,8 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping) declared_name = rebind.get_identifier ().as_string (); locus = rebind.get_identifier ().get_locus (); break; - case AST::UseTreeRebind::NewBindType::NONE: { + case AST::UseTreeRebind::NewBindType::NONE: + { const auto &segments = path.get_segments (); // We don't want to insert `self` with `use module::self` if (path.get_final_segment ().is_lower_self_seg ()) diff --git a/gcc/rust/resolve/rust-ice-finalizer.h b/gcc/rust/resolve/rust-ice-finalizer.h index 85ab88ff7146..578084a92cdc 100644 --- a/gcc/rust/resolve/rust-ice-finalizer.h +++ b/gcc/rust/resolve/rust-ice-finalizer.h @@ -54,10 +54,9 @@ namespace Resolver { /* The finalizer for our funny ICE. This prints a custom message instead of the default bug reporting instructions, as there is no bug to report. */ -void ATTRIBUTE_NORETURN -funny_ice_text_finalizer (diagnostic_text_output_format &text_output, - const diagnostic_info *diagnostic, - diagnostic_t diag_kind); +void ATTRIBUTE_NORETURN funny_ice_text_finalizer ( + diagnostic_text_output_format &text_output, const diagnostic_info *diagnostic, + diagnostic_t diag_kind); } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index dd2a8f37df06..06bf4fd3b7d7 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -377,7 +377,8 @@ Late::visit (AST::IdentifierExpr &expr) } else if (funny_error) { - diagnostic_text_finalizer (global_dc) = Resolver::funny_ice_text_finalizer; + diagnostic_text_finalizer (global_dc) + = Resolver::funny_ice_text_finalizer; emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1, "are you trying to break %s? how dare you?", expr.as_string ().c_str ()); diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index 122436bb22fe..4d88ad1eb370 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -415,21 +415,18 @@ TopLevel::visit (AST::TypeAlias &type_item) DefaultResolver::visit (type_item); } -static void -flatten_rebind ( +static void flatten_rebind ( const AST::UseTreeRebind &glob, std::vector> &rebind_paths); -static void -flatten_list ( +static void flatten_list ( const AST::UseTreeList &glob, std::vector &paths, std::vector &glob_paths, std::vector> &rebind_paths, NameResolutionContext &ctx); -static void -flatten_glob (const AST::UseTreeGlob &glob, - std::vector &glob_paths, - NameResolutionContext &ctx); +static void flatten_glob (const AST::UseTreeGlob &glob, + std::vector &glob_paths, + NameResolutionContext &ctx); static void flatten ( @@ -440,17 +437,20 @@ flatten ( { switch (tree->get_kind ()) { - case AST::UseTree::Rebind: { + case AST::UseTree::Rebind: + { auto rebind = static_cast (tree); flatten_rebind (*rebind, rebind_paths); break; } - case AST::UseTree::List: { + case AST::UseTree::List: + { auto list = static_cast (tree); flatten_list (*list, paths, glob_paths, rebind_paths, ctx); break; } - case AST::UseTree::Glob: { + case AST::UseTree::Glob: + { auto glob = static_cast (tree); flatten_glob (*glob, glob_paths, ctx); break; diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 414799edefee..a0df21798808 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -42,8 +42,7 @@ class Bvariable; namespace Backend { -void -init (); +void init (); // Name/type/location. Used for function parameters, struct fields, // interface methods. @@ -64,47 +63,37 @@ struct typed_identifier // debug void debug (tree); -void -debug (Bvariable *); +void debug (Bvariable *); -tree -get_identifier_node (const std::string &str); +tree get_identifier_node (const std::string &str); // Types. // Get the wchar type -tree -wchar_type (); +tree wchar_type (); // Get the Host pointer size in bits -int -get_pointer_size (); +int get_pointer_size (); // Get the raw str type const char* -tree -raw_str_type (); +tree raw_str_type (); // Get an unnamed integer type with the given signedness and number // of bits. -tree -integer_type (bool is_unsigned, int bits); +tree integer_type (bool is_unsigned, int bits); // Get an unnamed floating point type with the given number of bits // (32 or 64). -tree -float_type (int bits); +tree float_type (int bits); // Get a pointer type. -tree -pointer_type (tree to_type); +tree pointer_type (tree to_type); // Get a reference type. -tree -reference_type (tree to_type); +tree reference_type (tree to_type); // make type immutable -tree -immutable_type (tree base); +tree immutable_type (tree base); // Get a function type. The receiver, parameter, and results are // generated from the types in the Function_type. The Function_type @@ -115,41 +104,36 @@ immutable_type (tree base); // one result, RESULT_STRUCT is a struct type to hold the results, // and RESULTS may be ignored; if there are zero or one results, // RESULT_STRUCT is NULL. -tree -function_type (const typed_identifier &receiver, - const std::vector ¶meters, - const std::vector &results, tree result_struct, - location_t location); - -tree -function_type_variadic (const typed_identifier &receiver, - const std::vector ¶meters, - const std::vector &results, - tree result_struct, location_t location); - -tree -function_ptr_type (tree result, const std::vector &praameters, - location_t location); +tree function_type (const typed_identifier &receiver, + const std::vector ¶meters, + const std::vector &results, + tree result_struct, location_t location); + +tree function_type_variadic (const typed_identifier &receiver, + const std::vector ¶meters, + const std::vector &results, + tree result_struct, location_t location); + +tree function_ptr_type (tree result, const std::vector &praameters, + location_t location); // Get a struct type. -tree -struct_type (const std::vector &fields, bool layout = true); +tree struct_type (const std::vector &fields, + bool layout = true); // Get a union type. -tree -union_type (const std::vector &fields, bool layout = true); +tree union_type (const std::vector &fields, + bool layout = true); // Get an array type. -tree -array_type (tree element_type, tree length); +tree array_type (tree element_type, tree length); // Return a named version of a type. The location is the location // of the type definition. This will not be called for a type // created via placeholder_pointer_type, placeholder_struct_type, or // placeholder_array_type.. (It may be called for a pointer, // struct, or array type in a case like "type P *byte; type Q P".) -tree -named_type (const std::string &name, tree, location_t); +tree named_type (const std::string &name, tree, location_t); // Return the size of a type. int64_t type_size (tree); @@ -164,8 +148,7 @@ int64_t type_field_alignment (tree); // Return the offset of field INDEX in a struct type. INDEX is the // entry in the FIELDS std::vector parameter of struct_type or // set_placeholder_struct_type. -int64_t -type_field_offset (tree, size_t index); +int64_t type_field_offset (tree, size_t index); // Expressions. @@ -175,155 +158,128 @@ type_field_offset (tree, size_t index); tree zero_expression (tree); // Create a reference to a variable. -tree -var_expression (Bvariable *var, location_t); +tree var_expression (Bvariable *var, location_t); // Return an expression for the floating point value VAL in BTYPE. -tree -float_constant_expression (tree btype, mpfr_t val); +tree float_constant_expression (tree btype, mpfr_t val); // Return an expression for the string value VAL. -tree -string_constant_expression (const std::string &val); +tree string_constant_expression (const std::string &val); // Get a char literal -tree -char_constant_expression (char c); +tree char_constant_expression (char c); // Get a char literal -tree -wchar_constant_expression (wchar_t c); +tree wchar_constant_expression (wchar_t c); // Return an expression for the boolean value VAL. -tree -boolean_constant_expression (bool val); +tree boolean_constant_expression (bool val); // Return an expression that converts EXPR to TYPE. -tree -convert_expression (tree type, tree expr, location_t); +tree convert_expression (tree type, tree expr, location_t); // Return an expression for the field at INDEX in BSTRUCT. -tree -struct_field_expression (tree bstruct, size_t index, location_t); +tree struct_field_expression (tree bstruct, size_t index, location_t); // Create an expression that executes BSTAT before BEXPR. -tree -compound_expression (tree bstat, tree bexpr, location_t); +tree compound_expression (tree bstat, tree bexpr, location_t); // Return an expression that executes THEN_EXPR if CONDITION is true, or // ELSE_EXPR otherwise and returns the result as type BTYPE, within the // specified function FUNCTION. ELSE_EXPR may be NULL. BTYPE may be NULL. -tree -conditional_expression (tree function, tree btype, tree condition, - tree then_expr, tree else_expr, location_t); +tree conditional_expression (tree function, tree btype, tree condition, + tree then_expr, tree else_expr, location_t); // Return an expression for the negation operation OP EXPR. // Supported values of OP are enumerated in NegationOperator. -tree -negation_expression (NegationOperator op, tree expr, location_t); +tree negation_expression (NegationOperator op, tree expr, location_t); // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in ArithmeticOrLogicalOperator. -tree -arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left, - tree right, location_t loc); +tree arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, + tree left, tree right, location_t loc); // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in ArithmeticOrLogicalOperator. // This function adds overflow checking and returns a list of statements to // add to the current function context. The `receiver` variable refers to the // variable which will contain the result of that operation. -tree -arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op, - tree left, tree right, location_t loc, - Bvariable *receiver); +tree arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op, + tree left, tree right, + location_t loc, + Bvariable *receiver); // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in ComparisonOperator. -tree -comparison_expression (ComparisonOperator op, tree left, tree right, - location_t loc); +tree comparison_expression (ComparisonOperator op, tree left, tree right, + location_t loc); // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in LazyBooleanOperator. -tree -lazy_boolean_expression (LazyBooleanOperator op, tree left, tree right, - location_t); +tree lazy_boolean_expression (LazyBooleanOperator op, tree left, tree right, + location_t); // Return an expression that constructs BTYPE with VALS. BTYPE must be the // backend representation a of struct. VALS must be in the same order as the // corresponding fields in BTYPE. -tree -constructor_expression (tree btype, bool is_variant, - const std::vector &vals, int, location_t); +tree constructor_expression (tree btype, bool is_variant, + const std::vector &vals, int, location_t); // Return an expression that constructs an array of BTYPE with INDEXES and // VALS. INDEXES and VALS must have the same amount of elements. Each index // in INDEXES must be in the same order as the corresponding value in VALS. -tree -array_constructor_expression (tree btype, - const std::vector &indexes, - const std::vector &vals, location_t); +tree array_constructor_expression (tree btype, + const std::vector &indexes, + const std::vector &vals, location_t); -tree -array_initializer (tree, tree, tree, tree, tree, tree *, location_t); +tree array_initializer (tree, tree, tree, tree, tree, tree *, location_t); // Return an expression for ARRAY[INDEX] as an l-value. ARRAY is a valid // fixed-length array, not a slice. -tree -array_index_expression (tree array, tree index, location_t); +tree array_index_expression (tree array, tree index, location_t); // Create an expression for a call to FN with ARGS, taking place within // caller CALLER. -tree -call_expression (tree fn, const std::vector &args, tree static_chain, - location_t); +tree call_expression (tree fn, const std::vector &args, tree static_chain, + location_t); // Statements. // Create a variable initialization statement in the specified // function. This initializes a local variable at the point in the // program flow where it is declared. -tree -init_statement (tree, Bvariable *var, tree init); +tree init_statement (tree, Bvariable *var, tree init); // Create an assignment statement within the specified function. -tree -assignment_statement (tree lhs, tree rhs, location_t); +tree assignment_statement (tree lhs, tree rhs, location_t); // Create return statement for an decl for a value (can be NULL_TREE) at a // location -tree -return_statement (tree fndecl, tree val, location_t); +tree return_statement (tree fndecl, tree val, location_t); // Create an if statement within a function. ELSE_BLOCK may be NULL. -tree -if_statement (tree, tree condition, tree then_block, tree else_block, - location_t); +tree if_statement (tree, tree condition, tree then_block, tree else_block, + location_t); // infinite loop expressions -tree -loop_expression (tree body, location_t); +tree loop_expression (tree body, location_t); // exit expressions -tree -exit_expression (tree condition, location_t); +tree exit_expression (tree condition, location_t); // Create a single statement from two statements. tree compound_statement (tree, tree); // Create a single statement from a list of statements. -tree -statement_list (const std::vector &); +tree statement_list (const std::vector &); // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if // an exception occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and // if not NULL, it will always be executed. This is used for handling defers // in Go functions. In C++, the resulting code is of this form: // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; } -tree -exception_handler_statement (tree bstat, tree except_stmt, tree finally_stmt, - location_t); +tree exception_handler_statement (tree bstat, tree except_stmt, + tree finally_stmt, location_t); // Blocks. @@ -337,16 +293,14 @@ exception_handler_statement (tree bstat, tree except_stmt, tree finally_stmt, // the initial curly brace. END_LOCATION is the location of the end // of the block, more or less the location of the final curly brace. // The statements will be added after the block is created. -tree -block (tree function, tree enclosing, const std::vector &vars, - location_t start_location, location_t end_location); +tree block (tree function, tree enclosing, const std::vector &vars, + location_t start_location, location_t end_location); // Add the statements to a block. The block is created first. Then // the statements are created. Then the statements are added to the // block. This will called exactly once per block. The vector may // be empty if there are no statements. -void -block_add_statements (tree, const std::vector &); +void block_add_statements (tree, const std::vector &); // Variables. @@ -360,10 +314,10 @@ block_add_statements (tree, const std::vector &); // be put into a unique section if possible; this is intended to // permit the linker to garbage collect the variable if it is not // referenced. LOCATION is where the variable was defined. -Bvariable * -global_variable (const std::string &name, const std::string &asm_name, - tree btype, bool is_external, bool is_hidden, - bool in_unique_section, location_t location); +Bvariable *global_variable (const std::string &name, + const std::string &asm_name, tree btype, + bool is_external, bool is_hidden, + bool in_unique_section, location_t location); // A global variable will 1) be initialized to zero, or 2) be // initialized to a constant value, or 3) be initialized in the init @@ -371,8 +325,7 @@ global_variable (const std::string &name, const std::string &asm_name, // global_variable_set_init to set the initial value. If this is // not called, the backend should initialize a global variable to 0. // The init function may then assign a value to it. -void -global_variable_set_init (Bvariable *, tree); +void global_variable_set_init (Bvariable *, tree); // Create a local variable. The frontend will create the local // variables first, and then create the block which contains them. @@ -386,21 +339,18 @@ global_variable_set_init (Bvariable *, tree); // the function, as otherwise the variable would be on the heap). // LOCATION is where the variable is defined. For each local variable // the frontend will call init_statement to set the initial value. -Bvariable * -local_variable (tree function, const std::string &name, tree type, - Bvariable *decl_var, location_t location); +Bvariable *local_variable (tree function, const std::string &name, tree type, + Bvariable *decl_var, location_t location); // Create a function parameter. This is an incoming parameter, not // a result parameter (result parameters are treated as local // variables). The arguments are as for local_variable. -Bvariable * -parameter_variable (tree function, const std::string &name, tree type, - location_t location); +Bvariable *parameter_variable (tree function, const std::string &name, + tree type, location_t location); // Create a static chain parameter. This is the closure parameter. -Bvariable * -static_chain_variable (tree function, const std::string &name, tree type, - location_t location); +Bvariable *static_chain_variable (tree function, const std::string &name, + tree type, location_t location); // Create a temporary variable. A temporary variable has no name, // just a type. We pass in FUNCTION and BLOCK in case they are @@ -413,18 +363,16 @@ static_chain_variable (tree function, const std::string &name, tree type, // variable, and may not be very useful. This function should // return a variable which can be referenced later and should set // *PSTATEMENT to a statement which initializes the variable. -Bvariable * -temporary_variable (tree fndecl, tree bind_tree, tree type, tree init, - bool address_is_taken, location_t location, - tree *pstatement); +Bvariable *temporary_variable (tree fndecl, tree bind_tree, tree type, + tree init, bool address_is_taken, + location_t location, tree *pstatement); // Labels. // Create a new label. NAME will be empty if this is a label // created by the frontend for a loop construct. The location is // where the label is defined. -tree -label (tree, const std::string &name, location_t); +tree label (tree, const std::string &name, location_t); // Create a statement which defines a label. This statement will be // put into the codestream at the point where the label should be @@ -464,39 +412,34 @@ static const unsigned int function_in_unique_section = 1 << 3; // string, is the name that should be used in the symbol table; this // will be non-empty if a magic extern comment is used. FLAGS is // bit flags described above. -tree -function (tree fntype, const std::string &name, const std::string &asm_name, - unsigned int flags, location_t); +tree function (tree fntype, const std::string &name, + const std::string &asm_name, unsigned int flags, location_t); // Create a statement that runs all deferred calls for FUNCTION. This should // be a statement that looks like this in C++: // finish: // try { DEFER_RETURN; } catch { CHECK_DEFER; goto finish; } -tree -function_defer_statement (tree function, tree undefer, tree check_defer, - location_t); +tree function_defer_statement (tree function, tree undefer, tree check_defer, + location_t); // Record PARAM_VARS as the variables to use for the parameters of FUNCTION. // This will only be called for a function definition. Returns true on // success, false on failure. -bool -function_set_parameters (tree function, - const std::vector ¶m_vars); +bool function_set_parameters (tree function, + const std::vector ¶m_vars); // Utility. // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, // FUNCTION_DECLS, and VARIABLE_DECLS declared globally. -void -write_global_definitions (const std::vector &type_decls, - const std::vector &constant_decls, - const std::vector &function_decls, - const std::vector &variable_decls); +void write_global_definitions (const std::vector &type_decls, + const std::vector &constant_decls, + const std::vector &function_decls, + const std::vector &variable_decls); // TODO: make static -tree -fill_in_fields (tree, const std::vector &, bool); +tree fill_in_fields (tree, const std::vector &, bool); tree fill_in_array (tree, tree, tree); diff --git a/gcc/rust/rust-diagnostics.cc b/gcc/rust/rust-diagnostics.cc index 0c0ef6ed7e23..7b2d7570d1e3 100644 --- a/gcc/rust/rust-diagnostics.cc +++ b/gcc/rust/rust-diagnostics.cc @@ -48,27 +48,33 @@ expand_format (const char *fmt) c++; switch (*c) { - case '\0': { + case '\0': + { // malformed format string rust_unreachable (); } - case '%': { + case '%': + { ss << "%"; break; } - case 'm': { + case 'm': + { ss << mformat_value (); break; } - case '<': { + case '<': + { ss << rust_open_quote (); break; } - case '>': { + case '>': + { ss << rust_close_quote (); break; } - case 'q': { + case 'q': + { ss << rust_open_quote (); c++; if (*c == 'm') @@ -82,7 +88,8 @@ expand_format (const char *fmt) ss << rust_close_quote (); break; } - default: { + default: + { ss << "%" << *c; } } @@ -104,8 +111,8 @@ expand_format (const char *fmt) // calling function must need to have attribute gnu_printf as well, even // though there is already an attribute declaration for it. -static std::string -expand_message (const char *fmt, va_list ap) RUST_ATTRIBUTE_GCC_DIAG (1, 0); +static std::string expand_message (const char *fmt, va_list ap) + RUST_ATTRIBUTE_GCC_DIAG (1, 0); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsuggest-attribute=format" @@ -420,24 +427,24 @@ namespace Rust { */ // simple location -static Error -va_constructor (Error::Kind kind, location_t locus, const char *fmt, - va_list args) RUST_ATTRIBUTE_GCC_DIAG (3, 0); +static Error va_constructor (Error::Kind kind, location_t locus, + const char *fmt, va_list args) + RUST_ATTRIBUTE_GCC_DIAG (3, 0); // simple location + error code -static Error -va_constructor (Error::Kind kind, location_t locus, const ErrorCode code, - const char *fmt, va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0); +static Error va_constructor (Error::Kind kind, location_t locus, + const ErrorCode code, const char *fmt, + va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0); // rich location -static Error -va_constructor (Error::Kind kind, rich_location *r_locus, const char *fmt, - va_list args) RUST_ATTRIBUTE_GCC_DIAG (3, 0); +static Error va_constructor (Error::Kind kind, rich_location *r_locus, + const char *fmt, va_list args) + RUST_ATTRIBUTE_GCC_DIAG (3, 0); // rich location + error code -static Error -va_constructor (Error::Kind kind, rich_location *r_locus, const ErrorCode code, - const char *fmt, va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0); +static Error va_constructor (Error::Kind kind, rich_location *r_locus, + const ErrorCode code, const char *fmt, + va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0); // simple location static Error diff --git a/gcc/rust/rust-diagnostics.h b/gcc/rust/rust-diagnostics.h index a13dc6a2eaf8..0b83e8ca2d81 100644 --- a/gcc/rust/rust-diagnostics.h +++ b/gcc/rust/rust-diagnostics.h @@ -31,7 +31,7 @@ #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) #define RUST_ATTRIBUTE_GCC_DIAG(m, n) \ __attribute__ ((__format__ (__gcc_tdiag__, m, n))) \ - __attribute__ ((__nonnull__ (m))) + __attribute__ ((__nonnull__ (m))) #else #define RUST_ATTRIBUTE_GCC_DIAG(m, n) #endif @@ -119,10 +119,8 @@ rust_error_at(rich_location *richloc, const ErrorCode, const char *fmt, ...) // These interfaces provide a way for the front end to ask for // the open/close quote characters it should use when formatting // diagnostics (warnings, errors). -extern const char * -rust_open_quote (); -extern const char * -rust_close_quote (); +extern const char *rust_open_quote (); +extern const char *rust_close_quote (); // These interfaces are used by utilities above to pass warnings and // errors (once format specifiers have been expanded) to the back end, @@ -306,8 +304,7 @@ struct Error #define rust_sorry_at(location, ...) sorry_at (location, __VA_ARGS__) -void -rust_debug_loc (const location_t location, const char *fmt, - ...) ATTRIBUTE_PRINTF_2; +void rust_debug_loc (const location_t location, const char *fmt, + ...) ATTRIBUTE_PRINTF_2; #endif // !defined(RUST_DIAGNOSTICS_H) diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index e5319d320800..f440f79801b3 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -1876,7 +1876,8 @@ non_zero_size_type (tree type) } return rust_non_zero_struct; - case ARRAY_TYPE: { + case ARRAY_TYPE: + { tree element_type = non_zero_size_type (TREE_TYPE (type)); return build_array_type_nelts (element_type, 1); } diff --git a/gcc/rust/rust-object-export.h b/gcc/rust/rust-object-export.h index fe055c3ec057..784fef31f391 100644 --- a/gcc/rust/rust-object-export.h +++ b/gcc/rust/rust-object-export.h @@ -21,13 +21,10 @@ #include "rust-system.h" -extern unsigned int -rust_field_alignment (tree t); - -extern const char * -rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen, - int *perr); -extern void -rust_write_export_data (const char *bytes, unsigned int size); +extern unsigned int rust_field_alignment (tree t); + +extern const char *rust_read_export_data (int fd, off_t offset, char **pbuf, + size_t *plen, int *perr); +extern void rust_write_export_data (const char *bytes, unsigned int size); #endif // RUST_OBJECT_EXPORT_H diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 09f7e2ee4efb..d42ae6a3fda5 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -62,11 +62,9 @@ #include "tm.h" #include "rust-target.h" -extern bool -saw_errors (void); +extern bool saw_errors (void); -extern Linemap * -rust_get_linemap (); +extern Linemap *rust_get_linemap (); namespace Rust { @@ -151,9 +149,9 @@ validate_crate_name (const std::string &crate_name, Error &error) { if (!(is_alphabetic (c.value) || is_numeric (c.value) || c.value == '_')) { - error = Error (UNDEF_LOCATION, - "invalid character %qs in crate name: %qs", - c.as_string ().c_str (), crate_name.c_str ()); + error + = Error (UNDEF_LOCATION, "invalid character %qs in crate name: %qs", + c.as_string ().c_str (), crate_name.c_str ()); return false; } } @@ -204,14 +202,16 @@ Session::handle_option ( switch (code) { case OPT_I: - case OPT_L: { + case OPT_L: + { // TODO: add search path const std::string p = std::string (arg); add_search_path (p); } break; - case OPT_frust_extern_: { + case OPT_frust_extern_: + { std::string input (arg); ret = handle_extern_option (input); } @@ -252,7 +252,8 @@ Session::handle_option ( Compile::Mangler::set_mangling (flag_rust_mangling); break; - case OPT_frust_cfg_: { + case OPT_frust_cfg_: + { auto string_arg = std::string (arg); ret = handle_cfg_option (string_arg); break; @@ -1110,8 +1111,7 @@ Session::load_extern_crate (const std::string &crate_name, location_t locus) if (stream == NULL // No stream and && proc_macros.empty ()) // no proc macros { - rust_error_at (locus, "failed to locate crate %qs", - import_name.c_str ()); + rust_error_at (locus, "failed to locate crate %qs", import_name.c_str ()); return UNKNOWN_NODEID; } diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index 83ba121e4116..9af103cbd732 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -441,8 +441,7 @@ struct Session #if CHECKING_P namespace selftest { -extern void -rust_crate_name_validation_test (void); +extern void rust_crate_name_validation_test (void); } #endif // CHECKING_P diff --git a/gcc/rust/rust-system.h b/gcc/rust/rust-system.h index 986428b08195..a4551239f3ab 100644 --- a/gcc/rust/rust-system.h +++ b/gcc/rust/rust-system.h @@ -88,10 +88,8 @@ constexpr static const char *file_separator = "/"; */ #define rust_unreachable() (fancy_abort (__FILE__, __LINE__, __FUNCTION__)) -extern void -rust_preserve_from_gc (tree t); +extern void rust_preserve_from_gc (tree t); -extern const char * -rust_localize_identifier (const char *ident); +extern const char *rust_localize_identifier (const char *ident); #endif // !defined(RUST_SYSTEM_H) diff --git a/gcc/rust/rust-target.h b/gcc/rust/rust-target.h index dbc2baff29bd..e61ea5112c15 100644 --- a/gcc/rust/rust-target.h +++ b/gcc/rust/rust-target.h @@ -26,8 +26,7 @@ #include "rust-target.def" /* Used by target to add target-related info. */ -extern void -rust_add_target_info (const char *, const char *); +extern void rust_add_target_info (const char *, const char *); /* Each target can provide their own. */ extern struct gcc_targetrustm targetrustm; diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc index 6aa20a8c9414..825607431f07 100644 --- a/gcc/rust/typecheck/rust-autoderef.cc +++ b/gcc/rust/typecheck/rust-autoderef.cc @@ -26,8 +26,7 @@ namespace Rust { namespace Resolver { -static bool -resolve_operator_overload_fn ( +static bool resolve_operator_overload_fn ( LangItem::Kind lang_item_type, TyTy::BaseType *ty, TyTy::FnType **resolved_fn, Adjustment::AdjustmentType *requires_ref_adjustment); diff --git a/gcc/rust/typecheck/rust-casts.cc b/gcc/rust/typecheck/rust-casts.cc index 90bdef1fd3c1..d0a9f5dca015 100644 --- a/gcc/rust/typecheck/rust-casts.cc +++ b/gcc/rust/typecheck/rust-casts.cc @@ -73,7 +73,8 @@ TypeCastRules::cast_rules () to.get_ty ()->debug_str ().c_str ()); switch (from_type->get_kind ()) { - case TyTy::TypeKind::INFER: { + case TyTy::TypeKind::INFER: + { TyTy::InferType *from_infer = static_cast (from_type); switch (from_infer->get_infer_kind ()) @@ -85,7 +86,8 @@ TypeCastRules::cast_rules () case TyTy::InferType::InferTypeKind::INTEGRAL: switch (to.get_ty ()->get_kind ()) { - case TyTy::TypeKind::CHAR: { + case TyTy::TypeKind::CHAR: + { // only u8 and char bool was_uint = from.get_ty ()->get_kind () == TyTy::TypeKind::UINT; @@ -108,7 +110,8 @@ TypeCastRules::cast_rules () return TypeCoercionRules::CoercionResult{ {}, to.get_ty ()->clone ()}; - case TyTy::TypeKind::INFER: { + case TyTy::TypeKind::INFER: + { TyTy::InferType *to_infer = static_cast (to.get_ty ()); @@ -140,7 +143,8 @@ TypeCastRules::cast_rules () return TypeCoercionRules::CoercionResult{ {}, to.get_ty ()->clone ()}; - case TyTy::TypeKind::INFER: { + case TyTy::TypeKind::INFER: + { TyTy::InferType *to_infer = static_cast (to.get_ty ()); @@ -187,7 +191,8 @@ TypeCastRules::cast_rules () case TyTy::TypeKind::INT: switch (to.get_ty ()->get_kind ()) { - case TyTy::TypeKind::CHAR: { + case TyTy::TypeKind::CHAR: + { // only u8 and char bool was_uint = from.get_ty ()->get_kind () == TyTy::TypeKind::UINT; bool was_u8 = was_uint @@ -200,7 +205,8 @@ TypeCastRules::cast_rules () } break; - case TyTy::TypeKind::FLOAT: { + case TyTy::TypeKind::FLOAT: + { // can only do this for number types not char bool from_char = from.get_ty ()->get_kind () == TyTy::TypeKind::CHAR; @@ -210,7 +216,8 @@ TypeCastRules::cast_rules () } break; - case TyTy::TypeKind::POINTER: { + case TyTy::TypeKind::POINTER: + { // char can't be casted as a ptr bool from_char = from.get_ty ()->get_kind () == TyTy::TypeKind::CHAR; @@ -244,7 +251,8 @@ TypeCastRules::cast_rules () case TyTy::TypeKind::FLOAT: return TypeCoercionRules::CoercionResult{{}, to.get_ty ()->clone ()}; - case TyTy::TypeKind::INFER: { + case TyTy::TypeKind::INFER: + { TyTy::InferType *to_infer = static_cast (to.get_ty ()); @@ -273,7 +281,8 @@ TypeCastRules::cast_rules () case TyTy::TypeKind::USIZE: case TyTy::TypeKind::ISIZE: case TyTy::TypeKind::UINT: - case TyTy::TypeKind::INT: { + case TyTy::TypeKind::INT: + { // refs should not cast to numeric type bool from_ptr = from.get_ty ()->get_kind () == TyTy::TypeKind::POINTER; diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc index 5905992426c2..3a92a2f2f6ee 100644 --- a/gcc/rust/typecheck/rust-coercion.cc +++ b/gcc/rust/typecheck/rust-coercion.cc @@ -125,13 +125,15 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver) // pointers switch (expected->get_kind ()) { - case TyTy::TypeKind::POINTER: { + case TyTy::TypeKind::POINTER: + { TyTy::PointerType *ptr = static_cast (expected); try_result = coerce_unsafe_ptr (receiver, ptr, ptr->mutability ()); return !try_result.is_error (); } - case TyTy::TypeKind::REF: { + case TyTy::TypeKind::REF: + { TyTy::ReferenceType *ptr = static_cast (expected); try_result @@ -147,7 +149,8 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver) // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L210 switch (receiver->get_kind ()) { - default: { + default: + { rust_debug ( "do_coercion default unify and infer expected: %s receiver %s", receiver->debug_str ().c_str (), expected->debug_str ().c_str ()); @@ -182,7 +185,8 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver, TyTy::BaseType *element = nullptr; switch (receiver->get_kind ()) { - case TyTy::TypeKind::REF: { + case TyTy::TypeKind::REF: + { TyTy::ReferenceType *ref = static_cast (receiver); from_mutbl = ref->mutability (); @@ -190,14 +194,16 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver, } break; - case TyTy::TypeKind::POINTER: { + case TyTy::TypeKind::POINTER: + { TyTy::PointerType *ref = static_cast (receiver); from_mutbl = ref->mutability (); element = ref->get_base (); } break; - default: { + default: + { // FIXME this can probably turn into a unify_and if (receiver->can_eq (expected, false)) return CoercionResult{{}, expected->clone ()}; @@ -264,14 +270,16 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver, Mutability from_mutbl = Mutability::Imm; switch (receiver->get_kind ()) { - case TyTy::TypeKind::REF: { + case TyTy::TypeKind::REF: + { TyTy::ReferenceType *from = static_cast (receiver); from_mutbl = from->mutability (); } break; - default: { + default: + { // FIXME // we might be able to replace this with a can_eq because we default // back to a final unity anyway diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index 032bb5841272..35c9b0a6a2d3 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -224,7 +224,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference) // handling. break; - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { auto &typaram = static_cast (*generic_param); bool is_self = typaram.get_type_representation ().as_string ().compare ("Self") @@ -543,7 +544,8 @@ AssociatedImplTrait::setup_associated_types ( // handling. break; - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { TyTy::BaseType *l = nullptr; bool ok = context->lookup_type ( generic_param->get_mappings ().get_hirid (), &l); @@ -753,7 +755,8 @@ TraitItemReference::is_object_safe () const // https://doc.rust-lang.org/reference/items/traits.html#object-safety switch (get_trait_item_type ()) { - case TraitItemReference::TraitItemType::FN: { + case TraitItemReference::TraitItemType::FN: + { // lets be boring and just check that this is indeed a method will do // for now const HIR::TraitItem *item = get_hir_trait_item (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index 14b8ab8635e1..6d5806f967f8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -124,7 +124,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, TyTy::BaseType *infered = nullptr; switch (literal.get_lit_type ()) { - case HIR::Literal::LitType::INT: { + case HIR::Literal::LitType::INT: + { bool ok = false; switch (literal.get_type_hint ()) @@ -191,7 +192,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, } break; - case HIR::Literal::LitType::FLOAT: { + case HIR::Literal::LitType::FLOAT: + { bool ok = false; switch (literal.get_type_hint ()) @@ -216,25 +218,29 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, } break; - case HIR::Literal::LitType::BOOL: { + case HIR::Literal::LitType::BOOL: + { auto ok = context->lookup_builtin ("bool", &infered); rust_assert (ok); } break; - case HIR::Literal::LitType::CHAR: { + case HIR::Literal::LitType::CHAR: + { auto ok = context->lookup_builtin ("char", &infered); rust_assert (ok); } break; - case HIR::Literal::LitType::BYTE: { + case HIR::Literal::LitType::BYTE: + { auto ok = context->lookup_builtin ("u8", &infered); rust_assert (ok); } break; - case HIR::Literal::LitType::STRING: { + case HIR::Literal::LitType::STRING: + { TyTy::BaseType *base = nullptr; auto ok = context->lookup_builtin ("str", &base); rust_assert (ok); @@ -246,7 +252,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, } break; - case HIR::Literal::LitType::BYTE_STRING: { + case HIR::Literal::LitType::BYTE_STRING: + { /* This is an arraytype of u8 reference (&[u8;size]). It isn't in UTF-8, but really just a byte array. Code to construct the array reference copied from ArrayElemsValues and ArrayType. */ @@ -440,7 +447,8 @@ TypeCheckBase::resolve_generic_params ( { switch (generic_param->get_kind ()) { - case HIR::GenericParam::GenericKind::LIFETIME: { + case HIR::GenericParam::GenericKind::LIFETIME: + { auto lifetime_param = static_cast (*generic_param); auto lifetime = lifetime_param.get_lifetime (); @@ -449,7 +457,8 @@ TypeCheckBase::resolve_generic_params ( } break; - case HIR::GenericParam::GenericKind::CONST: { + case HIR::GenericParam::GenericKind::CONST: + { if (is_foreign && abi != Rust::ABI::INTRINSIC) { rust_error_at (generic_param->get_locus (), ErrorCode::E0044, @@ -478,7 +487,8 @@ TypeCheckBase::resolve_generic_params ( } break; - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { if (is_foreign && abi != Rust::ABI::INTRINSIC) { rust_error_at (generic_param->get_locus (), ErrorCode::E0044, diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 7283d01d5a3c..905d669b3545 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -373,7 +373,8 @@ TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) switch (expr.get_expr_type ()) { case ArithmeticOrLogicalOperator::LEFT_SHIFT: - case ArithmeticOrLogicalOperator::RIGHT_SHIFT: { + case ArithmeticOrLogicalOperator::RIGHT_SHIFT: + { TyTy::TyWithLocation from (rhs, expr.get_rhs ().get_locus ()); TyTy::TyWithLocation to (lhs, expr.get_lhs ().get_locus ()); infered = cast_site (expr.get_mappings ().get_hirid (), from, to, @@ -381,7 +382,8 @@ TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) } break; - default: { + default: + { infered = unify_site ( expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (lhs, expr.get_lhs ().get_locus ()), @@ -470,7 +472,8 @@ TypeCheckExpr::visit (HIR::NegationExpr &expr) // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators switch (expr.get_expr_type ()) { - case NegationOperator::NEGATE: { + case NegationOperator::NEGATE: + { bool valid = (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT) @@ -492,7 +495,8 @@ TypeCheckExpr::visit (HIR::NegationExpr &expr) } break; - case NegationOperator::NOT: { + case NegationOperator::NOT: + { bool valid = (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL) || (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) @@ -790,38 +794,45 @@ typecheck_inline_asm_operand (HIR::InlineAsm &expr) { switch (operand.get_register_type ()) { - case RegisterType::In: { + case RegisterType::In: + { auto in = operand.get_in (); TypeCheckExpr::Resolve (*in.expr); break; } - case RegisterType::Out: { + case RegisterType::Out: + { auto out = operand.get_out (); TypeCheckExpr::Resolve (*out.expr); break; } - case RegisterType::InOut: { + case RegisterType::InOut: + { auto in_out = operand.get_in_out (); TypeCheckExpr::Resolve (*in_out.expr); break; } - case RegisterType::SplitInOut: { + case RegisterType::SplitInOut: + { auto split_in_out = operand.get_split_in_out (); TypeCheckExpr::Resolve (*split_in_out.in_expr); TypeCheckExpr::Resolve (*split_in_out.out_expr); break; } - case RegisterType::Const: { + case RegisterType::Const: + { auto anon_const = operand.get_const ().anon_const; TypeCheckExpr::Resolve (*anon_const.expr); break; } - case RegisterType::Sym: { + case RegisterType::Sym: + { auto sym = operand.get_sym (); TypeCheckExpr::Resolve (*sym.expr); break; } - case RegisterType::Label: { + case RegisterType::Label: + { auto label = operand.get_label (); TypeCheckExpr::Resolve (*label.expr); break; @@ -996,8 +1007,7 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr) rich_location r (line_table, expr.get_locus ()); r.add_range (expr.get_array_expr ().get_locus ()); r.add_range (expr.get_index_expr ().get_locus ()); - rust_error_at (r, ErrorCode::E0277, - "the type %qs cannot be indexed by %qs", + rust_error_at (r, ErrorCode::E0277, "the type %qs cannot be indexed by %qs", array_expr_ty->get_name ().c_str (), index_expr_ty->get_name ().c_str ()); } @@ -1011,7 +1021,8 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) TyTy::BaseType *element_type = nullptr; switch (elements.get_array_expr_type ()) { - case HIR::ArrayElems::ArrayExprType::COPIED: { + case HIR::ArrayElems::ArrayExprType::COPIED: + { HIR::ArrayElemsCopied &elems = static_cast (elements); element_type = TypeCheckExpr::Resolve (elems.get_elem_to_copy ()); @@ -1035,7 +1046,8 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) } break; - case HIR::ArrayElems::ArrayExprType::VALUES: { + case HIR::ArrayElems::ArrayExprType::VALUES: + { HIR::ArrayElemsValues &elems = static_cast (elements); diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc index bc7f6dc58c48..168a934fa540 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc @@ -266,7 +266,8 @@ TypeCheckImplItem::visit (HIR::Function &function) self_type = self->clone (); break; - case HIR::SelfParam::IMM_REF: { + case HIR::SelfParam::IMM_REF: + { tl::optional region; if (self_param.has_lifetime ()) { @@ -290,7 +291,8 @@ TypeCheckImplItem::visit (HIR::Function &function) } break; - case HIR::SelfParam::MUT_REF: { + case HIR::SelfParam::MUT_REF: + { tl::optional region; if (self_param.has_lifetime ()) { @@ -494,10 +496,9 @@ TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant) rich_location r (line_table, constant.get_locus ()); r.add_range (resolved_trait_item.get_locus ()); - rust_error_at ( - r, "constant %qs has an incompatible type for trait %qs", - constant.get_identifier ().as_string ().c_str (), - trait_reference.get_name ().c_str ()); + rust_error_at (r, "constant %qs has an incompatible type for trait %qs", + constant.get_identifier ().as_string ().c_str (), + trait_reference.get_name ().c_str ()); } } @@ -545,10 +546,9 @@ TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type) rich_location r (line_table, type.get_locus ()); r.add_range (resolved_trait_item.get_locus ()); - rust_error_at ( - r, "type alias %qs has an incompatible type for trait %qs", - type.get_new_type_name ().as_string ().c_str (), - trait_reference.get_name ().c_str ()); + rust_error_at (r, "type alias %qs has an incompatible type for trait %qs", + type.get_new_type_name ().as_string ().c_str (), + trait_reference.get_name ().c_str ()); } // its actually a projection, since we need a way to actually bind the diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index bd13f7a56185..102083bd84c3 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -213,13 +213,15 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern) auto &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: { + case HIR::TupleStructItems::RANGED: + { // TODO rust_unreachable (); } break; - case HIR::TupleStructItems::MULTIPLE: { + case HIR::TupleStructItems::MULTIPLE: + { HIR::TupleStructItemsNoRange &items_no_range = static_cast (items); @@ -333,13 +335,15 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) { switch (field->get_item_type ()) { - case HIR::StructPatternField::ItemType::TUPLE_PAT: { + case HIR::StructPatternField::ItemType::TUPLE_PAT: + { // TODO rust_unreachable (); } break; - case HIR::StructPatternField::ItemType::IDENT_PAT: { + case HIR::StructPatternField::ItemType::IDENT_PAT: + { HIR::StructPatternFieldIdentPat &ident = static_cast (*field); @@ -358,7 +362,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) } break; - case HIR::StructPatternField::ItemType::IDENT: { + case HIR::StructPatternField::ItemType::IDENT: + { HIR::StructPatternFieldIdent &ident = static_cast (*field); @@ -397,7 +402,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) case HIR::StructPatternField::ItemType::IDENT: case HIR::StructPatternField::ItemType::IDENT_PAT: break; - default: { + default: + { auto first_elem = struct_pattern_elems.get_struct_pattern_fields () .at (0) @@ -459,7 +465,8 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) std::unique_ptr items; switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::MULTIPLE: { + case HIR::TuplePatternItems::ItemType::MULTIPLE: + { auto &ref = static_cast ( pattern.get_items ()); @@ -498,7 +505,8 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) } break; - case HIR::TuplePatternItems::ItemType::RANGED: { + case HIR::TuplePatternItems::ItemType::RANGED: + { // HIR::TuplePatternItemsRanged &ref // = *static_cast ( // pattern.get_items ().get ()); @@ -608,7 +616,8 @@ TypeCheckPattern::typecheck_range_pattern_bound ( TyTy::BaseType *resolved_bound = nullptr; switch (bound.get_bound_type ()) { - case HIR::RangePatternBound::RangePatternBoundType::LITERAL: { + case HIR::RangePatternBound::RangePatternBoundType::LITERAL: + { auto &ref = static_cast (bound); HIR::Literal lit = ref.get_literal (); @@ -617,14 +626,16 @@ TypeCheckPattern::typecheck_range_pattern_bound ( } break; - case HIR::RangePatternBound::RangePatternBoundType::PATH: { + case HIR::RangePatternBound::RangePatternBoundType::PATH: + { auto &ref = static_cast (bound); resolved_bound = TypeCheckExpr::Resolve (ref.get_path ()); } break; - case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: { + case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: + { auto &ref = static_cast (bound); resolved_bound = TypeCheckExpr::Resolve (ref.get_qualified_path ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index df1636a584a5..e3a08e6f044d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -329,8 +329,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) repeat_location.add_range (prev_field_locus); rust_error_at (repeat_location, ErrorCode::E0062, - "field %qs specified more than once", - field_name.c_str ()); + "field %qs specified more than once", field_name.c_str ()); return false; } diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 6919093b0f5f..18e04581ab83 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -908,7 +908,8 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam ¶m, { switch (bound->get_bound_type ()) { - case HIR::TypeParamBound::BoundType::TRAITBOUND: { + case HIR::TypeParamBound::BoundType::TRAITBOUND: + { HIR::TraitBound &b = static_cast (*bound); TyTy::TypeBoundPredicate predicate = get_predicate_from_bound ( @@ -920,7 +921,8 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam ¶m, { switch (predicate.get_polarity ()) { - case BoundPolarity::AntiBound: { + case BoundPolarity::AntiBound: + { bool found = predicates.find (predicate.get_id ()) != predicates.end (); if (found) @@ -937,7 +939,8 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam ¶m, } break; - default: { + default: + { if (predicates.find (predicate.get_id ()) == predicates.end ()) { @@ -1033,7 +1036,8 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item) { switch (bound->get_bound_type ()) { - case HIR::TypeParamBound::BoundType::TRAITBOUND: { + case HIR::TypeParamBound::BoundType::TRAITBOUND: + { auto *b = static_cast (bound.get ()); TyTy::TypeBoundPredicate predicate @@ -1042,7 +1046,8 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item) specified_bounds.push_back (std::move (predicate)); } break; - case HIR::TypeParamBound::BoundType::LIFETIME: { + case HIR::TypeParamBound::BoundType::LIFETIME: + { if (auto param = binding->try_as ()) { auto *b = static_cast (bound.get ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index fbaf3230d737..d386fda036bb 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -29,8 +29,7 @@ // for flag_name_resolution_2_0 #include "options.h" -extern bool -saw_errors (void); +extern bool saw_errors (void); namespace Rust { namespace Resolver { @@ -231,7 +230,8 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const break; case HIR::SelfParam::IMM_REF: - case HIR::SelfParam::MUT_REF: { + case HIR::SelfParam::MUT_REF: + { auto mutability = self_param.get_self_kind () == HIR::SelfParam::IMM_REF ? Mutability::Imm diff --git a/gcc/rust/typecheck/rust-type-util.h b/gcc/rust/typecheck/rust-type-util.h index 03874a48bd8e..dd97f1e989ac 100644 --- a/gcc/rust/typecheck/rust-type-util.h +++ b/gcc/rust/typecheck/rust-type-util.h @@ -25,33 +25,30 @@ namespace Rust { namespace Resolver { -bool -query_type (HirId reference, TyTy::BaseType **result); +bool query_type (HirId reference, TyTy::BaseType **result); -bool -types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t unify_locus, bool emit_errors); +bool types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, + location_t unify_locus, bool emit_errors); -TyTy::BaseType * -unify_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t unify_locus); +TyTy::BaseType *unify_site (HirId id, TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, location_t unify_locus); -TyTy::BaseType * -unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t unify_locus, bool emit_errors, bool commit_if_ok, - bool implicit_infer_vars, bool cleanup); +TyTy::BaseType *unify_site_and (HirId id, TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, + location_t unify_locus, bool emit_errors, + bool commit_if_ok, bool implicit_infer_vars, + bool cleanup); -TyTy::BaseType * -coercion_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t coercion_locus); +TyTy::BaseType *coercion_site (HirId id, TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, + location_t coercion_locus); -TyTy::BaseType * -try_coercion (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t coercion_locus); +TyTy::BaseType *try_coercion (HirId id, TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, + location_t coercion_locus); -TyTy::BaseType * -cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to, - location_t cast_locus); +TyTy::BaseType *cast_site (HirId id, TyTy::TyWithLocation from, + TyTy::TyWithLocation to, location_t cast_locus); AssociatedImplTrait * lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound, diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index e028a0af80bb..5d42f80221ee 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -226,7 +226,8 @@ TypeCheckBase::get_predicate_from_bound ( auto &final_seg = type_path.get_final_segment (); switch (final_seg.get_type ()) { - case HIR::TypePathSegment::SegmentType::GENERIC: { + case HIR::TypePathSegment::SegmentType::GENERIC: + { auto &final_generic_seg = static_cast (final_seg); if (final_generic_seg.has_generic_args ()) @@ -251,7 +252,8 @@ TypeCheckBase::get_predicate_from_bound ( } break; - case HIR::TypePathSegment::SegmentType::FUNCTION: { + case HIR::TypePathSegment::SegmentType::FUNCTION: + { auto &final_function_seg = static_cast (final_seg); auto &fn = final_function_seg.get_function_path (); diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc index 2e0830e4adad..5ce31243d9bc 100644 --- a/gcc/rust/typecheck/rust-tyty-call.cc +++ b/gcc/rust/typecheck/rust-tyty-call.cc @@ -171,7 +171,8 @@ TypeCheckCallExpr::visit (FnType &type) { case TyTy::TypeKind::ERROR: return; - case TyTy::TypeKind::INT: { + case TyTy::TypeKind::INT: + { auto &int_ty = static_cast (*argument_expr_tyty); if ((int_ty.get_int_kind () == TyTy::IntType::IntKind::I8) @@ -186,7 +187,8 @@ TypeCheckCallExpr::visit (FnType &type) } break; } - case TyTy::TypeKind::UINT: { + case TyTy::TypeKind::UINT: + { auto &uint_ty = static_cast (*argument_expr_tyty); if ((uint_ty.get_uint_kind () == TyTy::UintType::UintKind::U8) @@ -202,7 +204,8 @@ TypeCheckCallExpr::visit (FnType &type) } break; } - case TyTy::TypeKind::FLOAT: { + case TyTy::TypeKind::FLOAT: + { if (static_cast (*argument_expr_tyty) .get_float_kind () == TyTy::FloatType::FloatKind::F32) @@ -216,14 +219,16 @@ TypeCheckCallExpr::visit (FnType &type) } break; } - case TyTy::TypeKind::BOOL: { + case TyTy::TypeKind::BOOL: + { rich_location richloc (line_table, arg_locus); richloc.add_fixit_replace ("cast the value to c_int: as c_int"); rust_error_at (arg_locus, ErrorCode::E0617, "expected % variadic argument"); return; } - case TyTy::TypeKind::FNDEF: { + case TyTy::TypeKind::FNDEF: + { rust_error_at ( arg_locus, ErrorCode::E0617, "unexpected function definition type as variadic " diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h index c897c1321bde..aeefaa9323b1 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -621,7 +621,8 @@ class InferCmp : public BaseCmp ok = true; return; - case InferType::InferTypeKind::INTEGRAL: { + case InferType::InferTypeKind::INTEGRAL: + { if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL) { ok = true; @@ -635,7 +636,8 @@ class InferCmp : public BaseCmp } break; - case InferType::InferTypeKind::FLOAT: { + case InferType::InferTypeKind::FLOAT: + { if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) { ok = true; diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis.h b/gcc/rust/typecheck/rust-tyty-variance-analysis.h index 9059a2f225d3..282c6f305b49 100644 --- a/gcc/rust/typecheck/rust-tyty-variance-analysis.h +++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.h @@ -41,9 +41,10 @@ class CrateCtx std::unique_ptr private_ctx; }; -std::vector -query_field_regions (const ADTType *parent, size_t variant_index, - size_t field_index, const FreeRegions &parent_regions); +std::vector query_field_regions (const ADTType *parent, + size_t variant_index, + size_t field_index, + const FreeRegions &parent_regions); /** Variance semilattice */ class Variance diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index f0f4a07e9660..25310d3c34b2 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -230,11 +230,13 @@ BaseType::is_unit () const case NEVER: return true; - case TUPLE: { + case TUPLE: + { return x->as ()->num_fields () == 0; } - case ADT: { + case ADT: + { auto adt = x->as (); if (adt->is_enum ()) return false; @@ -894,28 +896,32 @@ BaseType::has_substitutions_defined () const case OPAQUE: return false; - case PROJECTION: { + case PROJECTION: + { const ProjectionType &p = *static_cast (x); const SubstitutionRef &ref = static_cast (p); return ref.has_substitutions (); } break; - case FNDEF: { + case FNDEF: + { const FnType &fn = *static_cast (x); const SubstitutionRef &ref = static_cast (fn); return ref.has_substitutions (); } break; - case ADT: { + case ADT: + { const ADTType &adt = *static_cast (x); const SubstitutionRef &ref = static_cast (adt); return ref.has_substitutions (); } break; - case CLOSURE: { + case CLOSURE: + { const ClosureType &closure = *static_cast (x); const SubstitutionRef &ref = static_cast (closure); @@ -956,28 +962,32 @@ BaseType::needs_generic_substitutions () const case OPAQUE: return false; - case PROJECTION: { + case PROJECTION: + { const ProjectionType &p = *static_cast (x); const SubstitutionRef &ref = static_cast (p); return ref.needs_substitution (); } break; - case FNDEF: { + case FNDEF: + { const FnType &fn = *static_cast (x); const SubstitutionRef &ref = static_cast (fn); return ref.needs_substitution (); } break; - case ADT: { + case ADT: + { const ADTType &adt = *static_cast (x); const SubstitutionRef &ref = static_cast (adt); return ref.needs_substitution (); } break; - case CLOSURE: { + case CLOSURE: + { const ClosureType &closure = *static_cast (x); const SubstitutionRef &ref = static_cast (closure); @@ -996,28 +1006,32 @@ BaseType::get_subst_argument_mappings () const const TyTy::BaseType *x = destructure (); switch (x->get_kind ()) { - case PROJECTION: { + case PROJECTION: + { const auto &p = *static_cast (x); const auto &ref = static_cast (p); return ref.get_substitution_arguments (); } break; - case FNDEF: { + case FNDEF: + { const auto &fn = *static_cast (x); const auto &ref = static_cast (fn); return ref.get_substitution_arguments (); } break; - case ADT: { + case ADT: + { const auto &adt = *static_cast (x); const auto &ref = static_cast (adt); return ref.get_substitution_arguments (); } break; - case CLOSURE: { + case CLOSURE: + { const auto &closure = *static_cast (x); const auto &ref = static_cast (closure); return ref.get_substitution_arguments (); @@ -1140,13 +1154,15 @@ InferType::default_type (BaseType **type) const case GENERAL: return false; - case INTEGRAL: { + case INTEGRAL: + { ok = context->lookup_builtin ("i32", type); rust_assert (ok); return ok; } - case FLOAT: { + case FLOAT: + { ok = context->lookup_builtin ("f64", type); rust_assert (ok); return ok; @@ -1269,7 +1285,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint) default_hint.kind = hint.get_kind (); break; - case INT: { + case INT: + { infer_kind = INTEGRAL; default_hint.kind = hint.get_kind (); default_hint.shint = TypeHint::SignedHint::SIGNED; @@ -1294,7 +1311,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint) } break; - case UINT: { + case UINT: + { infer_kind = INTEGRAL; default_hint.kind = hint.get_kind (); default_hint.shint = TypeHint::SignedHint::UNSIGNED; @@ -1319,7 +1337,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint) } break; - case TypeKind::FLOAT: { + case TypeKind::FLOAT: + { infer_kind = FLOAT; default_hint.shint = TypeHint::SignedHint::SIGNED; default_hint.kind = hint.get_kind (); diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 1cada9a4030b..81e15c896410 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -78,8 +78,7 @@ enum TypeKind ERROR }; -extern bool -is_primitive_type_kind (TypeKind kind); +extern bool is_primitive_type_kind (TypeKind kind); class TypeKindFormat { @@ -268,8 +267,8 @@ class CallableTypeInterface : public BaseType {} WARN_UNUSED_RESULT virtual size_t get_num_params () const = 0; - WARN_UNUSED_RESULT virtual BaseType * - get_param_type_at (size_t index) const = 0; + WARN_UNUSED_RESULT virtual BaseType *get_param_type_at (size_t index) const + = 0; WARN_UNUSED_RESULT virtual BaseType *get_return_type () const = 0; }; diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 294b677ba417..0ffab667433c 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -328,14 +328,16 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); switch (ltype->get_infer_kind ()) { case TyTy::InferType::InferTypeKind::GENERAL: return rtype->clone (); - case TyTy::InferType::InferTypeKind::INTEGRAL: { + case TyTy::InferType::InferTypeKind::INTEGRAL: + { bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL || r->get_infer_kind () @@ -345,7 +347,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, } break; - case TyTy::InferType::InferTypeKind::FLOAT: { + case TyTy::InferType::InferTypeKind::FLOAT: + { bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT || r->get_infer_kind () @@ -361,7 +364,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, case TyTy::INT: case TyTy::UINT: case TyTy::USIZE: - case TyTy::ISIZE: { + case TyTy::ISIZE: + { bool is_valid = (ltype->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) || (ltype->get_infer_kind () @@ -374,7 +378,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, } break; - case TyTy::FLOAT: { + case TyTy::FLOAT: + { bool is_valid = (ltype->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) || (ltype->get_infer_kind () @@ -404,7 +409,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, case TyTy::PROJECTION: case TyTy::DYNAMIC: case TyTy::CLOSURE: - case TyTy::OPAQUE: { + case TyTy::OPAQUE: + { bool is_valid = (ltype->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); if (is_valid) @@ -424,7 +430,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -433,7 +440,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::ADT: { + case TyTy::ADT: + { TyTy::ADTType &type = *static_cast (rtype); if (ltype->get_adt_kind () != type.get_adt_kind ()) { @@ -544,7 +552,8 @@ UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -589,7 +598,8 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -598,7 +608,8 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::REF: { + case TyTy::REF: + { TyTy::ReferenceType &type = *static_cast (rtype); auto base_type = ltype->get_base (); auto other_base_type = type.get_base (); @@ -660,7 +671,8 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -669,7 +681,8 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::POINTER: { + case TyTy::POINTER: + { TyTy::PointerType &type = *static_cast (rtype); auto base_type = ltype->get_base (); auto other_base_type = type.get_base (); @@ -731,7 +744,8 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -740,7 +754,8 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::PARAM: { + case TyTy::PARAM: + { TyTy::ParamType &type = *static_cast (rtype); // bool symbol_matches // = ltype->get_symbol ().compare (type.get_symbol ()) == 0; @@ -793,7 +808,8 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -802,7 +818,8 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::ARRAY: { + case TyTy::ARRAY: + { TyTy::ArrayType &type = *static_cast (rtype); TyTy::BaseType *element_unify = UnifyRules::Resolve ( TyTy::TyWithLocation (ltype->get_element_type ()), @@ -853,7 +870,8 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -862,7 +880,8 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::SLICE: { + case TyTy::SLICE: + { TyTy::SliceType &type = *static_cast (rtype); TyTy::BaseType *element_unify = UnifyRules::Resolve ( TyTy::TyWithLocation (ltype->get_element_type ()), @@ -912,7 +931,8 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -921,7 +941,8 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::FNDEF: { + case TyTy::FNDEF: + { TyTy::FnType &type = *static_cast (rtype); if (ltype->num_params () != type.num_params ()) { @@ -1003,7 +1024,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1012,7 +1034,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) } break; - case TyTy::FNPTR: { + case TyTy::FNPTR: + { TyTy::FnPtr &type = *static_cast (rtype); if (ltype->num_params () != type.num_params ()) { @@ -1048,7 +1071,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) } break; - case TyTy::FNDEF: { + case TyTy::FNDEF: + { TyTy::FnType &type = *static_cast (rtype); auto this_ret_type = ltype->get_return_type (); auto other_ret_type = type.get_return_type (); @@ -1120,7 +1144,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1129,7 +1154,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::TUPLE: { + case TyTy::TUPLE: + { TyTy::TupleType &type = *static_cast (rtype); if (ltype->num_fields () != type.num_fields ()) { @@ -1191,7 +1217,8 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1239,7 +1266,8 @@ UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1287,7 +1315,8 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL @@ -1300,7 +1329,8 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::INT: { + case TyTy::INT: + { TyTy::IntType &type = *static_cast (rtype); bool is_valid = ltype->get_int_kind () == type.get_int_kind (); if (is_valid) @@ -1342,7 +1372,8 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL @@ -1355,7 +1386,8 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::UINT: { + case TyTy::UINT: + { TyTy::UintType &type = *static_cast (rtype); bool is_valid = ltype->get_uint_kind () == type.get_uint_kind (); if (is_valid) @@ -1397,7 +1429,8 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL @@ -1410,7 +1443,8 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::FLOAT: { + case TyTy::FLOAT: + { TyTy::FloatType &type = *static_cast (rtype); bool is_valid = ltype->get_float_kind () == type.get_float_kind (); if (is_valid) @@ -1452,7 +1486,8 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT; @@ -1500,7 +1535,8 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT; @@ -1548,7 +1584,8 @@ UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1569,7 +1606,8 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype, { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1619,7 +1657,8 @@ UnifyRules::expect_projection (TyTy::ProjectionType *ltype, { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1666,7 +1705,8 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1675,7 +1715,8 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::DYNAMIC: { + case TyTy::DYNAMIC: + { TyTy::DynamicObjectType &type = *static_cast (rtype); if (ltype->num_specified_bounds () != type.num_specified_bounds ()) @@ -1725,7 +1766,8 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1734,7 +1776,8 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::CLOSURE: { + case TyTy::CLOSURE: + { TyTy::ClosureType &type = *static_cast (rtype); if (ltype->get_def_id () != type.get_def_id ()) { @@ -1796,7 +1839,8 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1805,7 +1849,8 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::OPAQUE: { + case TyTy::OPAQUE: + { auto &type = *static_cast (rtype); if (ltype->num_specified_bounds () != type.num_specified_bounds ()) { diff --git a/gcc/rust/util/rust-abi.h b/gcc/rust/util/rust-abi.h index a0180ed4d951..357a5db95ffc 100644 --- a/gcc/rust/util/rust-abi.h +++ b/gcc/rust/util/rust-abi.h @@ -34,11 +34,9 @@ enum ABI SYSV64 }; -extern Rust::ABI -get_abi_from_string (const std::string &abi); +extern Rust::ABI get_abi_from_string (const std::string &abi); -extern std::string -get_string_from_abi (Rust::ABI abi); +extern std::string get_string_from_abi (Rust::ABI abi); } // namespace Rust diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index c77e99c1ca5a..9bf4f7773c68 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -221,7 +221,8 @@ check_doc_attribute (const AST::Attribute &attribute) break; // FIXME: Handle them as well - case AST::AttrInput::TOKEN_TREE: { + case AST::AttrInput::TOKEN_TREE: + { // FIXME: This doesn't check for #[doc(alias(...))] const auto &option = static_cast ( attribute.get_attr_input ()); diff --git a/gcc/rust/util/rust-base62.h b/gcc/rust/util/rust-base62.h index e751c95f18f5..5fd7a37292e5 100644 --- a/gcc/rust/util/rust-base62.h +++ b/gcc/rust/util/rust-base62.h @@ -26,8 +26,7 @@ namespace Rust { /** * Get the Base62 representation of an integer */ -std::string -base62_integer (uint64_t value); +std::string base62_integer (uint64_t value); } // namespace Rust diff --git a/gcc/rust/util/rust-dir-owner.h b/gcc/rust/util/rust-dir-owner.h index dcb45d84278c..fb72bb1551cb 100644 --- a/gcc/rust/util/rust-dir-owner.h +++ b/gcc/rust/util/rust-dir-owner.h @@ -26,8 +26,7 @@ namespace Rust { // extracts the owned subdirectory name from a file name -bool -get_file_subdir (const std::string &filename, std::string &subdir); +bool get_file_subdir (const std::string &filename, std::string &subdir); } // namespace Rust diff --git a/gcc/rust/util/rust-edition.h b/gcc/rust/util/rust-edition.h index d034ea03a6f1..532fedb98799 100644 --- a/gcc/rust/util/rust-edition.h +++ b/gcc/rust/util/rust-edition.h @@ -33,8 +33,7 @@ enum class Edition E2021 }; -Edition -get_rust_edition (); +Edition get_rust_edition (); } // namespace Rust diff --git a/gcc/rust/util/rust-punycode.h b/gcc/rust/util/rust-punycode.h index a939f05e886d..75260ce0468a 100644 --- a/gcc/rust/util/rust-punycode.h +++ b/gcc/rust/util/rust-punycode.h @@ -27,8 +27,7 @@ namespace Rust { /* Encode a string as punycode. Returns a string if encoding is successful. * Returns nullopt otherwise. Note that a returned string contains only ASCII * characters and does not start with `xn--`. */ -tl::optional -encode_punycode (const Utf8String &src); +tl::optional encode_punycode (const Utf8String &src); } // namespace Rust @@ -36,8 +35,7 @@ encode_punycode (const Utf8String &src); namespace selftest { -void -rust_punycode_encode_test (); +void rust_punycode_encode_test (); } // namespace selftest diff --git a/gcc/rust/util/rust-token-converter.cc b/gcc/rust/util/rust-token-converter.cc index fc34adb9b195..52172f40cfa6 100644 --- a/gcc/rust/util/rust-token-converter.cc +++ b/gcc/rust/util/rust-token-converter.cc @@ -202,7 +202,8 @@ convert (const std::vector &tokens) case PERCENT_EQ: case SCOPE_RESOLUTION: case NOT_EQUAL: - case EQUAL_EQUAL: { + case EQUAL_EQUAL: + { auto str = token->as_string (); auto it = str.cbegin (); for (; it != str.cend () - 1; it++) @@ -260,9 +261,8 @@ convert (const std::vector &tokens) return trees.back (); } -static void -from_tokenstream (const ProcMacro::TokenStream &ts, - std::vector &result); +static void from_tokenstream (const ProcMacro::TokenStream &ts, + std::vector &result); /** * Append the token corresponding to a given Ident to a vector. diff --git a/gcc/rust/util/rust-token-converter.h b/gcc/rust/util/rust-token-converter.h index 5405d6e59d6e..6e4af50439ef 100644 --- a/gcc/rust/util/rust-token-converter.h +++ b/gcc/rust/util/rust-token-converter.h @@ -23,14 +23,11 @@ namespace Rust { -ProcMacro::TokenStream -convert (const std::vector &tokens); +ProcMacro::TokenStream convert (const std::vector &tokens); -std::vector -convert (const ProcMacro::TokenStream &ts); +std::vector convert (const ProcMacro::TokenStream &ts); -ProcMacro::Literal -convert_literal (const_TokenPtr lit); +ProcMacro::Literal convert_literal (const_TokenPtr lit); } // namespace Rust diff --git a/gcc/rust/util/rust-unicode.h b/gcc/rust/util/rust-unicode.h index 6a6526db3090..6579b806976e 100644 --- a/gcc/rust/util/rust-unicode.h +++ b/gcc/rust/util/rust-unicode.h @@ -59,20 +59,15 @@ class Utf8String Utf8String nfc_normalize () const; }; -bool -is_alphabetic (uint32_t codepoint); +bool is_alphabetic (uint32_t codepoint); -bool -is_ascii_only (const std::string &str); +bool is_ascii_only (const std::string &str); -bool -is_numeric (uint32_t codepoint); +bool is_numeric (uint32_t codepoint); -bool -is_nfc_qc_no (uint32_t codepoint); +bool is_nfc_qc_no (uint32_t codepoint); -bool -is_nfc_qc_maybe (uint32_t codepoint); +bool is_nfc_qc_maybe (uint32_t codepoint); enum class QuickCheckResult { @@ -81,8 +76,7 @@ enum class QuickCheckResult MAYBE }; -QuickCheckResult -nfc_quick_check (const std::vector &s); +QuickCheckResult nfc_quick_check (const std::vector &s); } // namespace Rust @@ -90,14 +84,11 @@ nfc_quick_check (const std::vector &s); namespace selftest { -void -rust_nfc_qc_test (); +void rust_nfc_qc_test (); -void -rust_utf8_normalize_test (); +void rust_utf8_normalize_test (); -void -rust_utf8_property_test (); +void rust_utf8_property_test (); } // namespace selftest diff --git a/gcc/rust/util/rust-unwrap-segment.h b/gcc/rust/util/rust-unwrap-segment.h index bebdc3aadd4d..af3a237ea28e 100644 --- a/gcc/rust/util/rust-unwrap-segment.h +++ b/gcc/rust/util/rust-unwrap-segment.h @@ -83,14 +83,11 @@ template class unwrap_type_segment_inner /* * Used to get the node id of a path segment object */ -NodeId -unwrap_segment_node_id (const AST::TypePathSegment &seg); +NodeId unwrap_segment_node_id (const AST::TypePathSegment &seg); -NodeId -unwrap_segment_node_id (const AST::SimplePathSegment &seg); +NodeId unwrap_segment_node_id (const AST::SimplePathSegment &seg); -NodeId -unwrap_segment_node_id (const AST::PathExprSegment &seg); +NodeId unwrap_segment_node_id (const AST::PathExprSegment &seg); template NodeId diff --git a/libgrust/libproc_macro_internal/ffistring.h b/libgrust/libproc_macro_internal/ffistring.h index e176bc299850..b133b35bcb0f 100644 --- a/libgrust/libproc_macro_internal/ffistring.h +++ b/libgrust/libproc_macro_internal/ffistring.h @@ -43,11 +43,9 @@ struct FFIString }; extern "C" { -FFIString -FFIString__new (const unsigned char *data, std::uint64_t len); +FFIString FFIString__new (const unsigned char *data, std::uint64_t len); -void -FFIString__drop (FFIString *str); +void FFIString__drop (FFIString *str); } } // namespace ProcMacro diff --git a/libgrust/libproc_macro_internal/ident.h b/libgrust/libproc_macro_internal/ident.h index cdc9b0d5d95d..839471675a78 100644 --- a/libgrust/libproc_macro_internal/ident.h +++ b/libgrust/libproc_macro_internal/ident.h @@ -47,17 +47,13 @@ struct Ident extern "C" { -Ident -Ident__new (FFIString str, Span span); +Ident Ident__new (FFIString str, Span span); -Ident -Ident__new_raw (FFIString str, Span span); +Ident Ident__new_raw (FFIString str, Span span); -void -Ident__drop (Ident *ident); +void Ident__drop (Ident *ident); -Ident -Ident__clone (const Ident *ident); +Ident Ident__clone (const Ident *ident); } } // namespace ProcMacro diff --git a/libgrust/libproc_macro_internal/literal.h b/libgrust/libproc_macro_internal/literal.h index c8579471b9df..b30c69a2925d 100644 --- a/libgrust/libproc_macro_internal/literal.h +++ b/libgrust/libproc_macro_internal/literal.h @@ -105,8 +105,7 @@ struct Literal }; extern "C" { -bool -Literal__from_string (FFIString str, Literal *lit); +bool Literal__from_string (FFIString str, Literal *lit); } } // namespace ProcMacro diff --git a/libgrust/libproc_macro_internal/proc_macro.h b/libgrust/libproc_macro_internal/proc_macro.h index ce9adb24734d..d5f2e20d8d69 100644 --- a/libgrust/libproc_macro_internal/proc_macro.h +++ b/libgrust/libproc_macro_internal/proc_macro.h @@ -96,8 +96,7 @@ struct ProcmacroArray Procmacro *macros; }; -extern "C" bool -bridge_is_available (); +extern "C" bool bridge_is_available (); } // namespace ProcMacro diff --git a/libgrust/libproc_macro_internal/tokenstream.h b/libgrust/libproc_macro_internal/tokenstream.h index 4e13ce7690d9..f24d4ab68925 100644 --- a/libgrust/libproc_macro_internal/tokenstream.h +++ b/libgrust/libproc_macro_internal/tokenstream.h @@ -51,23 +51,17 @@ struct TokenStream static void drop (TokenStream *stream); }; -extern "C" TokenStream -TokenStream__new (); +extern "C" TokenStream TokenStream__new (); -extern "C" TokenStream -TokenStream__with_capacity (std::uint64_t capacity); +extern "C" TokenStream TokenStream__with_capacity (std::uint64_t capacity); -extern "C" void -TokenSream__push (TokenStream *stream, TokenTree tree); +extern "C" void TokenSream__push (TokenStream *stream, TokenTree tree); -extern "C" bool -TokenStream__from_string (FFIString str, TokenStream *ts); +extern "C" bool TokenStream__from_string (FFIString str, TokenStream *ts); -extern "C" TokenStream -TokenStream__clone (const TokenStream *ts); +extern "C" TokenStream TokenStream__clone (const TokenStream *ts); -extern "C" void -TokenStream__drop (TokenStream *stream); +extern "C" void TokenStream__drop (TokenStream *stream); } // namespace ProcMacro From d53c3a2e76c86fbbc7dc1c94801573006674114d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Poulhi=C3=A8s?= Date: Tue, 13 May 2025 21:28:16 +0200 Subject: [PATCH 023/161] gccrs: remove now useless clang-format comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Config has been updated upstream to correctly indent declaration. gcc/rust/ChangeLog: * rust-attribs.cc (handle_hot_attribute): Remove clang-format comment. Signed-off-by: Marc Poulhiès --- gcc/rust/rust-attribs.cc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/gcc/rust/rust-attribs.cc b/gcc/rust/rust-attribs.cc index 195dfbd57887..a98c1fab0403 100644 --- a/gcc/rust/rust-attribs.cc +++ b/gcc/rust/rust-attribs.cc @@ -41,10 +41,6 @@ along with GCC; see the file COPYING3. If not see extern const struct scoped_attribute_specs grs_langhook_gnu_attribute_table; extern const struct scoped_attribute_specs grs_langhook_common_attribute_table; -/* clang-format off */ -/* Disable clang-format because it insists in having the return type on a - single line (that's for definitions) */ - /* Internal attribute handlers for built-in functions. */ static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); static tree handle_leaf_attribute (tree *, tree, tree, int, bool *); @@ -64,8 +60,6 @@ static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); static tree handle_cold_attribute (tree *, tree, tree, int, bool *); static tree handle_hot_attribute (tree *, tree, tree, int, bool *); -/* clang-format on */ - /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ { \ From 73f625f3db3466aaac364997165b848a280bf8c8 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Thu, 8 May 2025 17:32:05 -0400 Subject: [PATCH 024/161] Small improvements to DefaultASTVisitor and nr2.0 gcc/rust/ChangeLog: * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Only visit the path of an instance of Visibility if the instance has a path. * ast/rust-ast.h (SimplePath::SimplePath): Make sure constructors are explicit. * resolve/rust-early-name-resolver-2.0.cc (Early::visit_attributes): Pass entire paths to NameResolutionContext::resolve_path. (Early::visit): Likewise and avoid copying a path. * resolve/rust-forever-stack.hxx (ForeverStack::resolve_path): Assert that at least one path segment has been passed in. Signed-off-by: Owen Avery --- gcc/rust/ast/rust-ast-visitor.cc | 3 ++- gcc/rust/ast/rust-ast.h | 8 ++++---- gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 12 ++++++------ gcc/rust/resolve/rust-forever-stack.hxx | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 8c1d9ff61356..d197db66cf49 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -762,7 +762,8 @@ DefaultASTVisitor::visit (AST::TypeBoundWhereClauseItem &item) void DefaultASTVisitor::visit (AST::Visibility &vis) { - visit (vis.get_path ()); + if (vis.has_path ()) + visit (vis.get_path ()); } void diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 5ce92231434d..fa8616e8db6c 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -402,15 +402,15 @@ class SimplePath public: // Constructor - SimplePath (std::vector path_segments, - bool has_opening_scope_resolution = false, - location_t locus = UNDEF_LOCATION) + explicit SimplePath (std::vector path_segments, + bool has_opening_scope_resolution = false, + location_t locus = UNDEF_LOCATION) : opening_scope_resolution (has_opening_scope_resolution), segments (std::move (path_segments)), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} - SimplePath (Identifier ident) + explicit SimplePath (Identifier ident) : opening_scope_resolution (false), segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}), locus (ident.get_locus ()), diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 9d2b77a0e3ab..1e29c7967b82 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -249,7 +249,7 @@ Early::visit (AST::Module &module) void Early::visit (AST::MacroInvocation &invoc) { - auto path = invoc.get_invoc_data ().get_path (); + auto &path = invoc.get_invoc_data ().get_path (); if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin) for (auto &pending_invoc : invoc.get_pending_eager_invocations ()) @@ -272,7 +272,7 @@ Early::visit (AST::MacroInvocation &invoc) // we won't have changed `definition` from `nullopt` if there are more // than one segments in our path if (!definition.has_value ()) - definition = ctx.resolve_path (path.get_segments (), Namespace::Macros); + definition = ctx.resolve_path (path, Namespace::Macros); // if the definition still does not have a value, then it's an error if (!definition.has_value ()) @@ -314,8 +314,8 @@ Early::visit_attributes (std::vector &attrs) auto traits = attr.get_traits_to_derive (); for (auto &trait : traits) { - auto definition = ctx.resolve_path (trait.get ().get_segments (), - Namespace::Macros); + auto definition + = ctx.resolve_path (trait.get (), Namespace::Macros); if (!definition.has_value ()) { // FIXME: Change to proper error message @@ -337,8 +337,8 @@ Early::visit_attributes (std::vector &attrs) ->lookup_builtin (name) .is_error ()) // Do not resolve builtins { - auto definition = ctx.resolve_path (attr.get_path ().get_segments (), - Namespace::Macros); + auto definition + = ctx.resolve_path (attr.get_path (), Namespace::Macros); if (!definition.has_value ()) { // FIXME: Change to proper error message diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 069111eeb0e0..17136b86ffcd 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -629,7 +629,7 @@ ForeverStack::resolve_path ( std::function insert_segment_resolution, std::vector &collect_errors) { - // TODO: What to do if segments.empty() ? + rust_assert (!segments.empty ()); // handle paths with opening scopes std::function cleanup_current = [] () {}; From ed0013d9679d954f5e8ceb522b2bcab9eb2b8d6a Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Wed, 28 Feb 2024 23:26:39 +0100 Subject: [PATCH 025/161] Rust: Move 'libformat_parser' build into the GCC build directory Fixes Rust-GCC#2883. * .gitignore: Remove 'libgrust/*/target/'. --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 7150fc3b29ca..f044fe16b5f6 100644 --- a/.gitignore +++ b/.gitignore @@ -71,6 +71,3 @@ stamp-* /gmp* /isl* /gettext* - -# ADDITIONS from GCCRS front-end -libgrust/*/target/ From 685bc4d476fc3635a5ede5833fe8c59924677375 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Tue, 13 May 2025 18:01:33 -0400 Subject: [PATCH 026/161] Remove rvalue reference binding This should be unnecessary, since even C++11 has implicit move. gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_expr_stmt): Avoid reference binding and remove std::move in return statements. Signed-off-by: Owen Avery --- gcc/rust/parse/rust-parse-impl.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index b661040a7159..7a4d47658f12 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -7103,10 +7103,7 @@ Parser::parse_expr_stmt (AST::AttrVec outer_attrs, if (lexer.peek_token ()->get_id () == EXCLAM) { - // Bind a reference to avoid -Wredundant-move on post-P1825R0 - // compilers. Change to non-reference type and remove the moves - // below once C++20 is required to build gcc. - std::unique_ptr &&invoc + std::unique_ptr invoc = parse_macro_invocation_partial (std::move (path), std::move (outer_attrs)); @@ -7114,7 +7111,7 @@ Parser::parse_expr_stmt (AST::AttrVec outer_attrs, { invoc->add_semicolon (); // Macro invocation with semicolon. - return std::move (invoc); + return invoc; } TokenId after_macro = lexer.peek_token ()->get_id (); @@ -7122,14 +7119,14 @@ Parser::parse_expr_stmt (AST::AttrVec outer_attrs, if (restrictions.allow_close_after_expr_stmt && (after_macro == RIGHT_PAREN || after_macro == RIGHT_CURLY || after_macro == RIGHT_SQUARE)) - return std::move (invoc); + return invoc; if (invoc->get_invoc_data ().get_delim_tok_tree ().get_delim_type () == AST::CURLY && after_macro != DOT && after_macro != QUESTION_MARK) { rust_debug ("braced macro statement"); - return std::move (invoc); + return invoc; } null_denotation = std::move (invoc); From df9e42340fb08453465ce611470630be84785bcc Mon Sep 17 00:00:00 2001 From: Tom Schollenberger Date: Sun, 11 May 2025 22:57:28 -0400 Subject: [PATCH 027/161] gccrs: Fix NR2 ICE in visit_attributes Undefined attribute macros have no proc macro definition, which results in a failing `rust_assert`. This changes that assert to an if statement, that returns early if there is no proc macro definition. Fixes #3661. gcc/rust/ChangeLog: * resolve/rust-early-name-resolver-2.0.cc (Early::visit_attributes): rust_assert to if gcc/testsuite/ChangeLog: * rust/compile/issue-3661.rs: Test NR2 has expected behavior Signed-off-by: Tom Schollenberger --- gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 3 ++- gcc/testsuite/rust/compile/issue-3661.rs | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/rust/compile/issue-3661.rs diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 1e29c7967b82..b00bd1ee7f8e 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -350,7 +350,8 @@ Early::visit_attributes (std::vector &attrs) auto pm_def = mappings.lookup_attribute_proc_macro_def ( definition->get_node_id ()); - rust_assert (pm_def.has_value ()); + if (!pm_def.has_value ()) + return; mappings.insert_attribute_proc_macro_invocation (attr.get_path (), pm_def.value ()); diff --git a/gcc/testsuite/rust/compile/issue-3661.rs b/gcc/testsuite/rust/compile/issue-3661.rs new file mode 100644 index 000000000000..8d03c3630d56 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3661.rs @@ -0,0 +1,10 @@ +pub macro m($inner_str:expr) { + #[m = $inner_str] + // { dg-error "macro not found" "" { target *-*-* } .-1 } + + struct S; +} + +fn main() { + m!(stringify!(foo)); +} From 8a0bb51bb3dcb8b2d6cffbf90a64e11a37ec05df Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Wed, 14 May 2025 20:05:55 -0400 Subject: [PATCH 028/161] nr2.0: Fix test builtin_abort.rs gcc/testsuite/ChangeLog: * rust/execute/torture/builtin_abort.rs: Fix path to intrinsics::abort. Signed-off-by: Owen Avery --- gcc/testsuite/rust/execute/torture/builtin_abort.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/testsuite/rust/execute/torture/builtin_abort.rs b/gcc/testsuite/rust/execute/torture/builtin_abort.rs index 9f2d8c2d9f38..8c8259adcb7c 100644 --- a/gcc/testsuite/rust/execute/torture/builtin_abort.rs +++ b/gcc/testsuite/rust/execute/torture/builtin_abort.rs @@ -9,6 +9,6 @@ mod intrinsics { } pub fn main () -> i32 { - abort(); + intrinsics::abort(); 0 } From ab260206cb8488a4ca682682d8549ea154b2e7b7 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Wed, 14 May 2025 18:22:33 -0400 Subject: [PATCH 029/161] nr2.0: Fix some paths in test files This is similar to 9faba024ef18b9c4d67f22bd3b020b5e445fad0a, but it applies to execute tests. gcc/testsuite/ChangeLog: * rust/execute/torture/for-loop1.rs: Adjust paths. * rust/execute/torture/for-loop2.rs: Likewise. * rust/execute/torture/iter1.rs: Likewise. Signed-off-by: Owen Avery --- .../rust/execute/torture/for-loop1.rs | 38 +++++++++---------- .../rust/execute/torture/for-loop2.rs | 38 +++++++++---------- gcc/testsuite/rust/execute/torture/iter1.rs | 38 +++++++++---------- 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/gcc/testsuite/rust/execute/torture/for-loop1.rs b/gcc/testsuite/rust/execute/torture/for-loop1.rs index 5a6a70c37d64..334218927b13 100644 --- a/gcc/testsuite/rust/execute/torture/for-loop1.rs +++ b/gcc/testsuite/rust/execute/torture/for-loop1.rs @@ -102,30 +102,30 @@ mod ptr { #[lang = "const_ptr"] impl *const T { pub unsafe fn offset(self, count: isize) -> *const T { - intrinsics::offset(self, count) + crate::intrinsics::offset(self, count) } } #[lang = "mut_ptr"] impl *mut T { pub unsafe fn offset(self, count: isize) -> *mut T { - intrinsics::offset(self, count) as *mut T + crate::intrinsics::offset(self, count) as *mut T } } pub unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { let x = x as *mut u8; let y = y as *mut u8; - let len = mem::size_of::() * count; + let len = crate::mem::size_of::() * count; swap_nonoverlapping_bytes(x, y, len) } pub unsafe fn swap_nonoverlapping_one(x: *mut T, y: *mut T) { // For types smaller than the block optimization below, // just swap directly to avoid pessimizing codegen. - if mem::size_of::() < 32 { + if crate::mem::size_of::() < 32 { let z = read(x); - intrinsics::copy_nonoverlapping(y, x, 1); + crate::intrinsics::copy_nonoverlapping(y, x, 1); write(y, z); } else { swap_nonoverlapping(x, y, 1); @@ -133,12 +133,12 @@ mod ptr { } pub unsafe fn write(dst: *mut T, src: T) { - intrinsics::move_val_init(&mut *dst, src) + crate::intrinsics::move_val_init(&mut *dst, src) } pub unsafe fn read(src: *const T) -> T { - let mut tmp: T = mem::uninitialized(); - intrinsics::copy_nonoverlapping(src, &mut tmp, 1); + let mut tmp: T = crate::mem::uninitialized(); + crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1); tmp } @@ -146,7 +146,7 @@ mod ptr { struct Block(u64, u64, u64, u64); struct UnalignedBlock(u64, u64, u64, u64); - let block_size = mem::size_of::(); + let block_size = crate::mem::size_of::(); // Loop through x & y, copying them `Block` at a time // The optimizer should unroll the loop fully for most types @@ -155,31 +155,31 @@ mod ptr { while i + block_size <= len { // Create some uninitialized memory as scratch space // Declaring `t` here avoids aligning the stack when this loop is unused - let mut t: Block = mem::uninitialized(); + let mut t: Block = crate::mem::uninitialized(); let t = &mut t as *mut _ as *mut u8; let x = x.offset(i as isize); let y = y.offset(i as isize); // Swap a block of bytes of x & y, using t as a temporary buffer // This should be optimized into efficient SIMD operations where available - intrinsics::copy_nonoverlapping(x, t, block_size); - intrinsics::copy_nonoverlapping(y, x, block_size); - intrinsics::copy_nonoverlapping(t, y, block_size); + crate::intrinsics::copy_nonoverlapping(x, t, block_size); + crate::intrinsics::copy_nonoverlapping(y, x, block_size); + crate::intrinsics::copy_nonoverlapping(t, y, block_size); i += block_size; } if i < len { // Swap any remaining bytes - let mut t: UnalignedBlock = mem::uninitialized(); + let mut t: UnalignedBlock = crate::mem::uninitialized(); let rem = len - i; let t = &mut t as *mut _ as *mut u8; let x = x.offset(i as isize); let y = y.offset(i as isize); - intrinsics::copy_nonoverlapping(x, t, rem); - intrinsics::copy_nonoverlapping(y, x, rem); - intrinsics::copy_nonoverlapping(t, y, rem); + crate::intrinsics::copy_nonoverlapping(x, t, rem); + crate::intrinsics::copy_nonoverlapping(y, x, rem); + crate::intrinsics::copy_nonoverlapping(t, y, rem); } } } @@ -194,7 +194,7 @@ mod mem { pub fn swap(x: &mut T, y: &mut T) { unsafe { - ptr::swap_nonoverlapping_one(x, y); + crate::ptr::swap_nonoverlapping_one(x, y); } } @@ -204,7 +204,7 @@ mod mem { } pub unsafe fn uninitialized() -> T { - intrinsics::uninit() + crate::intrinsics::uninit() } } diff --git a/gcc/testsuite/rust/execute/torture/for-loop2.rs b/gcc/testsuite/rust/execute/torture/for-loop2.rs index 5ba2cd1351a6..4f5dfe1a0a26 100644 --- a/gcc/testsuite/rust/execute/torture/for-loop2.rs +++ b/gcc/testsuite/rust/execute/torture/for-loop2.rs @@ -101,30 +101,30 @@ mod ptr { #[lang = "const_ptr"] impl *const T { pub unsafe fn offset(self, count: isize) -> *const T { - intrinsics::offset(self, count) + crate::intrinsics::offset(self, count) } } #[lang = "mut_ptr"] impl *mut T { pub unsafe fn offset(self, count: isize) -> *mut T { - intrinsics::offset(self, count) as *mut T + crate::intrinsics::offset(self, count) as *mut T } } pub unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { let x = x as *mut u8; let y = y as *mut u8; - let len = mem::size_of::() * count; + let len = crate::mem::size_of::() * count; swap_nonoverlapping_bytes(x, y, len) } pub unsafe fn swap_nonoverlapping_one(x: *mut T, y: *mut T) { // For types smaller than the block optimization below, // just swap directly to avoid pessimizing codegen. - if mem::size_of::() < 32 { + if crate::mem::size_of::() < 32 { let z = read(x); - intrinsics::copy_nonoverlapping(y, x, 1); + crate::intrinsics::copy_nonoverlapping(y, x, 1); write(y, z); } else { swap_nonoverlapping(x, y, 1); @@ -132,12 +132,12 @@ mod ptr { } pub unsafe fn write(dst: *mut T, src: T) { - intrinsics::move_val_init(&mut *dst, src) + crate::intrinsics::move_val_init(&mut *dst, src) } pub unsafe fn read(src: *const T) -> T { - let mut tmp: T = mem::uninitialized(); - intrinsics::copy_nonoverlapping(src, &mut tmp, 1); + let mut tmp: T = crate::mem::uninitialized(); + crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1); tmp } @@ -145,7 +145,7 @@ mod ptr { struct Block(u64, u64, u64, u64); struct UnalignedBlock(u64, u64, u64, u64); - let block_size = mem::size_of::(); + let block_size = crate::mem::size_of::(); // Loop through x & y, copying them `Block` at a time // The optimizer should unroll the loop fully for most types @@ -154,31 +154,31 @@ mod ptr { while i + block_size <= len { // Create some uninitialized memory as scratch space // Declaring `t` here avoids aligning the stack when this loop is unused - let mut t: Block = mem::uninitialized(); + let mut t: Block = crate::mem::uninitialized(); let t = &mut t as *mut _ as *mut u8; let x = x.offset(i as isize); let y = y.offset(i as isize); // Swap a block of bytes of x & y, using t as a temporary buffer // This should be optimized into efficient SIMD operations where available - intrinsics::copy_nonoverlapping(x, t, block_size); - intrinsics::copy_nonoverlapping(y, x, block_size); - intrinsics::copy_nonoverlapping(t, y, block_size); + crate::intrinsics::copy_nonoverlapping(x, t, block_size); + crate::intrinsics::copy_nonoverlapping(y, x, block_size); + crate::intrinsics::copy_nonoverlapping(t, y, block_size); i += block_size; } if i < len { // Swap any remaining bytes - let mut t: UnalignedBlock = mem::uninitialized(); + let mut t: UnalignedBlock = crate::mem::uninitialized(); let rem = len - i; let t = &mut t as *mut _ as *mut u8; let x = x.offset(i as isize); let y = y.offset(i as isize); - intrinsics::copy_nonoverlapping(x, t, rem); - intrinsics::copy_nonoverlapping(y, x, rem); - intrinsics::copy_nonoverlapping(t, y, rem); + crate::intrinsics::copy_nonoverlapping(x, t, rem); + crate::intrinsics::copy_nonoverlapping(y, x, rem); + crate::intrinsics::copy_nonoverlapping(t, y, rem); } } } @@ -193,7 +193,7 @@ mod mem { pub fn swap(x: &mut T, y: &mut T) { unsafe { - ptr::swap_nonoverlapping_one(x, y); + crate::ptr::swap_nonoverlapping_one(x, y); } } @@ -203,7 +203,7 @@ mod mem { } pub unsafe fn uninitialized() -> T { - intrinsics::uninit() + crate::intrinsics::uninit() } } diff --git a/gcc/testsuite/rust/execute/torture/iter1.rs b/gcc/testsuite/rust/execute/torture/iter1.rs index c3b6c7bc3f89..233eb60383b3 100644 --- a/gcc/testsuite/rust/execute/torture/iter1.rs +++ b/gcc/testsuite/rust/execute/torture/iter1.rs @@ -99,30 +99,30 @@ mod ptr { #[lang = "const_ptr"] impl *const T { pub unsafe fn offset(self, count: isize) -> *const T { - intrinsics::offset(self, count) + crate::intrinsics::offset(self, count) } } #[lang = "mut_ptr"] impl *mut T { pub unsafe fn offset(self, count: isize) -> *mut T { - intrinsics::offset(self, count) as *mut T + crate::intrinsics::offset(self, count) as *mut T } } pub unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { let x = x as *mut u8; let y = y as *mut u8; - let len = mem::size_of::() * count; + let len = crate::mem::size_of::() * count; swap_nonoverlapping_bytes(x, y, len) } pub unsafe fn swap_nonoverlapping_one(x: *mut T, y: *mut T) { // For types smaller than the block optimization below, // just swap directly to avoid pessimizing codegen. - if mem::size_of::() < 32 { + if crate::mem::size_of::() < 32 { let z = read(x); - intrinsics::copy_nonoverlapping(y, x, 1); + crate::intrinsics::copy_nonoverlapping(y, x, 1); write(y, z); } else { swap_nonoverlapping(x, y, 1); @@ -130,12 +130,12 @@ mod ptr { } pub unsafe fn write(dst: *mut T, src: T) { - intrinsics::move_val_init(&mut *dst, src) + crate::intrinsics::move_val_init(&mut *dst, src) } pub unsafe fn read(src: *const T) -> T { - let mut tmp: T = mem::uninitialized(); - intrinsics::copy_nonoverlapping(src, &mut tmp, 1); + let mut tmp: T = crate::mem::uninitialized(); + crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1); tmp } @@ -143,7 +143,7 @@ mod ptr { struct Block(u64, u64, u64, u64); struct UnalignedBlock(u64, u64, u64, u64); - let block_size = mem::size_of::(); + let block_size = crate::mem::size_of::(); // Loop through x & y, copying them `Block` at a time // The optimizer should unroll the loop fully for most types @@ -152,31 +152,31 @@ mod ptr { while i + block_size <= len { // Create some uninitialized memory as scratch space // Declaring `t` here avoids aligning the stack when this loop is unused - let mut t: Block = mem::uninitialized(); + let mut t: Block = crate::mem::uninitialized(); let t = &mut t as *mut _ as *mut u8; let x = x.offset(i as isize); let y = y.offset(i as isize); // Swap a block of bytes of x & y, using t as a temporary buffer // This should be optimized into efficient SIMD operations where available - intrinsics::copy_nonoverlapping(x, t, block_size); - intrinsics::copy_nonoverlapping(y, x, block_size); - intrinsics::copy_nonoverlapping(t, y, block_size); + crate::intrinsics::copy_nonoverlapping(x, t, block_size); + crate::intrinsics::copy_nonoverlapping(y, x, block_size); + crate::intrinsics::copy_nonoverlapping(t, y, block_size); i += block_size; } if i < len { // Swap any remaining bytes - let mut t: UnalignedBlock = mem::uninitialized(); + let mut t: UnalignedBlock = crate::mem::uninitialized(); let rem = len - i; let t = &mut t as *mut _ as *mut u8; let x = x.offset(i as isize); let y = y.offset(i as isize); - intrinsics::copy_nonoverlapping(x, t, rem); - intrinsics::copy_nonoverlapping(y, x, rem); - intrinsics::copy_nonoverlapping(t, y, rem); + crate::intrinsics::copy_nonoverlapping(x, t, rem); + crate::intrinsics::copy_nonoverlapping(y, x, rem); + crate::intrinsics::copy_nonoverlapping(t, y, rem); } } } @@ -191,7 +191,7 @@ mod mem { pub fn swap(x: &mut T, y: &mut T) { unsafe { - ptr::swap_nonoverlapping_one(x, y); + crate::ptr::swap_nonoverlapping_one(x, y); } } @@ -201,7 +201,7 @@ mod mem { } pub unsafe fn uninitialized() -> T { - intrinsics::uninit() + crate::intrinsics::uninit() } } From 1982968c7cfd4e09613170f88c0b8661dcaa9b0d Mon Sep 17 00:00:00 2001 From: Parthib Date: Sat, 21 Jan 2023 18:33:07 +0000 Subject: [PATCH 030/161] Revert 10-second timeout for each test Signed-off-by: Parthib --- gcc/testsuite/lib/rust.exp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/gcc/testsuite/lib/rust.exp b/gcc/testsuite/lib/rust.exp index 9513e1c89558..692030cf8832 100644 --- a/gcc/testsuite/lib/rust.exp +++ b/gcc/testsuite/lib/rust.exp @@ -168,10 +168,7 @@ proc rust_target_compile { source dest type options } { global gluefile wrap_flags global ALWAYS_RUSTFLAGS global RUST_UNDER_TEST - global individual_timeout - - # HACK: guard against infinite loops in the compiler - set individual_timeout 10 + if { [target_info needs_status_wrapper] != "" && [info exists gluefile] } { lappend options "libs=${gluefile}" From eac67a204d4a560f661ddd331c4242df4cdd393e Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 19 May 2025 17:55:53 +0100 Subject: [PATCH 031/161] gccrs: refactor default infer vars to be its own function This is just a simple refactor to pull all the logic outside of the closure which makes it more readable. gcc/rust/ChangeLog: * typecheck/rust-hir-type-check.h: new function * typecheck/rust-typecheck-context.cc (TypeCheckContext::compute_inference_variables): call the new helper (TypeCheckContext::compute_infer_var): refactored code Signed-off-by: Philip Herron --- gcc/rust/typecheck/rust-hir-type-check.h | 4 +- gcc/rust/typecheck/rust-typecheck-context.cc | 67 +++++++++++--------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 18a65fec0483..356c55803ed6 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -263,13 +263,15 @@ class TypeCheckContext WARN_UNUSED_RESULT std::vector regions_from_generic_args (const HIR::GenericArgs &args) const; - void compute_inference_variables (bool error); + void compute_inference_variables (bool emit_error); TyTy::VarianceAnalysis::CrateCtx &get_variance_analysis_ctx (); private: TypeCheckContext (); + bool compute_infer_var (HirId id, TyTy::BaseType *ty, bool emit_error); + std::map node_id_refs; std::map resolved; std::vector> builtins; diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc index 9112b998f168..7b3584823e44 100644 --- a/gcc/rust/typecheck/rust-typecheck-context.cc +++ b/gcc/rust/typecheck/rust-typecheck-context.cc @@ -575,43 +575,48 @@ TypeCheckContext::regions_from_generic_args (const HIR::GenericArgs &args) const } void -TypeCheckContext::compute_inference_variables (bool error) +TypeCheckContext::compute_inference_variables (bool emit_error) { - auto &mappings = Analysis::Mappings::get (); - // default inference variables if possible iterate ([&] (HirId id, TyTy::BaseType *ty) mutable -> bool { - // nothing to do - if (ty->get_kind () != TyTy::TypeKind::INFER) - return true; + return compute_infer_var (id, ty, emit_error); + }); +} - TyTy::InferType *infer_var = static_cast (ty); - TyTy::BaseType *default_type; - - rust_debug_loc (mappings.lookup_location (id), - "trying to default infer-var: %s", - infer_var->as_string ().c_str ()); - bool ok = infer_var->default_type (&default_type); - if (!ok) - { - if (error) - rust_error_at (mappings.lookup_location (id), ErrorCode::E0282, - "type annotations needed"); - return true; - } - - auto result - = unify_site (id, TyTy::TyWithLocation (ty), - TyTy::TyWithLocation (default_type), UNDEF_LOCATION); - rust_assert (result); - rust_assert (result->get_kind () != TyTy::TypeKind::ERROR); - result->set_ref (id); - insert_type (Analysis::NodeMapping (mappings.get_current_crate (), 0, id, - UNKNOWN_LOCAL_DEFID), - result); +bool +TypeCheckContext::compute_infer_var (HirId id, TyTy::BaseType *ty, + bool emit_error) +{ + auto &mappings = Analysis::Mappings::get (); + // nothing to do + if (ty->get_kind () != TyTy::TypeKind::INFER) return true; - }); + + TyTy::InferType *infer_var = static_cast (ty); + TyTy::BaseType *default_type; + + rust_debug_loc (mappings.lookup_location (id), + "trying to default infer-var: %s", + infer_var->as_string ().c_str ()); + bool ok = infer_var->default_type (&default_type); + if (!ok) + { + if (emit_error) + rust_error_at (mappings.lookup_location (id), ErrorCode::E0282, + "type annotations needed"); + return true; + } + + auto result + = unify_site (id, TyTy::TyWithLocation (ty), + TyTy::TyWithLocation (default_type), UNDEF_LOCATION); + rust_assert (result); + rust_assert (result->get_kind () != TyTy::TypeKind::ERROR); + result->set_ref (id); + insert_implicit_type (id, result); + + return true; } TyTy::VarianceAnalysis::CrateCtx & From 484b02c4e2eda87b2f8eddcf53ebefa26ea80cc7 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 19 May 2025 17:42:17 +0100 Subject: [PATCH 032/161] gccrs: Remove unneeded clones untill we have an arena allocator for these tmps Cloning inference variables is very expensive because it means we are indirectly creating an implicit new inference variable added to the reference chain. gcc/rust/ChangeLog: * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::check_base_type_privacy): no need for unreachable here * typecheck/rust-unify.cc (UnifyRules::commit): dont clone infer vars (UnifyRules::expect_inference_variable): likewise Signed-off-by: Philip Herron --- .../errors/privacy/rust-privacy-reporter.cc | 3 ++- gcc/rust/typecheck/rust-unify.cc | 18 ++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc index 3faa3b404e69..e1d4b167d3d8 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc @@ -221,8 +221,9 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings, auto ref_id = ty->get_ref (); if (auto lookup_id = mappings.lookup_hir_to_node (ref_id)) return check_for_privacy_violation (*lookup_id, locus); - rust_unreachable (); } + break; + case TyTy::REF: return recursive_check ( static_cast (ty)->get_base ()); diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 0ffab667433c..6699f7e46b56 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -69,7 +69,6 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other, TyTy::BaseType *resolved) { TypeCheckContext &context = *TypeCheckContext::get (); - Analysis::Mappings &mappings = Analysis::Mappings::get (); TyTy::BaseType *b = base->destructure (); TyTy::BaseType *o = other->destructure (); @@ -102,13 +101,8 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other, continue; // if any of the types are inference variables lets fix them - if (ref_tyty->get_kind () == TyTy::TypeKind::INFER) - { - auto node = Analysis::NodeMapping (mappings.get_current_crate (), - UNKNOWN_NODEID, ref, - UNKNOWN_LOCAL_DEFID); - context.insert_type (node, resolved->clone ()); - } + if (ref_tyty->is ()) + context.insert_implicit_type (ref, resolved); } } } @@ -343,7 +337,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, || r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return rtype->clone (); + return rtype; } break; @@ -354,7 +348,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, || r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return rtype->clone (); + return rtype; } break; } @@ -373,7 +367,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, if (is_valid) { ltype->apply_primitive_type_hint (*rtype); - return rtype->clone (); + return rtype; } } break; @@ -387,7 +381,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, if (is_valid) { ltype->apply_primitive_type_hint (*rtype); - return rtype->clone (); + return rtype; } } break; From 8eba52565da9abf9d36533e0602c1063e83277db Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 26 May 2025 19:30:45 +0100 Subject: [PATCH 033/161] gccrs: Fix non canonical type bug with tuples When working on rpit we needed to change to use a monomorphized clone of the result of function calls. This ended up causing a verify gimple issue with tuples because: fn test(a: A, b: B) -> (A, B) When passing for example: let a = test:: (123, 456) -> (A=i32, B=i32) The resulting gimple types became: const struct (A=i32, B=i32) vs struct (i32, i32) We removed the VIEW_CONVERT_EXPR support to auto fix this stuff a good while ago because it hides these kinds of issues because the type hasher included the A=i32, B=i32 vs the i32, i32 name so updating this to use get_name instead keeps the naming the same as well as the fields meaning these types are 100% equivilant and therefore no conversion is required. This only occurs because tuples are not named types we should really add more rust specific info on our gimple TYPES. gcc/rust/ChangeLog: * backend/rust-compile-type.cc (TyTyResolveCompile::visit): use get_name * typecheck/rust-tyty.cc (TupleType::get_name): likewise Signed-off-by: Philip Herron --- gcc/rust/backend/rust-compile-type.cc | 2 +- gcc/rust/typecheck/rust-tyty.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index 83e5756429f5..af34c2281f54 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -454,7 +454,7 @@ TyTyResolveCompile::visit (const TyTy::TupleType &type) } tree struct_type_record = Backend::struct_type (fields); - translated = Backend::named_type (type.as_string (), struct_type_record, + translated = Backend::named_type (type.get_name (), struct_type_record, type.get_ident ().locus); } diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 25310d3c34b2..83b4c923aa6f 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -2011,7 +2011,7 @@ TupleType::get_name () const std::string fields_buffer; for (const TyVar &field : get_fields ()) { - fields_buffer += field.get_tyty ()->as_string (); + fields_buffer += field.get_tyty ()->get_name (); bool has_next = (i + 1) < get_fields ().size (); fields_buffer += has_next ? ", " : ""; i++; From a34ff4c4ae3cc90e235ddfb149a1ca9ae5d575f2 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 19 May 2025 18:02:13 +0100 Subject: [PATCH 034/161] gccrs: Initial support for Return Position Impl Trait This is the initial patch for RPIT, we can build on this to handle the more complex cases but there are enough distinct changes going on here that it should just get merged now. RPIT is really a sneaky generic so for example: fn foo() -> impl Bar { Baz } This is represented as: fn () -> OpaqueType Bar. But when we handle the coercion site for Baz on impl Bar when we type resolve the function we know that the underlying type is Baz. Note this function is _not_ generic so its using this special OpaqueType and keeping track of the underlying type in its ty_ref reference hir-id which will resolve to Baz. This also means if we have a case where maybe this was in an if statement: fn foo(a: i32) -> impl Bar { if a > 10 { Baz } else { Qux } } The rules of impl Bar is that Baz is handled but Baz and Qux are different underlying types so this is not allowed. The reason is impl traits are not generic and although from a programmer perspective the callers dont know what the underlying type is, the compiler _knows_ what it is. So really when you call a function and get its return position impl trait the compiler knows what to do and does all whats nessecary to handle calling functions using that type etc. gcc/rust/ChangeLog: * backend/rust-compile-type.cc (TyTyResolveCompile::visit): we need to resolve the underlying type * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): just clone * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): ensure we monomphize to get the underlying * typecheck/rust-tyty.cc (BaseType::destructure): handle opaque types (OpaqueType::resolve): this is much simpler now (OpaqueType::handle_substitions): no longer needed * typecheck/rust-tyty.h: update header * typecheck/rust-unify.cc (UnifyRules::expect_opaque): unify rules for opaque gcc/testsuite/ChangeLog: * rust/compile/bad-rpit1.rs: New test. * rust/execute/torture/impl_rpit1.rs: New test. * rust/execute/torture/impl_rpit2.rs: New test. * rust/execute/torture/impl_rpit3.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/backend/rust-compile-type.cc | 4 +- .../typecheck/rust-substitution-mapper.cc | 2 +- gcc/rust/typecheck/rust-tyty-call.cc | 2 +- gcc/rust/typecheck/rust-tyty.cc | 72 ++------------- gcc/rust/typecheck/rust-tyty.h | 2 - gcc/rust/typecheck/rust-unify.cc | 92 +++++++++---------- gcc/testsuite/rust/compile/bad-rpit1.rs | 26 ++++++ .../rust/execute/torture/impl_rpit1.rs | 28 ++++++ .../rust/execute/torture/impl_rpit2.rs | 36 ++++++++ .../rust/execute/torture/impl_rpit3.rs | 25 +++++ 10 files changed, 169 insertions(+), 120 deletions(-) create mode 100644 gcc/testsuite/rust/compile/bad-rpit1.rs create mode 100644 gcc/testsuite/rust/execute/torture/impl_rpit1.rs create mode 100644 gcc/testsuite/rust/execute/torture/impl_rpit2.rs create mode 100644 gcc/testsuite/rust/execute/torture/impl_rpit3.rs diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index af34c2281f54..00b21fbbf952 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -755,7 +755,9 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type) void TyTyResolveCompile::visit (const TyTy::OpaqueType &type) { - translated = error_mark_node; + rust_assert (type.can_resolve ()); + auto underlying = type.resolve (); + translated = TyTyResolveCompile::compile (ctx, underlying, trait_object_mode); } tree diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc index f0bd1f8bb17f..bdfde55718be 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.cc +++ b/gcc/rust/typecheck/rust-substitution-mapper.cc @@ -374,7 +374,7 @@ SubstMapperInternal::visit (TyTy::DynamicObjectType &type) void SubstMapperInternal::visit (TyTy::OpaqueType &type) { - resolved = type.handle_substitions (mappings); + resolved = type.clone (); } // SubstMapperFromExisting diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc index 5ce31243d9bc..63bb1ff91f80 100644 --- a/gcc/rust/typecheck/rust-tyty-call.cc +++ b/gcc/rust/typecheck/rust-tyty-call.cc @@ -251,7 +251,7 @@ TypeCheckCallExpr::visit (FnType &type) } type.monomorphize (); - resolved = type.get_return_type ()->clone (); + resolved = type.get_return_type ()->monomorphized_clone (); } void diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 83b4c923aa6f..91c68efe972d 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -548,17 +548,14 @@ BaseType::destructure () const { x = p->get (); } - // else if (auto p = x->try_as ()) - // { - // auto pr = p->resolve (); - - // rust_debug ("XXXXXX") - - // if (pr == x) - // return pr; + else if (auto p = x->try_as ()) + { + auto pr = p->resolve (); + if (pr == x) + return pr; - // x = pr; - // } + x = pr; + } else { return x; @@ -3643,28 +3640,7 @@ BaseType * OpaqueType::resolve () const { TyVar var (get_ty_ref ()); - BaseType *r = var.get_tyty (); - - while (r->get_kind () == TypeKind::OPAQUE) - { - OpaqueType *rr = static_cast (r); - if (!rr->can_resolve ()) - break; - - TyVar v (rr->get_ty_ref ()); - BaseType *n = v.get_tyty (); - - // fix infinite loop - if (r == n) - break; - - r = n; - } - - if (r->get_kind () == TypeKind::OPAQUE && (r->get_ref () == r->get_ty_ref ())) - return TyVar (r->get_ty_ref ()).get_tyty (); - - return r; + return var.get_tyty (); } bool @@ -3674,41 +3650,9 @@ OpaqueType::is_equal (const BaseType &other) const if (can_resolve () != other2.can_resolve ()) return false; - if (can_resolve ()) - return resolve ()->can_eq (other2.resolve (), false); - return bounds_compatible (other, UNDEF_LOCATION, false); } -OpaqueType * -OpaqueType::handle_substitions (SubstitutionArgumentMappings &subst_mappings) -{ - // SubstitutionArg arg = SubstitutionArg::error (); - // bool ok = subst_mappings.get_argument_for_symbol (this, &arg); - // if (!ok || arg.is_error ()) - // return this; - - // OpaqueType *p = static_cast (clone ()); - // subst_mappings.on_param_subst (*p, arg); - - // // there are two cases one where we substitute directly to a new PARAM and - // // otherwise - // if (arg.get_tyty ()->get_kind () == TyTy::TypeKind::PARAM) - // { - // p->set_ty_ref (arg.get_tyty ()->get_ref ()); - // return p; - // } - - // // this is the new subst that this needs to pass - // p->set_ref (mappings.get_next_hir_id ()); - // p->set_ty_ref (arg.get_tyty ()->get_ref ()); - - // return p; - - rust_unreachable (); - return nullptr; -} - // StrType StrType::StrType (HirId ref, std::set refs) diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 81e15c896410..c759521090da 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -440,8 +440,6 @@ class OpaqueType : public BaseType std::string get_name () const override final; bool is_equal (const BaseType &other) const override; - - OpaqueType *handle_substitions (SubstitutionArgumentMappings &mappings); }; class StructFieldType diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 6699f7e46b56..95463ae94734 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -1831,61 +1831,51 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) TyTy::BaseType * UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) { - switch (rtype->get_kind ()) + if (rtype->is ()) { - case TyTy::INFER: - { - TyTy::InferType *r = static_cast (rtype); - bool is_valid - = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; - if (is_valid) - return ltype->clone (); - } - break; + TyTy::OpaqueType *ro = rtype->as (); + if (!ltype->is_equal (*ro)) + return new TyTy::ErrorType (0); - case TyTy::OPAQUE: - { - auto &type = *static_cast (rtype); - if (ltype->num_specified_bounds () != type.num_specified_bounds ()) - { - return new TyTy::ErrorType (0); - } - - if (!ltype->bounds_compatible (type, locus, true)) - { + if (ltype->can_resolve () && ro->can_resolve ()) + { + auto lr = ltype->resolve (); + auto rr = ro->resolve (); + + auto res = UnifyRules::Resolve (TyTy::TyWithLocation (lr), + TyTy::TyWithLocation (rr), locus, + commit_flag, false /* emit_error */, + infer_flag, commits, infers); + if (res->get_kind () == TyTy::TypeKind::ERROR) return new TyTy::ErrorType (0); - } - - return ltype->clone (); - } - break; - - case TyTy::CLOSURE: - case TyTy::SLICE: - case TyTy::PARAM: - case TyTy::POINTER: - case TyTy::STR: - case TyTy::ADT: - case TyTy::REF: - case TyTy::ARRAY: - case TyTy::FNDEF: - case TyTy::FNPTR: - case TyTy::TUPLE: - case TyTy::BOOL: - case TyTy::CHAR: - case TyTy::INT: - case TyTy::UINT: - case TyTy::FLOAT: - case TyTy::USIZE: - case TyTy::ISIZE: - case TyTy::NEVER: - case TyTy::PLACEHOLDER: - case TyTy::PROJECTION: - case TyTy::DYNAMIC: - case TyTy::ERROR: - return new TyTy::ErrorType (0); + } + else if (ltype->can_resolve ()) + { + auto lr = ltype->resolve (); + ro->set_ty_ref (lr->get_ref ()); + } + else if (ro->can_resolve ()) + { + auto rr = ro->resolve (); + ltype->set_ty_ref (rr->get_ref ()); + } } - return new TyTy::ErrorType (0); + else if (ltype->can_resolve ()) + { + auto underly = ltype->resolve (); + auto res = UnifyRules::Resolve (TyTy::TyWithLocation (underly), + TyTy::TyWithLocation (rtype), locus, + commit_flag, false /* emit_error */, + infer_flag, commits, infers); + if (res->get_kind () == TyTy::TypeKind::ERROR) + return new TyTy::ErrorType (0); + } + else + { + ltype->set_ty_ref (rtype->get_ref ()); + } + + return ltype; } } // namespace Resolver diff --git a/gcc/testsuite/rust/compile/bad-rpit1.rs b/gcc/testsuite/rust/compile/bad-rpit1.rs new file mode 100644 index 000000000000..d8c21b11c64a --- /dev/null +++ b/gcc/testsuite/rust/compile/bad-rpit1.rs @@ -0,0 +1,26 @@ +#[lang = "sized"] +trait Sized {} + +trait Foo { + fn id(&self) -> i32; +} + +struct A; +struct B; + +impl Foo for A { + fn id(&self) -> i32 { + 1 + } +} + +impl Foo for B { + fn id(&self) -> i32 { + 2 + } +} + +fn make_foo(cond: bool) -> impl Foo { + if cond { A } else { B } + // { dg-error "mismatched types, expected .A. but got .B. .E0308." "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust/execute/torture/impl_rpit1.rs b/gcc/testsuite/rust/execute/torture/impl_rpit1.rs new file mode 100644 index 000000000000..8ce5f21ef87e --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_rpit1.rs @@ -0,0 +1,28 @@ +#[lang = "sized"] +trait Sized {} + +trait Foo { + fn id(&self) -> i32; +} + +struct Thing(i32); + +impl Foo for Thing { + fn id(&self) -> i32 { + self.0 + } +} + +fn make_thing(a: i32) -> impl Foo { + Thing(a) +} + +fn use_foo(f: impl Foo) -> i32 { + f.id() +} + +fn main() -> i32 { + let value = make_thing(42); + let val = use_foo(value); + val - 42 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_rpit2.rs b/gcc/testsuite/rust/execute/torture/impl_rpit2.rs new file mode 100644 index 000000000000..f7cbbb668649 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_rpit2.rs @@ -0,0 +1,36 @@ +#[lang = "sized"] +trait Sized {} + +trait Foo { + fn id(&self) -> i32; +} + +struct Thing(i32); + +impl Thing { + fn double(&self) -> i32 { + // { dg-warning "associated function is never used: .double." "" { target *-*-* } .-1 } + self.0 * 2 + } +} + +impl Foo for Thing { + fn id(&self) -> i32 { + self.0 + } +} + +fn make_thing(a: i32) -> impl Foo { + Thing(a) +} + +fn use_foo(f: impl Foo) -> i32 { + f.id() +} + +fn main() -> i32 { + let value = make_thing(21); + let id = use_foo(value); + + id - 21 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_rpit3.rs b/gcc/testsuite/rust/execute/torture/impl_rpit3.rs new file mode 100644 index 000000000000..dd68eb29ef96 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_rpit3.rs @@ -0,0 +1,25 @@ +#[lang = "sized"] +trait Sized {} + +trait Foo { + fn id(&self) -> i32; +} + +struct Thing(i32); + +impl Foo for Thing { + fn id(&self) -> i32 { + self.0 + } +} + +fn make_thing() -> impl Foo { + Thing(99) +} + +fn main() -> i32 { + let v = make_thing(); + let r = &v; + let val = r.id(); + val - 99 +} From c02a814a056e841504cfa289476c8b8c0275af45 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Wed, 14 May 2025 20:03:01 -0400 Subject: [PATCH 035/161] nr2.0: Fix IfLet pattern handling gcc/rust/ChangeLog: * resolve/rust-default-resolver.cc (DefaultResolver::visit_if_let_patterns): New function definition. (DefaultResolver::visit): New IfLetExpr visitor definition. * resolve/rust-default-resolver.h (DefaultResolver::visit_if_let_patterns): New function declaration. (DefaultResolver::visit): New IfLetExpr visitor declaration. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove IfLetExpr visitor definition. (Late::visit_if_let_patterns): New function definition. * resolve/rust-late-name-resolver-2.0.h (Late::visit): Remove IfLetExpr visitor declaration. (Late::visit_if_let_patterns): New function declaration. * resolve/rust-name-resolution-context.h (BindingSource::IfLet): New enumerator. Signed-off-by: Owen Avery --- gcc/rust/resolve/rust-default-resolver.cc | 22 +++++++++++++++++++ gcc/rust/resolve/rust-default-resolver.h | 2 ++ .../resolve/rust-late-name-resolver-2.0.cc | 12 +++------- .../resolve/rust-late-name-resolver-2.0.h | 2 +- .../resolve/rust-name-resolution-context.h | 1 + 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index dce5aaa6a11a..12f6e1c83349 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -60,6 +60,28 @@ DefaultResolver::visit (AST::ForLoopExpr &expr) [this, &expr] () { AST::DefaultASTVisitor::visit (expr); }); } +void +DefaultResolver::visit_if_let_patterns (AST::IfLetExpr &expr) +{ + for (auto &pattern : expr.get_patterns ()) + visit (pattern); +} + +void +DefaultResolver::visit (AST::IfLetExpr &expr) +{ + auto inner_vis = [this, &expr] () { + visit_if_let_patterns (expr); + visit (expr.get_if_block ()); + }; + + visit_outer_attrs (expr); + + visit (expr.get_value_expr ()); + + ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), inner_vis); +} + void DefaultResolver::visit (AST::Trait &trait) { diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 87281377d70f..639e87113d4b 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -46,6 +46,8 @@ class DefaultResolver : public AST::DefaultASTVisitor void visit (AST::Module &) override; void visit (AST::Function &) override; void visit (AST::ForLoopExpr &expr) override; + virtual void visit_if_let_patterns (AST::IfLetExpr &expr); + void visit (AST::IfLetExpr &expr) override; void visit (AST::Trait &) override; // used to handle Self insertion in TopLevel virtual void maybe_insert_big_self (AST::Impl &) {} diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 06bf4fd3b7d7..c056b726201e 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -147,19 +147,13 @@ Late::visit (AST::ForLoopExpr &expr) } void -Late::visit (AST::IfLetExpr &expr) +Late::visit_if_let_patterns (AST::IfLetExpr &expr) { - visit_outer_attrs (expr); + ctx.bindings.enter (BindingSource::IfLet); - ctx.bindings.enter (BindingSource::Let); - - for (auto &pattern : expr.get_patterns ()) - visit (pattern); + DefaultResolver::visit_if_let_patterns (expr); ctx.bindings.exit (); - - visit (expr.get_value_expr ()); - visit (expr.get_if_block ()); } void diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 171d9bfe0f6e..4b7b1b874112 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -50,7 +50,7 @@ class Late : public DefaultResolver void visit (AST::SelfParam &) override; void visit (AST::MatchArm &) override; void visit (AST::ForLoopExpr &) override; - void visit (AST::IfLetExpr &) override; + void visit_if_let_patterns (AST::IfLetExpr &) override; // resolutions void visit (AST::IdentifierExpr &) override; diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index 19ba75076869..cf87c8f1c79b 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -177,6 +177,7 @@ enum class BindingSource { Match, Let, + IfLet, For, /* Closure param or function param */ Param From 0bd45020f92d4e557bd0a52c4662bbb3d6170017 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 20 May 2025 18:44:57 +0100 Subject: [PATCH 036/161] gccrs: Always emit the error highest in the type hierarchy The unify code was a bit dumb here where we always set emit_error to false for any subtypes for example in comparing tuples we always emitted the whole tuple didnt match the other tuple but really its much better to say expected bool got i32 because the element types didn't match. gcc/rust/ChangeLog: * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsized): dont emit error here * typecheck/rust-unify.cc (UnifyRules::resolve_subtype): new helper to handle emit error (UnifyRules::expect_adt): call resolve_subtype (UnifyRules::expect_reference): likewise (UnifyRules::expect_pointer): likewise (UnifyRules::expect_array): likewise (UnifyRules::expect_slice): likewise (UnifyRules::expect_fndef): likewise (UnifyRules::expect_fnptr): likewise (UnifyRules::expect_tuple): likewise (UnifyRules::expect_closure): likewise (UnifyRules::expect_opaque): likeiwse * typecheck/rust-unify.h: add new helper to header gcc/testsuite/ChangeLog: * rust/compile/traits9.rs: update errors * rust/compile/unify-errors1.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/typecheck/rust-coercion.cc | 2 +- gcc/rust/typecheck/rust-unify.cc | 128 +++++++++----------- gcc/rust/typecheck/rust-unify.h | 3 + gcc/testsuite/rust/compile/traits9.rs | 3 +- gcc/testsuite/rust/compile/unify-errors1.rs | 49 ++++++++ 5 files changed, 110 insertions(+), 75 deletions(-) create mode 100644 gcc/testsuite/rust/compile/unify-errors1.rs diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc index 3a92a2f2f6ee..50c74ed689d3 100644 --- a/gcc/rust/typecheck/rust-coercion.cc +++ b/gcc/rust/typecheck/rust-coercion.cc @@ -401,7 +401,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, if (expect_dyn && need_unsize) { - bool bounds_compatible = b->bounds_compatible (*a, locus, true); + bool bounds_compatible = b->bounds_compatible (*a, locus, false); if (!bounds_compatible) { unsafe_error = true; diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 95463ae94734..9144f2eafba4 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -52,6 +52,22 @@ UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, return result; } +TyTy::BaseType * +UnifyRules::resolve_subtype (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs) +{ + TyTy::BaseType *result + = UnifyRules::Resolve (lhs, rhs, locus, commit_flag, emit_error, infer_flag, + commits, infers); + + // If the recursive call resulted in an error and would have emitted an error + // message, disable error emission for the current level to avoid duplicate + // errors + if (result->get_kind () == TyTy::TypeKind::ERROR && emit_error) + emit_error = false; + + return result; +} + TyTy::BaseType * UnifyRules::get_base () { @@ -471,11 +487,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) TyTy::BaseType *other_field_ty = other_field->get_field_type (); TyTy::BaseType *unified_ty - = UnifyRules::Resolve (TyTy::TyWithLocation (this_field_ty), - TyTy::TyWithLocation (other_field_ty), - locus, commit_flag, - false /* emit_error */, infer_flag, - commits, infers); + = resolve_subtype (TyTy::TyWithLocation (this_field_ty), + TyTy::TyWithLocation (other_field_ty)); if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -497,11 +510,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) auto pa = a.get_param_ty (); auto pb = b.get_param_ty (); - auto res - = UnifyRules::Resolve (TyTy::TyWithLocation (pa), - TyTy::TyWithLocation (pb), locus, - commit_flag, false /* emit_error */, - infer_flag, commits, infers); + auto res = resolve_subtype (TyTy::TyWithLocation (pa), + TyTy::TyWithLocation (pb)); if (res->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -609,10 +619,8 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) auto other_base_type = type.get_base (); TyTy::BaseType *base_resolved - = UnifyRules::Resolve (TyTy::TyWithLocation (base_type), - TyTy::TyWithLocation (other_base_type), locus, - commit_flag, false /* emit_error */, - infer_flag, commits, infers); + = resolve_subtype (TyTy::TyWithLocation (base_type), + TyTy::TyWithLocation (other_base_type)); if (base_resolved->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -682,10 +690,8 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) auto other_base_type = type.get_base (); TyTy::BaseType *base_resolved - = UnifyRules::Resolve (TyTy::TyWithLocation (base_type), - TyTy::TyWithLocation (other_base_type), locus, - commit_flag, false /* emit_error */, - infer_flag, commits, infers); + = resolve_subtype (TyTy::TyWithLocation (base_type), + TyTy::TyWithLocation (other_base_type)); if (base_resolved->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -815,10 +821,9 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) case TyTy::ARRAY: { TyTy::ArrayType &type = *static_cast (rtype); - TyTy::BaseType *element_unify = UnifyRules::Resolve ( - TyTy::TyWithLocation (ltype->get_element_type ()), - TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag, - false /* emit_error*/, infer_flag, commits, infers); + TyTy::BaseType *element_unify + = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()), + TyTy::TyWithLocation (type.get_element_type ())); if (element_unify->get_kind () != TyTy::TypeKind::ERROR) { @@ -877,10 +882,9 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) case TyTy::SLICE: { TyTy::SliceType &type = *static_cast (rtype); - TyTy::BaseType *element_unify = UnifyRules::Resolve ( - TyTy::TyWithLocation (ltype->get_element_type ()), - TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag, - false /* emit_error*/, infer_flag, commits, infers); + TyTy::BaseType *element_unify + = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()), + TyTy::TyWithLocation (type.get_element_type ())); if (element_unify->get_kind () != TyTy::TypeKind::ERROR) { @@ -948,21 +952,17 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) auto a = ltype->param_at (i).get_type (); auto b = type.param_at (i).get_type (); - auto unified_param - = UnifyRules::Resolve (TyTy::TyWithLocation (a), - TyTy::TyWithLocation (b), locus, - commit_flag, false /* emit_errors */, - infer_flag, commits, infers); + auto unified_param = resolve_subtype (TyTy::TyWithLocation (a), + TyTy::TyWithLocation (b)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); } } - auto unified_return = UnifyRules::Resolve ( - TyTy::TyWithLocation (ltype->get_return_type ()), - TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag, - false /* emit_errors */, infer_flag, commits, infers); + auto unified_return + = resolve_subtype (TyTy::TyWithLocation (ltype->get_return_type ()), + TyTy::TyWithLocation (type.get_return_type ())); if (unified_return->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -1041,21 +1041,17 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) auto a = ltype->get_param_type_at (i); auto b = type.get_param_type_at (i); - auto unified_param - = UnifyRules::Resolve (TyTy::TyWithLocation (a), - TyTy::TyWithLocation (b), locus, - commit_flag, false /* emit_errors */, - infer_flag, commits, infers); + auto unified_param = resolve_subtype (TyTy::TyWithLocation (a), + TyTy::TyWithLocation (b)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); } } - auto unified_return = UnifyRules::Resolve ( - TyTy::TyWithLocation (ltype->get_return_type ()), - TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag, - false /* emit_errors */, infer_flag, commits, infers); + auto unified_return + = resolve_subtype (TyTy::TyWithLocation (ltype->get_return_type ()), + TyTy::TyWithLocation (type.get_return_type ())); if (unified_return->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -1072,10 +1068,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) auto other_ret_type = type.get_return_type (); auto unified_result - = UnifyRules::Resolve (TyTy::TyWithLocation (this_ret_type), - TyTy::TyWithLocation (other_ret_type), locus, - commit_flag, false /*emit_errors*/, infer_flag, - commits, infers); + = resolve_subtype (TyTy::TyWithLocation (this_ret_type), + TyTy::TyWithLocation (other_ret_type)); if (unified_result->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -1092,10 +1086,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) auto other_param = type.param_at (i).get_type (); auto unified_param - = UnifyRules::Resolve (TyTy::TyWithLocation (this_param), - TyTy::TyWithLocation (other_param), locus, - commit_flag, false /* emit_errors */, - infer_flag, commits, infers); + = resolve_subtype (TyTy::TyWithLocation (this_param), + TyTy::TyWithLocation (other_param)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -1163,10 +1155,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) TyTy::BaseType *fo = type.get_field (i); TyTy::BaseType *unified_ty - = UnifyRules::Resolve (TyTy::TyWithLocation (bo), - TyTy::TyWithLocation (fo), locus, - commit_flag, false /* emit_errors */, - infer_flag, commits, infers); + = resolve_subtype (TyTy::TyWithLocation (bo), + TyTy::TyWithLocation (fo)); if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) return new TyTy::ErrorType (0); @@ -1778,19 +1768,17 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) return new TyTy::ErrorType (0); } - TyTy::BaseType *args_res = UnifyRules::Resolve ( - TyTy::TyWithLocation (<ype->get_parameters ()), - TyTy::TyWithLocation (&type.get_parameters ()), locus, commit_flag, - false /* emit_error */, infer_flag, commits, infers); + TyTy::BaseType *args_res + = resolve_subtype (TyTy::TyWithLocation (<ype->get_parameters ()), + TyTy::TyWithLocation (&type.get_parameters ())); if (args_res->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); } - TyTy::BaseType *res = UnifyRules::Resolve ( - TyTy::TyWithLocation (<ype->get_result_type ()), - TyTy::TyWithLocation (&type.get_result_type ()), locus, commit_flag, - false /* emit_error */, infer_flag, commits, infers); + TyTy::BaseType *res + = resolve_subtype (TyTy::TyWithLocation (<ype->get_result_type ()), + TyTy::TyWithLocation (&type.get_result_type ())); if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -1842,10 +1830,8 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) auto lr = ltype->resolve (); auto rr = ro->resolve (); - auto res = UnifyRules::Resolve (TyTy::TyWithLocation (lr), - TyTy::TyWithLocation (rr), locus, - commit_flag, false /* emit_error */, - infer_flag, commits, infers); + auto res = resolve_subtype (TyTy::TyWithLocation (lr), + TyTy::TyWithLocation (rr)); if (res->get_kind () == TyTy::TypeKind::ERROR) return new TyTy::ErrorType (0); } @@ -1863,10 +1849,8 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) else if (ltype->can_resolve ()) { auto underly = ltype->resolve (); - auto res = UnifyRules::Resolve (TyTy::TyWithLocation (underly), - TyTy::TyWithLocation (rtype), locus, - commit_flag, false /* emit_error */, - infer_flag, commits, infers); + auto res = resolve_subtype (TyTy::TyWithLocation (underly), + TyTy::TyWithLocation (rtype)); if (res->get_kind () == TyTy::TypeKind::ERROR) return new TyTy::ErrorType (0); } diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h index 5ff3b7c48dbe..f64f0ed27b82 100644 --- a/gcc/rust/typecheck/rust-unify.h +++ b/gcc/rust/typecheck/rust-unify.h @@ -91,6 +91,9 @@ class UnifyRules std::vector &commits, std::vector &infers); + TyTy::BaseType *resolve_subtype (TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs); + void emit_type_mismatch () const; void emit_abi_mismatch (const TyTy::FnType &expected, const TyTy::FnType &got) const; diff --git a/gcc/testsuite/rust/compile/traits9.rs b/gcc/testsuite/rust/compile/traits9.rs index bb3034d0f21c..f4308e8ccc17 100644 --- a/gcc/testsuite/rust/compile/traits9.rs +++ b/gcc/testsuite/rust/compile/traits9.rs @@ -11,6 +11,5 @@ fn main() { a = Foo(123); let b: &dyn Bar = &a; - // { dg-error "bounds not satisfied for Foo .Bar. is not satisfied" "" { target *-*-* } .-1 } - // { dg-error "expected" "" { target *-*-* } .-2 } + // { dg-error "bounds not satisfied for Foo .Bar. is not satisfied .E0277." "" { target *-*-* } .-1 } } diff --git a/gcc/testsuite/rust/compile/unify-errors1.rs b/gcc/testsuite/rust/compile/unify-errors1.rs new file mode 100644 index 000000000000..0fe95efd0d7f --- /dev/null +++ b/gcc/testsuite/rust/compile/unify-errors1.rs @@ -0,0 +1,49 @@ +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +trait MyTrait {} + +struct Wrapper { + value: T, +} + +struct NotImpl; + +trait A {} +trait B {} + +struct Wrapper2 { + value: T, +} + +struct NotImpl2; + +impl A for NotImpl2 {} + +fn takes_tuple(x: (i32, bool)) {} + +fn requires_copy(value: T) {} + +pub fn test() { + takes_tuple((1, 2)); + // { dg-error "mismatched types, expected .bool. but got .. .E0308." "" { target *-*-* } .-1 } + + takes_tuple((1, 2, 3)); + // { dg-error "mismatched types, expected ..i32, bool.. but got .., , .. .E0308." "" { target *-*-* } .-1 } + + takes_tuple("hello"); + // { dg-error "mismatched types, expected ..i32, bool.. but got .& str. .E0308." "" { target *-*-* } .-1 } + + let x = &mut 5; + requires_copy(x); + // { dg-error "bounds not satisfied for &mut .Copy. is not satisfied .E0277." "" { target *-*-* } .-1 } + + let _x = Wrapper { value: NotImpl }; + // { dg-error "bounds not satisfied for NotImpl .MyTrait. is not satisfied .E0277." "" { target *-*-* } .-1 } + + let _x = Wrapper2 { value: NotImpl2 }; + // { dg-error "bounds not satisfied for NotImpl2 .B. is not satisfied .E0277." "" { target *-*-* } .-1 } +} From 4ebafbaccaf365a675af4c140fb1132ecf2c52fb Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 9 Apr 2025 18:18:30 +0200 Subject: [PATCH 037/161] ast: Add ConstBlock and AnonConst nodes gcc/rust/ChangeLog: * ast/rust-expr.h: Declare AnonConst and ConstBlock and use them. * ast/rust-ast-full-decls.h: Likewise. * ast/rust-ast.cc: Add implementation for AnonConst and ConstBlock. * ast/rust-ast.h: Likewise. * ast/rust-ast-collector.cc (TokenCollector::visit): Likewise. * ast/rust-ast-collector.h: Likewise. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. * ast/rust-ast-visitor.h: Likewise. * expand/rust-derive.h: Likewise. * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise. * hir/rust-ast-lower-base.h: Likewise. * hir/rust-ast-lower-expr.cc (translate_operand_const): Likewise. * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise. * resolve/rust-ast-resolve-base.h: Likewise. * resolve/rust-ast-resolve-expr.h: Likewise. * resolve/rust-ast-resolve-expr.cc: Likewise. --- gcc/rust/ast/rust-ast-collector.cc | 18 ++- gcc/rust/ast/rust-ast-collector.h | 2 + gcc/rust/ast/rust-ast-full-decls.h | 4 +- gcc/rust/ast/rust-ast-visitor.cc | 14 +- gcc/rust/ast/rust-ast-visitor.h | 4 + gcc/rust/ast/rust-ast.cc | 24 ++++ gcc/rust/ast/rust-ast.h | 2 + gcc/rust/ast/rust-expr.h | 151 +++++++++++++++++++--- gcc/rust/expand/rust-derive.h | 2 + gcc/rust/hir/rust-ast-lower-base.cc | 6 + gcc/rust/hir/rust-ast-lower-base.h | 2 + gcc/rust/hir/rust-ast-lower-expr.cc | 8 +- gcc/rust/resolve/rust-ast-resolve-base.cc | 8 ++ gcc/rust/resolve/rust-ast-resolve-base.h | 3 + gcc/rust/resolve/rust-ast-resolve-expr.cc | 15 ++- gcc/rust/resolve/rust-ast-resolve-expr.h | 2 + 16 files changed, 237 insertions(+), 28 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index cab763964154..d6b6a495d110 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -1269,6 +1269,22 @@ TokenCollector::visit (BlockExpr &expr) newline (); } +void +TokenCollector::visit (AnonConst &expr) +{ + visit (expr.get_inner_expr ()); +} + +void +TokenCollector::visit (ConstBlock &expr) +{ + push (Rust::Token::make (CONST, expr.get_locus ())); + + // The inner expression is already a block expr, so we don't need to add + // curlies + visit (expr.get_const_expr ()); +} + void TokenCollector::visit (ClosureExprInnerTyped &expr) { @@ -1564,7 +1580,7 @@ TokenCollector::visit (InlineAsm &expr) } case RegisterType::Const: { - visit (operand.get_const ().anon_const.expr); + visit (operand.get_const ().anon_const.get_inner_expr ()); break; } case RegisterType::Sym: diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index f45e3cc51aee..cec2365892ec 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -277,6 +277,8 @@ class TokenCollector : public ASTVisitor void visit (ClosureParam ¶m); void visit (ClosureExprInner &expr); void visit (BlockExpr &expr); + void visit (AnonConst &expr); + void visit (ConstBlock &expr); void visit (ClosureExprInnerTyped &expr); void visit (ContinueExpr &expr); void visit (BreakExpr &expr); diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 1d5853d0deb5..b410f3ad006e 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -115,6 +115,8 @@ struct ClosureParam; class ClosureExpr; class ClosureExprInner; class BlockExpr; +class AnonConst; +class ConstBlock; class ClosureExprInnerTyped; class ContinueExpr; class BreakExpr; @@ -145,7 +147,7 @@ struct MatchCase; class MatchExpr; class AwaitExpr; class AsyncBlockExpr; -struct AnonConst; +enum class InlineAsmOption; struct InlineAsmRegOrRegClass; class InlineAsmOperand; struct InlineAsmPlaceHolder; diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index d197db66cf49..bd1b65aaec91 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -455,6 +455,18 @@ DefaultASTVisitor::visit (AST::BlockExpr &expr) visit (expr.get_tail_expr ()); } +void +DefaultASTVisitor::visit (AST::ConstBlock &expr) +{ + visit (expr.get_const_expr ()); +} + +void +DefaultASTVisitor::visit (AST::AnonConst &expr) +{ + visit (expr.get_inner_expr ()); +} + void DefaultASTVisitor::visit (AST::ClosureExprInnerTyped &expr) { @@ -704,7 +716,7 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr) } case RegisterType::Const: { - visit (operand.get_const ().anon_const.expr); + visit (operand.get_const ().anon_const.get_inner_expr ()); break; } case RegisterType::Sym: diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index b1fc50465a1a..22fd98b6ea8c 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -104,6 +104,8 @@ class ASTVisitor virtual void visit (FieldAccessExpr &expr) = 0; virtual void visit (ClosureExprInner &expr) = 0; virtual void visit (BlockExpr &expr) = 0; + virtual void visit (AnonConst &expr) = 0; + virtual void visit (ConstBlock &expr) = 0; virtual void visit (ClosureExprInnerTyped &expr) = 0; virtual void visit (ContinueExpr &expr) = 0; virtual void visit (BreakExpr &expr) = 0; @@ -293,6 +295,8 @@ class DefaultASTVisitor : public ASTVisitor virtual void visit (AST::FieldAccessExpr &expr) override; virtual void visit (AST::ClosureExprInner &expr) override; virtual void visit (AST::BlockExpr &expr) override; + virtual void visit (AST::AnonConst &expr) override; + virtual void visit (AST::ConstBlock &expr) override; virtual void visit (AST::ClosureExprInnerTyped &expr) override; virtual void visit (AST::ContinueExpr &expr) override; virtual void visit (AST::BreakExpr &expr) override; diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 86e700091f36..fdd86679ba74 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -1277,6 +1277,18 @@ BlockExpr::as_string () const return str; } +std::string +AnonConst::as_string () const +{ + return "AnonConst: " + expr->as_string (); +} + +std::string +ConstBlock::as_string () const +{ + return "ConstBlock: " + expr.as_string (); +} + std::string TraitImpl::as_string () const { @@ -4520,6 +4532,18 @@ BlockExpr::accept_vis (ASTVisitor &vis) vis.visit (*this); } +void +AnonConst::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstBlock::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + void ClosureExprInnerTyped::accept_vis (ASTVisitor &vis) { diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index fa8616e8db6c..90d2104eb85b 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1255,6 +1255,8 @@ class Expr : public Visitable FieldAccess, Closure, Block, + ConstExpr, + ConstBlock, Continue, Break, Range, diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 9ecca2251031..ba20bfaa6014 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1214,6 +1214,8 @@ class ArrayElemsValues : public ArrayElems class ArrayElemsCopied : public ArrayElems { std::unique_ptr elem_to_copy; + + // TODO: This should be replaced by a ConstExpr std::unique_ptr num_copies; location_t locus; @@ -2744,6 +2746,124 @@ class BlockExpr : public ExprWithBlock } }; +class AnonConst : public ExprWithBlock +{ +public: + AnonConst (std::unique_ptr &&expr, location_t locus = UNKNOWN_LOCATION) + : ExprWithBlock (), locus (locus), expr (std::move (expr)) + { + rust_assert (this->expr); + } + + AnonConst (const AnonConst &other) + { + node_id = other.node_id; + locus = other.locus; + expr = other.expr->clone_expr (); + } + + AnonConst operator= (const AnonConst &other) + { + node_id = other.node_id; + locus = other.locus; + expr = other.expr->clone_expr (); + + return *this; + } + + std::string as_string () const override; + + Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstExpr; } + + location_t get_locus () const override { return locus; } + Expr &get_inner_expr () { return *expr; } + NodeId get_node_id () const override { return node_id; } + + /* FIXME: AnonConst are always "internal" and should not have outer attributes + * - is that true? Or should we instead call + * expr->get_outer_attrs()/expr->set_outer_attrs() */ + + std::vector &get_outer_attrs () override + { + static auto attrs = std::vector (); + return attrs; + } + + void set_outer_attrs (std::vector) override {} + + /* FIXME: Likewise for mark_for_strip() ? */ + void mark_for_strip () override {} + bool is_marked_for_strip () const override { return false; } + + void accept_vis (ASTVisitor &vis) override; + +private: + location_t locus; + std::unique_ptr expr; + + AnonConst *clone_expr_with_block_impl () const override + { + return new AnonConst (*this); + } +}; + +class ConstBlock : public ExprWithBlock +{ +public: + ConstBlock (AnonConst &&expr, location_t locus = UNKNOWN_LOCATION, + std::vector &&outer_attrs = {}) + : ExprWithBlock (), expr (std::move (expr)), + outer_attrs (std::move (outer_attrs)), locus (locus) + {} + + ConstBlock (const ConstBlock &other) + : ExprWithBlock (other), expr (other.expr), outer_attrs (other.outer_attrs), + locus (other.locus) + {} + + ConstBlock operator= (const ConstBlock &other) + { + expr = other.expr; + node_id = other.node_id; + outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + std::string as_string () const override; + + Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstBlock; } + + AnonConst &get_const_expr () { return expr; } + + void accept_vis (ASTVisitor &vis) override; + + std::vector &get_outer_attrs () override { return outer_attrs; } + + void set_outer_attrs (std::vector new_attrs) override + { + outer_attrs = std::move (new_attrs); + } + + location_t get_locus () const override { return locus; } + + bool is_marked_for_strip () const override { return marked_for_strip; } + void mark_for_strip () override { marked_for_strip = true; } + +private: + AnonConst expr; + + std::vector outer_attrs; + location_t locus; + bool marked_for_strip = false; + + ConstBlock *clone_expr_with_block_impl () const override + { + return new ConstBlock (*this); + } +}; + // Represents a type-specified closure expression AST node class ClosureExprInnerTyped : public ClosureExpr { @@ -4822,27 +4942,18 @@ class AsyncBlockExpr : public ExprWithBlock } }; -struct AnonConst +// Inline-assembly specific options +enum class InlineAsmOption { - NodeId id; - std::unique_ptr expr; - AnonConst (NodeId id, std::unique_ptr expr) - : id (id), expr (std::move (expr)) - { - rust_assert (this->expr != nullptr); - } - AnonConst (const AnonConst &other) - { - id = other.id; - expr = other.expr->clone_expr (); - } - - AnonConst operator= (const AnonConst &other) - { - id = other.id; - expr = other.expr->clone_expr (); - return *this; - } + PURE = 1 << 0, + NOMEM = 1 << 1, + READONLY = 1 << 2, + PRESERVES_FLAGS = 1 << 3, + NORETURN = 1 << 4, + NOSTACK = 1 << 5, + ATT_SYNTAX = 1 << 6, + RAW = 1 << 7, + MAY_UNWIND = 1 << 8, }; struct InlineAsmRegOrRegClass diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index 5fca49ca1f32..ff4f427695ad 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -147,6 +147,8 @@ class DeriveVisitor : public AST::ASTVisitor virtual void visit (FieldAccessExpr &expr) override final{}; virtual void visit (ClosureExprInner &expr) override final{}; virtual void visit (BlockExpr &expr) override final{}; + virtual void visit (AnonConst &expr) override final{}; + virtual void visit (ConstBlock &expr) override final{}; virtual void visit (ClosureExprInnerTyped &expr) override final{}; virtual void visit (ContinueExpr &expr) override final{}; virtual void visit (BreakExpr &expr) override final{}; diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index b7d3224f2c22..5b35052b6656 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -201,6 +201,12 @@ void ASTLoweringBase::visit (AST::BlockExpr &) {} void +ASTLoweringBase::visit (AST::AnonConst &) +{} +void +ASTLoweringBase::visit (AST::ConstBlock &) +{} +void ASTLoweringBase::visit (AST::ClosureExprInnerTyped &) {} void diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index 31161810c6fd..51912be66b4f 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -131,6 +131,8 @@ class ASTLoweringBase : public AST::ASTVisitor virtual void visit (AST::FieldAccessExpr &expr) override; virtual void visit (AST::ClosureExprInner &expr) override; virtual void visit (AST::BlockExpr &expr) override; + virtual void visit (AST::AnonConst &expr) override; + virtual void visit (AST::ConstBlock &expr) override; virtual void visit (AST::ClosureExprInnerTyped &expr) override; virtual void visit (AST::ContinueExpr &expr) override; virtual void visit (AST::BreakExpr &expr) override; diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc index 07d0c835e567..5f562e6ffd71 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.cc +++ b/gcc/rust/hir/rust-ast-lower-expr.cc @@ -867,10 +867,10 @@ HIR::InlineAsmOperand translate_operand_const (const AST::InlineAsmOperand &operand) { auto const_value = operand.get_const (); - struct HIR::AnonConst anon_const (const_value.anon_const.id, - std::unique_ptr ( - ASTLoweringExpr::translate ( - *const_value.anon_const.expr.get ()))); + struct HIR::AnonConst anon_const ( + const_value.anon_const.get_node_id (), + std::unique_ptr ( + ASTLoweringExpr::translate (const_value.anon_const.get_inner_expr ()))); struct HIR::InlineAsmOperand::Const cnst { anon_const diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc index b781ce33f3f4..71c4c4834db2 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ b/gcc/rust/resolve/rust-ast-resolve-base.cc @@ -231,6 +231,14 @@ void ResolverBase::visit (AST::BlockExpr &) {} +void +ResolverBase::visit (AST::AnonConst &) +{} + +void +ResolverBase::visit (AST::ConstBlock &) +{} + void ResolverBase::visit (AST::ClosureExprInnerTyped &) {} diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index 5bb9e4f18226..e17bdcb5eaad 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -21,6 +21,7 @@ #include "rust-ast-visitor.h" #include "rust-ast.h" +#include "rust-expr.h" #include "rust-name-resolver.h" #include "rust-diagnostics.h" #include "rust-location.h" @@ -85,6 +86,8 @@ class ResolverBase : public AST::ASTVisitor void visit (AST::FieldAccessExpr &); void visit (AST::ClosureExprInner &); void visit (AST::BlockExpr &); + void visit (AST::AnonConst &); + void visit (AST::ConstBlock &); void visit (AST::ClosureExprInnerTyped &); void visit (AST::ContinueExpr &); void visit (AST::BreakExpr &); diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc index 8580f4b1575c..8482123e891c 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc @@ -314,6 +314,18 @@ ResolveExpr::visit (AST::BlockExpr &expr) resolver->get_label_scope ().pop (); } +void +ResolveExpr::visit (AST::AnonConst &expr) +{ + ResolveExpr::go (expr.get_inner_expr (), prefix, canonical_prefix); +} + +void +ResolveExpr::visit (AST::ConstBlock &expr) +{ + ResolveExpr::go (expr.get_const_expr (), prefix, canonical_prefix); +} + void translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix, const CanonicalPath &canonical_prefix) @@ -352,7 +364,8 @@ translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix, case RegisterType::Const: { auto anon_const = operand.get_const ().anon_const; - ResolveExpr::go (*anon_const.expr, prefix, canonical_prefix); + ResolveExpr::go (anon_const.get_inner_expr (), prefix, + canonical_prefix); break; } case RegisterType::Sym: diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index b296d669cb7c..aad160504174 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -56,6 +56,8 @@ class ResolveExpr : public ResolverBase void visit (AST::IfLetExpr &expr) override; void visit (AST::IfLetExprConseqElse &expr) override; void visit (AST::BlockExpr &expr) override; + void visit (AST::AnonConst &expr) override; + void visit (AST::ConstBlock &expr) override; void visit (AST::InlineAsm &expr) override; void visit (AST::LlvmInlineAsm &expr) override; void visit (AST::UnsafeBlockExpr &expr) override; From e4e6cc055495fc89c39d710c34f0fb55ddece623 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 15 Apr 2025 17:33:11 +0200 Subject: [PATCH 038/161] parser: Add base for parsing const blocks gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_const_block_expr): New function. * parse/rust-parse.h: Declare it. --- gcc/rust/parse/rust-parse-impl.h | 27 +++++++++++++++++++++++++++ gcc/rust/parse/rust-parse.h | 5 +++++ 2 files changed, 32 insertions(+) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 7a4d47658f12..9c9208f9ba49 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -7264,6 +7264,30 @@ Parser::parse_block_expr ( std::move (label), locus, end_locus)); } +/* Parse a "const block", a block preceded by the `const` keyword whose + * statements can be const evaluated and used in constant contexts */ +template +std::unique_ptr +Parser::parse_const_block_expr (AST::AttrVec outer_attrs, + location_t locus) +{ + auto block = parse_block_expr (); + + if (!block) + { + add_error (Error (locus, "failed to parse inner block in const block")); + skip_after_end_block (); + + return nullptr; + } + + auto block_locus = block->get_locus (); + + return std::make_unique (AST::AnonConst (std::move (block), + block_locus), + locus, std::move (outer_attrs)); +} + /* Parses a "grouped" expression (expression in parentheses), used to control * precedence. */ template @@ -12537,6 +12561,9 @@ Parser::null_denotation_not_path ( "use of %qs is not allowed on the right-side of an assignment", tok->get_token_description ())); return nullptr; + case CONST: + return parse_const_block_expr (std::move (outer_attrs), + tok->get_locus ()); default: if (!restrictions.expr_can_be_null) add_error (Error (tok->get_locus (), diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index c8ee5f109b0c..4fab60ffb080 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -17,6 +17,7 @@ along with GCC; see the file COPYING3. If not see #ifndef RUST_PARSE_H #define RUST_PARSE_H +#include "rust-ast.h" #include "rust-item.h" #include "rust-lex.h" #include "rust-ast-full.h" @@ -165,6 +166,10 @@ template class Parser tl::optional = tl::nullopt, location_t pratt_parsed_loc = UNKNOWN_LOCATION); + std::unique_ptr + parse_const_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + location_t loc = UNKNOWN_LOCATION); + bool is_macro_rules_def (const_TokenPtr t); std::unique_ptr parse_item (bool called_from_statement); std::unique_ptr parse_pattern (); From a537f01e27b50f727c35b6c75fa6cbaf76811b03 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 15 Apr 2025 13:34:38 +0200 Subject: [PATCH 039/161] hir: Add const blocks gcc/rust/ChangeLog: * hir/tree/rust-hir-expr.h: New classes. * hir/tree/rust-hir-full-decls.h: Likewise. * hir/tree/rust-hir.cc: Handle AnonConst and ConstBlock. * backend/rust-compile-block.cc: Likewise. * backend/rust-compile-block.h: Likewise. * backend/rust-compile-expr.cc (CompileExpr::visit): Likewise. * backend/rust-compile-expr.h: Likewise. * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Likewise. * checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Likewise. * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Likewise. * checks/errors/borrowck/rust-bir-builder-struct.h: Likewise. * checks/errors/borrowck/rust-function-collector.h: Likewise. * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::visit): Likewise. * checks/errors/privacy/rust-privacy-reporter.h: Likewise. * checks/errors/rust-const-checker.cc (ConstChecker::visit): Likewise. * checks/errors/rust-const-checker.h: Likewise. * checks/errors/rust-hir-pattern-analysis.cc (PatternChecker::visit): Likewise. * checks/errors/rust-hir-pattern-analysis.h: Likewise. * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): Likewise. * checks/errors/rust-unsafe-checker.h: Likewise. * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise. (translate_operand_out): Likewise. (translate_operand_inout): Likewise. (translate_operand_const): Likewise. * hir/rust-ast-lower-expr.h: Likewise. * hir/rust-hir-dump.cc (Dump::visit): Likewise. * hir/rust-hir-dump.h: Likewise. * hir/tree/rust-hir-expr-abstract.h: Likewise. * hir/tree/rust-hir-expr.cc (AnonConst::AnonConst): Likewise. (AnonConst::operator=): Likewise. (ConstBlock::ConstBlock): Likewise. (ConstBlock::operator=): Likewise. * hir/tree/rust-hir-visitor.h: * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise. (typecheck_inline_asm_operand): Likewise. * typecheck/rust-hir-type-check-expr.h: Likewise. --- gcc/rust/backend/rust-compile-block.cc | 1 + gcc/rust/backend/rust-compile-block.h | 9 +++ gcc/rust/backend/rust-compile-expr.cc | 13 +++ gcc/rust/backend/rust-compile-expr.h | 2 + .../borrowck/rust-bir-builder-expr-stmt.cc | 12 +++ .../borrowck/rust-bir-builder-expr-stmt.h | 2 + .../borrowck/rust-bir-builder-lazyboolexpr.h | 8 ++ .../errors/borrowck/rust-bir-builder-struct.h | 2 + .../errors/borrowck/rust-function-collector.h | 2 + .../errors/privacy/rust-privacy-reporter.cc | 12 +++ .../errors/privacy/rust-privacy-reporter.h | 2 + gcc/rust/checks/errors/rust-const-checker.cc | 20 +++++ gcc/rust/checks/errors/rust-const-checker.h | 2 + .../errors/rust-hir-pattern-analysis.cc | 12 +++ .../checks/errors/rust-hir-pattern-analysis.h | 2 + gcc/rust/checks/errors/rust-unsafe-checker.cc | 12 +++ gcc/rust/checks/errors/rust-unsafe-checker.h | 2 + gcc/rust/hir/rust-ast-lower-expr.cc | 60 +++++++++++--- gcc/rust/hir/rust-ast-lower-expr.h | 2 + gcc/rust/hir/rust-hir-dump.cc | 22 ++++++ gcc/rust/hir/rust-hir-dump.h | 2 + gcc/rust/hir/tree/rust-hir-expr-abstract.h | 4 +- gcc/rust/hir/tree/rust-hir-expr.cc | 64 ++++++++++----- gcc/rust/hir/tree/rust-hir-expr.h | 79 ++++++++++++++++--- gcc/rust/hir/tree/rust-hir-full-decls.h | 3 +- gcc/rust/hir/tree/rust-hir-visitor.h | 6 ++ gcc/rust/hir/tree/rust-hir.cc | 51 ++++++++++++ .../typecheck/rust-hir-type-check-expr.cc | 14 +++- gcc/rust/typecheck/rust-hir-type-check-expr.h | 2 + 29 files changed, 380 insertions(+), 44 deletions(-) diff --git a/gcc/rust/backend/rust-compile-block.cc b/gcc/rust/backend/rust-compile-block.cc index f844a27e9890..03c36d21709f 100644 --- a/gcc/rust/backend/rust-compile-block.cc +++ b/gcc/rust/backend/rust-compile-block.cc @@ -19,6 +19,7 @@ #include "rust-compile-block.h" #include "rust-compile-stmt.h" #include "rust-compile-expr.h" +#include "rust-hir-expr.h" namespace Rust { namespace Compile { diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h index 3f38d087859f..90515f648831 100644 --- a/gcc/rust/backend/rust-compile-block.h +++ b/gcc/rust/backend/rust-compile-block.h @@ -83,6 +83,8 @@ class CompileConditionalBlocks : public HIRCompileBase, void visit (HIR::MethodCallExpr &) override {} void visit (HIR::FieldAccessExpr &) override {} void visit (HIR::BlockExpr &) override {} + void visit (HIR::AnonConst &) override {} + void visit (HIR::ConstBlock &) override {} void visit (HIR::ContinueExpr &) override {} void visit (HIR::BreakExpr &) override {} void visit (HIR::RangeFromToExpr &) override {} @@ -138,6 +140,12 @@ class CompileExprWithBlock : public HIRCompileBase, translated = CompileBlock::compile (expr, ctx, result); } + void visit (HIR::ConstBlock &expr) override + { + rust_unreachable (); + // translated = CompileExpr::compile (expr, ctx, result); + } + // Empty visit for unused Expression HIR nodes. void visit (HIR::PathInExpression &) override {} void visit (HIR::QualifiedPathInExpression &) override {} @@ -184,6 +192,7 @@ class CompileExprWithBlock : public HIRCompileBase, void visit (HIR::AsyncBlockExpr &) override {} void visit (HIR::InlineAsm &) override {} void visit (HIR::LlvmInlineAsm &) override {} + void visit (HIR::AnonConst &) override {} private: CompileExprWithBlock (Context *ctx, Bvariable *result) diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index cace059f7426..d8ddab5bd9aa 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -30,6 +30,7 @@ #include "realmpfr.h" #include "convert.h" #include "print-tree.h" +#include "rust-hir-expr.h" #include "rust-system.h" #include "rust-tyty.h" @@ -440,6 +441,18 @@ CompileExpr::visit (HIR::BlockExpr &expr) translated = Backend::var_expression (tmp, expr.get_locus ()); } +void +CompileExpr::visit (HIR::AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +CompileExpr::visit (HIR::ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + void CompileExpr::visit (HIR::UnsafeBlockExpr &expr) { diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 65ed4b39e2dd..bc347bf5066f 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -48,6 +48,8 @@ class CompileExpr : private HIRCompileBase, protected HIR::HIRExpressionVisitor void visit (HIR::IfExpr &expr) override; void visit (HIR::IfExprConseqElse &expr) override; void visit (HIR::BlockExpr &expr) override; + void visit (HIR::AnonConst &expr) override; + void visit (HIR::ConstBlock &expr) override; void visit (HIR::UnsafeBlockExpr &expr) override; void visit (HIR::StructExprStruct &struct_expr) override; void visit (HIR::StructExprStructFields &struct_expr) override; diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc index c59aba40d1cf..0799a4ea84c1 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc @@ -416,6 +416,18 @@ ExprStmtBuilder::visit (HIR::BlockExpr &block) ctx.place_db.pop_scope (); } +void +ExprStmtBuilder::visit (HIR::AnonConst &block) +{ + rust_unreachable (); +} + +void +ExprStmtBuilder::visit (HIR::ConstBlock &block) +{ + rust_unreachable (); +} + void ExprStmtBuilder::visit (HIR::ContinueExpr &cont) { diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h index 5cab3c495fd1..45d3d584825b 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h @@ -84,6 +84,8 @@ class ExprStmtBuilder final : public AbstractExprBuilder, void visit (HIR::MethodCallExpr &expr) override; void visit (HIR::FieldAccessExpr &expr) override; void visit (HIR::BlockExpr &block) override; + void visit (HIR::AnonConst &block) override; + void visit (HIR::ConstBlock &block) override; void visit (HIR::ContinueExpr &cont) override; void visit (HIR::BreakExpr &brk) override; void visit (HIR::RangeFromToExpr &range) override; diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h index b7a1555b392b..a5ec56907438 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h @@ -169,6 +169,14 @@ class LazyBooleanExprBuilder : public AbstractExprBuilder { return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ()); } + void visit (HIR::AnonConst &expr) override + { + return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ()); + } + void visit (HIR::ConstBlock &expr) override + { + return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ()); + } void visit (HIR::UnsafeBlockExpr &expr) override { return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ()); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h index 84311cc7a2a7..2e11f635110f 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h @@ -133,6 +133,8 @@ class StructBuilder : public AbstractBuilder, public HIR::HIRFullVisitor void visit (HIR::MethodCallExpr &expr) override { rust_unreachable (); } void visit (HIR::FieldAccessExpr &expr) override { rust_unreachable (); } void visit (HIR::BlockExpr &expr) override { rust_unreachable (); } + void visit (HIR::AnonConst &expr) override { rust_unreachable (); } + void visit (HIR::ConstBlock &expr) override { rust_unreachable (); } void visit (HIR::ClosureExpr &expr) override { rust_unreachable (); } void visit (HIR::ContinueExpr &expr) override { rust_unreachable (); } void visit (HIR::BreakExpr &expr) override { rust_unreachable (); } diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h b/gcc/rust/checks/errors/borrowck/rust-function-collector.h index 7cf095240072..860915e09202 100644 --- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h +++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h @@ -104,6 +104,8 @@ class FunctionCollector : public HIR::HIRFullVisitor void visit (HIR::MethodCallExpr &expr) override {} void visit (HIR::FieldAccessExpr &expr) override {} void visit (HIR::BlockExpr &expr) override {} + void visit (HIR::AnonConst &expr) override {} + void visit (HIR::ConstBlock &expr) override {} void visit (HIR::ContinueExpr &expr) override {} void visit (HIR::BreakExpr &expr) override {} void visit (HIR::RangeFromToExpr &expr) override {} diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc index e1d4b167d3d8..e8a679214d48 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc @@ -522,6 +522,18 @@ PrivacyReporter::visit (HIR::BlockExpr &expr) expr.get_final_expr ().accept_vis (*this); } +void +PrivacyReporter::visit (HIR::AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +PrivacyReporter::visit (HIR::ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + void PrivacyReporter::visit (HIR::ContinueExpr &) {} diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h index 7df2cf488b65..07eebf65df02 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h @@ -106,6 +106,8 @@ types virtual void visit (HIR::MethodCallExpr &expr); virtual void visit (HIR::FieldAccessExpr &expr); virtual void visit (HIR::BlockExpr &expr); + virtual void visit (HIR::AnonConst &expr); + virtual void visit (HIR::ConstBlock &expr); virtual void visit (HIR::ContinueExpr &expr); virtual void visit (HIR::BreakExpr &expr); virtual void visit (HIR::RangeFromToExpr &expr); diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc index 3716ea53174f..5cbab3d554ca 100644 --- a/gcc/rust/checks/errors/rust-const-checker.cc +++ b/gcc/rust/checks/errors/rust-const-checker.cc @@ -416,6 +416,26 @@ ConstChecker::visit (BlockExpr &expr) expr.get_final_expr ().accept_vis (*this); } +void +ConstChecker::visit (AnonConst &expr) +{ + const_context.enter (expr.get_mappings ().get_hirid ()); + + expr.get_inner_expr ().accept_vis (*this); + + const_context.exit (); +} + +void +ConstChecker::visit (ConstBlock &expr) +{ + const_context.enter (expr.get_mappings ().get_hirid ()); + + expr.get_const_expr ().accept_vis (*this); + + const_context.exit (); +} + void ConstChecker::visit (ContinueExpr &) {} diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h index b954330df4ca..22398747e585 100644 --- a/gcc/rust/checks/errors/rust-const-checker.h +++ b/gcc/rust/checks/errors/rust-const-checker.h @@ -113,6 +113,8 @@ class ConstChecker : public HIRFullVisitor virtual void visit (FieldAccessExpr &expr) override; virtual void visit (ClosureExpr &expr) override; virtual void visit (BlockExpr &expr) override; + virtual void visit (AnonConst &expr) override; + virtual void visit (ConstBlock &expr) override; virtual void visit (ContinueExpr &expr) override; virtual void visit (BreakExpr &expr) override; virtual void visit (RangeFromToExpr &expr) override; diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc index 6db769f2f63a..ec22a0ee92eb 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc @@ -294,6 +294,18 @@ PatternChecker::visit (BlockExpr &expr) expr.get_final_expr ().accept_vis (*this); } +void +PatternChecker::visit (AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +PatternChecker::visit (ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + void PatternChecker::visit (ContinueExpr &) {} diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h index 62107e1d27f5..5766180ec799 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h @@ -86,6 +86,8 @@ class PatternChecker : public HIR::HIRFullVisitor virtual void visit (MethodCallExpr &expr) override; virtual void visit (FieldAccessExpr &expr) override; virtual void visit (BlockExpr &expr) override; + virtual void visit (AnonConst &expr) override; + virtual void visit (ConstBlock &expr) override; virtual void visit (ClosureExpr &expr) override; virtual void visit (ContinueExpr &expr) override; virtual void visit (BreakExpr &expr) override; diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc index 46eef115877e..d90088faf74e 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.cc +++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc @@ -539,6 +539,18 @@ UnsafeChecker::visit (BlockExpr &expr) expr.get_final_expr ().accept_vis (*this); } +void +UnsafeChecker::visit (AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +UnsafeChecker::visit (ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + void UnsafeChecker::visit (ContinueExpr &) {} diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h index 9a8fb7cdb0a7..8a9830f7cd6e 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.h +++ b/gcc/rust/checks/errors/rust-unsafe-checker.h @@ -95,6 +95,8 @@ class UnsafeChecker : public HIRFullVisitor virtual void visit (FieldAccessExpr &expr) override; virtual void visit (ClosureExpr &expr) override; virtual void visit (BlockExpr &expr) override; + virtual void visit (AnonConst &expr) override; + virtual void visit (ConstBlock &expr) override; virtual void visit (ContinueExpr &expr) override; virtual void visit (BreakExpr &expr) override; virtual void visit (RangeFromToExpr &expr) override; diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc index 5f562e6ffd71..16e80a0841aa 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.cc +++ b/gcc/rust/hir/rust-ast-lower-expr.cc @@ -25,6 +25,7 @@ #include "rust-ast-lower-type.h" #include "rust-ast.h" #include "rust-diagnostics.h" +#include "rust-hir-map.h" #include "rust-system.h" #include "tree/rust-hir-expr.h" @@ -126,6 +127,43 @@ ASTLoweringExpr::visit (AST::BlockExpr &expr) translated = ASTLoweringBlock::translate (expr, &terminated); } +void +ASTLoweringExpr::visit (AST::AnonConst &expr) +{ + auto inner_expr = ASTLoweringExpr::translate (expr.get_inner_expr ()); + + auto &mappings = Analysis::Mappings::get (); + auto crate_num = mappings.get_current_crate (); + auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (), + mappings.get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::AnonConst (std::move (mapping), + std::unique_ptr (inner_expr), + expr.get_locus ()); +} + +void +ASTLoweringExpr::visit (AST::ConstBlock &expr) +{ + auto inner_expr = ASTLoweringExpr::translate (expr.get_const_expr ()); + + // we know this will always be an `AnonConst`, or we have an issue. Let's + // assert just to be sure. + rust_assert (inner_expr->get_expression_type () == Expr::ExprType::AnonConst); + auto anon_const = static_cast (inner_expr); + + auto &mappings = Analysis::Mappings::get (); + auto crate_num = mappings.get_current_crate (); + auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (), + mappings.get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::ConstBlock (std::move (mapping), std::move (*anon_const), + expr.get_locus (), expr.get_outer_attrs ()); +} + void ASTLoweringExpr::visit (AST::UnsafeBlockExpr &expr) { @@ -841,6 +879,7 @@ translate_operand_out (const AST::InlineAsmOperand &operand) *out_value.expr.get ()))); return out; } + HIR::InlineAsmOperand translate_operand_inout (const AST::InlineAsmOperand &operand) { @@ -851,6 +890,7 @@ translate_operand_inout (const AST::InlineAsmOperand &operand) *inout_value.expr.get ()))); return inout; } + HIR::InlineAsmOperand translate_operand_split_in_out (const AST::InlineAsmOperand &operand) { @@ -863,19 +903,21 @@ translate_operand_split_in_out (const AST::InlineAsmOperand &operand) ASTLoweringExpr::translate (*split_in_out_value.out_expr.get ()))); return split_in_out; } + HIR::InlineAsmOperand translate_operand_const (const AST::InlineAsmOperand &operand) { auto const_value = operand.get_const (); - struct HIR::AnonConst anon_const ( - const_value.anon_const.get_node_id (), - std::unique_ptr ( - ASTLoweringExpr::translate (const_value.anon_const.get_inner_expr ()))); - struct HIR::InlineAsmOperand::Const cnst - { - anon_const - }; - return cnst; + + auto inner_expr = ASTLoweringExpr::translate (const_value.anon_const); + + // Like `ConstBlock`, we know this should only be an `AnonConst` - let's + // assert to make sure and static cast + rust_assert (inner_expr->get_expression_type () == Expr::ExprType::AnonConst); + + auto anon_const = static_cast (inner_expr); + + return HIR::InlineAsmOperand::Const{*anon_const}; } HIR::InlineAsmOperand diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index adedeb3cfcba..9d1bf68e8762 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -82,6 +82,8 @@ class ASTLoweringExpr : public ASTLoweringBase void visit (AST::IfLetExpr &expr) override; void visit (AST::IfLetExprConseqElse &expr) override; void visit (AST::BlockExpr &expr) override; + void visit (AST::AnonConst &expr) override; + void visit (AST::ConstBlock &expr) override; void visit (AST::UnsafeBlockExpr &expr) override; void visit (AST::PathInExpression &expr) override; void visit (AST::QualifiedPathInExpression &expr) override; diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index 96cd65640572..ee5765e280c5 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -1296,6 +1296,28 @@ Dump::visit (BlockExpr &e) end ("BlockExpr"); } +void +Dump::visit (AnonConst &e) +{ + begin ("AnonConst"); + do_expr (e); + + visit_field ("inner", e.get_inner_expr ()); + + end ("AnonConst"); +} + +void +Dump::visit (ConstBlock &e) +{ + begin ("ConstBlock"); + do_expr (e); + + visit_field ("inner", e.get_const_expr ()); + + end ("ConstBlock"); +} + void Dump::visit (ContinueExpr &e) { diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h index a1b89ca58741..8c39f489baff 100644 --- a/gcc/rust/hir/rust-hir-dump.h +++ b/gcc/rust/hir/rust-hir-dump.h @@ -146,6 +146,8 @@ class Dump : public HIRFullVisitor virtual void visit (FieldAccessExpr &) override; virtual void visit (ClosureExpr &) override; virtual void visit (BlockExpr &) override; + virtual void visit (AnonConst &) override; + virtual void visit (ConstBlock &) override; virtual void visit (ContinueExpr &) override; virtual void visit (BreakExpr &) override; virtual void visit (RangeFromToExpr &) override; diff --git a/gcc/rust/hir/tree/rust-hir-expr-abstract.h b/gcc/rust/hir/tree/rust-hir-expr-abstract.h index 5bc5d8903099..8272a82808c9 100644 --- a/gcc/rust/hir/tree/rust-hir-expr-abstract.h +++ b/gcc/rust/hir/tree/rust-hir-expr-abstract.h @@ -43,7 +43,7 @@ class Expr : public Node, virtual public FullVisitable WITHOUT_BLOCK, }; - enum ExprType + enum class ExprType { Lit, Operator, @@ -58,6 +58,8 @@ class Expr : public Node, virtual public FullVisitable FieldAccess, Closure, Block, + AnonConst, + ConstBlock, Continue, Break, Range, diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc b/gcc/rust/hir/tree/rust-hir-expr.cc index 5df9253aae21..93dcec2c8d79 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.cc +++ b/gcc/rust/hir/tree/rust-hir-expr.cc @@ -790,6 +790,50 @@ BlockExpr::operator= (BlockExpr const &other) return *this; } +AnonConst::AnonConst (Analysis::NodeMapping mappings, + std::unique_ptr &&expr, location_t locus) + : ExprWithBlock (std::move (mappings), {}), locus (locus), + expr (std::move (expr)) +{ + rust_assert (this->expr); +} + +AnonConst::AnonConst (const AnonConst &other) + : ExprWithBlock (other), locus (other.locus), expr (other.expr->clone_expr ()) +{} + +AnonConst +AnonConst::operator= (const AnonConst &other) +{ + ExprWithBlock::operator= (other); + + locus = other.locus; + expr = other.expr->clone_expr (); + + return *this; +} + +ConstBlock::ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr, + location_t locus, AST::AttrVec outer_attrs) + : ExprWithBlock (std::move (mappings), std::move (outer_attrs)), + expr (std::move (expr)), locus (locus) +{} + +ConstBlock::ConstBlock (const ConstBlock &other) + : ExprWithBlock (other), expr (other.expr), locus (other.locus) +{} + +ConstBlock +ConstBlock::operator= (const ConstBlock &other) +{ + ExprWithBlock::operator= (other); + + expr = other.expr; + locus = other.locus; + + return *this; +} + ContinueExpr::ContinueExpr (Analysis::NodeMapping mappings, location_t locus, tl::optional label, AST::AttrVec outer_attribs) @@ -1310,26 +1354,6 @@ OperatorExprMeta::OperatorExprMeta (HIR::ComparisonExpr &expr) locus (expr.get_locus ()) {} -AnonConst::AnonConst (NodeId id, std::unique_ptr expr) - : id (id), expr (std::move (expr)) -{ - rust_assert (this->expr != nullptr); -} - -AnonConst::AnonConst (const AnonConst &other) -{ - id = other.id; - expr = other.expr->clone_expr (); -} - -AnonConst -AnonConst::operator= (const AnonConst &other) -{ - id = other.id; - expr = other.expr->clone_expr (); - return *this; -} - InlineAsmOperand::In::In ( const tl::optional ®, std::unique_ptr expr) diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 6fbe1e48e1b0..bf278d68b31e 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -19,12 +19,14 @@ #ifndef RUST_HIR_EXPR_H #define RUST_HIR_EXPR_H +#include "rust-ast.h" #include "rust-hir-expr-abstract.h" #include "rust-hir-literal.h" #include "rust-common.h" #include "rust-hir-bound.h" #include "rust-hir-attrs.h" #include "rust-expr.h" +#include "rust-hir-map.h" namespace Rust { namespace HIR { @@ -1800,6 +1802,71 @@ class BlockExpr : public ExprWithBlock, public WithInnerAttrs } }; +class AnonConst : public ExprWithBlock +{ +public: + AnonConst (Analysis::NodeMapping mappings, std::unique_ptr &&expr, + location_t locus = UNKNOWN_LOCATION); + AnonConst (const AnonConst &other); + AnonConst operator= (const AnonConst &other); + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + ExprType get_expression_type () const final override + { + return ExprType::AnonConst; + } + + location_t get_locus () const override { return locus; } + Expr &get_inner_expr () { return *expr; } + const Expr &get_inner_expr () const { return *expr; } + +private: + location_t locus; + std::unique_ptr expr; + + AnonConst *clone_expr_with_block_impl () const override + { + return new AnonConst (*this); + } +}; + +class ConstBlock : public ExprWithBlock +{ +public: + ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr, + location_t locus = UNKNOWN_LOCATION, + AST::AttrVec outer_attrs = {}); + ConstBlock (const ConstBlock &other); + ConstBlock operator= (const ConstBlock &other); + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::string as_string () const override; + + ExprType get_expression_type () const final override + { + return ExprType::ConstBlock; + } + + location_t get_locus () const override { return locus; } + AnonConst &get_const_expr () { return expr; } + const AnonConst &get_const_expr () const { return expr; } + +private: + AnonConst expr; + location_t locus; + + ConstBlock *clone_expr_with_block_impl () const override + { + return new ConstBlock (*this); + } +}; + // HIR node representing continue expression within loops class ContinueExpr : public ExprWithoutBlock { @@ -2892,18 +2959,6 @@ class InlineAsmRegClass std::string placeholder; }; -struct AnonConst -{ - NodeId id; - std::unique_ptr expr; - - AnonConst (NodeId id, std::unique_ptr expr); - - AnonConst (const AnonConst &other); - - AnonConst operator= (const AnonConst &other); -}; - class InlineAsmOperand { public: diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h index 1e313ec1c7b7..2905117dcb7c 100644 --- a/gcc/rust/hir/tree/rust-hir-full-decls.h +++ b/gcc/rust/hir/tree/rust-hir-full-decls.h @@ -95,6 +95,8 @@ class FieldAccessExpr; struct ClosureParam; class ClosureExpr; class BlockExpr; +class AnonConst; +class ConstBlock; class ContinueExpr; class BreakExpr; class RangeExpr; @@ -123,7 +125,6 @@ class AwaitExpr; class AsyncBlockExpr; class InlineAsmReg; class InlineAsmRegClass; -struct AnonConst; class InlineAsmOperand; class InlineAsm; class LlvmInlineAsm; diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h index 283cc346e1e3..43f00dd73b3f 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.h +++ b/gcc/rust/hir/tree/rust-hir-visitor.h @@ -64,6 +64,8 @@ class HIRFullVisitor virtual void visit (MethodCallExpr &expr) = 0; virtual void visit (FieldAccessExpr &expr) = 0; virtual void visit (BlockExpr &expr) = 0; + virtual void visit (AnonConst &expr) = 0; + virtual void visit (ConstBlock &expr) = 0; virtual void visit (ClosureExpr &expr) = 0; virtual void visit (ContinueExpr &expr) = 0; virtual void visit (BreakExpr &expr) = 0; @@ -201,6 +203,8 @@ class HIRFullVisitorBase : public HIRFullVisitor virtual void visit (FieldAccessExpr &) override {} virtual void visit (ClosureExpr &) override {} virtual void visit (BlockExpr &) override {} + virtual void visit (AnonConst &) override {} + virtual void visit (ConstBlock &) override {} virtual void visit (ContinueExpr &) override {} virtual void visit (BreakExpr &) override {} virtual void visit (RangeFromToExpr &) override {} @@ -427,6 +431,8 @@ class HIRExpressionVisitor virtual void visit (MethodCallExpr &expr) = 0; virtual void visit (FieldAccessExpr &expr) = 0; virtual void visit (BlockExpr &expr) = 0; + virtual void visit (AnonConst &expr) = 0; + virtual void visit (ConstBlock &expr) = 0; virtual void visit (ContinueExpr &expr) = 0; virtual void visit (BreakExpr &expr) = 0; virtual void visit (RangeFromToExpr &expr) = 0; diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index 9c8293bd6036..2b9c9ea081a1 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -1049,6 +1049,33 @@ BlockExpr::as_string () const return str; } +std::string +AnonConst::as_string () const +{ + std::string istr = indent_spaces (enter); + std::string str = istr + "AnonConst:\n" + istr; + + str += get_inner_expr ().as_string (); + + str += "\n" + indent_spaces (out); + + return str; +} + +std::string +ConstBlock::as_string () const +{ + std::string istr = indent_spaces (enter); + + std::string str = istr + "ConstBlock:\n" + istr; + + str += get_const_expr ().as_string (); + + str += "\n" + indent_spaces (out); + + return str; +} + std::string TypeAlias::as_string () const { @@ -4056,6 +4083,18 @@ BlockExpr::accept_vis (HIRFullVisitor &vis) vis.visit (*this); } +void +AnonConst::accept_vis (HIRFullVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstBlock::accept_vis (HIRFullVisitor &vis) +{ + vis.visit (*this); +} + void ContinueExpr::accept_vis (HIRFullVisitor &vis) { @@ -5028,6 +5067,18 @@ BlockExpr::accept_vis (HIRExpressionVisitor &vis) vis.visit (*this); } +void +AnonConst::accept_vis (HIRExpressionVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstBlock::accept_vis (HIRExpressionVisitor &vis) +{ + vis.visit (*this); +} + void Function::accept_vis (HIRStmtVisitor &vis) { diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 905d669b3545..81d95c83239f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -646,6 +646,18 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) } } +void +TypeCheckExpr::visit (HIR::AnonConst &expr) +{ + infered = TypeCheckExpr::Resolve (expr.get_inner_expr ()); +} + +void +TypeCheckExpr::visit (HIR::ConstBlock &expr) +{ + infered = TypeCheckExpr::Resolve (expr.get_const_expr ()); +} + void TypeCheckExpr::visit (HIR::RangeFromToExpr &expr) { @@ -822,7 +834,7 @@ typecheck_inline_asm_operand (HIR::InlineAsm &expr) case RegisterType::Const: { auto anon_const = operand.get_const ().anon_const; - TypeCheckExpr::Resolve (*anon_const.expr); + TypeCheckExpr::Resolve (anon_const.get_inner_expr ()); break; } case RegisterType::Sym: diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 79121b36b436..e0a3278fb82d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -46,6 +46,8 @@ class TypeCheckExpr : private TypeCheckBase, private HIR::HIRExpressionVisitor void visit (HIR::IfExpr &expr) override; void visit (HIR::IfExprConseqElse &expr) override; void visit (HIR::BlockExpr &expr) override; + void visit (HIR::AnonConst &expr) override; + void visit (HIR::ConstBlock &expr) override; void visit (HIR::UnsafeBlockExpr &expr) override; void visit (HIR::ArrayIndexExpr &expr) override; void visit (HIR::ArrayExpr &expr) override; From d5adb018b636087fa940528d7a2e57e90752d7e0 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 15 Apr 2025 13:41:41 +0200 Subject: [PATCH 040/161] const-block: Add testcase gcc/testsuite/ChangeLog: * rust/execute/torture/const_block1.rs: New test. --- gcc/testsuite/rust/execute/torture/const_block1.rs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 gcc/testsuite/rust/execute/torture/const_block1.rs diff --git a/gcc/testsuite/rust/execute/torture/const_block1.rs b/gcc/testsuite/rust/execute/torture/const_block1.rs new file mode 100644 index 000000000000..eaf343249d13 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/const_block1.rs @@ -0,0 +1,9 @@ +const X: i32 = const { + let a = 15; + let b = 14; + a + b +}; + +fn main() -> i32 { + X - 29 +} From cdec672976e2f036ed4fee0c9046b026515954e0 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Wed, 4 Jun 2025 01:06:06 -0400 Subject: [PATCH 041/161] Make ConstantItem use Identifier The change to ASTLoweringExternItem is necessary, since with this patch Identifier can be implicitly converted to std::string. gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Handle changed type of ConstantItem::identifier. * ast/rust-ast.cc (ConstantItem::as_string): Likewise. * ast/rust-ast.h (operator const std::string &): New member function. * ast/rust-item.h (ConstantItem::identifier): Change type from std::string to Identifier. (ConstantItem::ConstantItem): Handle changed type of identifier field. (ConstantItem::is_unnamed): Likewise. (ConstantItem::get_identifier): Likewise. * hir/rust-ast-lower-extern.h (ASTLoweringExternItem::visit): Avoid discarding location of wildcard patterns. * lex/rust-token.cc: Include "rust-ast.h". (Token::make_identifier): Add overload accepting an Identifier instance. * lex/rust-token.h (class Identifier): Add forward declaration in order to... (Token::make_identifier): ...declare an overload for this static member function. Signed-off-by: Owen Avery --- gcc/rust/ast/rust-ast-collector.cc | 3 +-- gcc/rust/ast/rust-ast.cc | 2 +- gcc/rust/ast/rust-ast.h | 2 ++ gcc/rust/ast/rust-item.h | 10 +++++----- gcc/rust/hir/rust-ast-lower-extern.h | 2 +- gcc/rust/lex/rust-token.cc | 8 ++++++++ gcc/rust/lex/rust-token.h | 6 ++++++ 7 files changed, 24 insertions(+), 9 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index d6b6a495d110..c6ec0e7bb9be 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -2077,8 +2077,7 @@ TokenCollector::visit (ConstantItem &item) } else { - auto id = item.get_identifier (); - push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); + push (Rust::Token::make_identifier (item.get_identifier ())); } push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (item.get_type ()); diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index fdd86679ba74..916829fe95c0 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -624,7 +624,7 @@ ConstantItem::as_string () const { std::string str = VisItem::as_string (); - str += "const " + identifier; + str += "const " + identifier.as_string (); // DEBUG: null pointer check if (type == nullptr) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 90d2104eb85b..cd586c6aa7d3 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -62,6 +62,8 @@ class Identifier return ident == other.ident; } + operator const std::string & () const { return ident; } + private: std::string ident; location_t loc; diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 247a65f39c2e..d11eed7687b5 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -2450,7 +2450,7 @@ class ConstantItem : public VisItem, public AssociatedItem // either has an identifier or "_" - maybe handle in identifier? // bool identifier_is_underscore; // if no identifier declared, identifier will be "_" - std::string identifier; + Identifier identifier; std::unique_ptr type; std::unique_ptr const_expr; @@ -2460,7 +2460,7 @@ class ConstantItem : public VisItem, public AssociatedItem public: std::string as_string () const override; - ConstantItem (std::string ident, Visibility vis, std::unique_ptr type, + ConstantItem (Identifier ident, Visibility vis, std::unique_ptr type, std::unique_ptr const_expr, std::vector outer_attrs, location_t locus) : VisItem (std::move (vis), std::move (outer_attrs)), @@ -2468,7 +2468,7 @@ class ConstantItem : public VisItem, public AssociatedItem const_expr (std::move (const_expr)), locus (locus) {} - ConstantItem (std::string ident, Visibility vis, std::unique_ptr type, + ConstantItem (Identifier ident, Visibility vis, std::unique_ptr type, std::vector outer_attrs, location_t locus) : VisItem (std::move (vis), std::move (outer_attrs)), identifier (std::move (ident)), type (std::move (type)), @@ -2511,7 +2511,7 @@ class ConstantItem : public VisItem, public AssociatedItem /* Returns whether constant item is an "unnamed" (wildcard underscore used * as identifier) constant. */ - bool is_unnamed () const { return identifier == "_"; } + bool is_unnamed () const { return identifier.as_string () == "_"; } location_t get_locus () const override final { return locus; } @@ -2556,7 +2556,7 @@ class ConstantItem : public VisItem, public AssociatedItem return type; } - std::string get_identifier () const { return identifier; } + const Identifier &get_identifier () const { return identifier; } Item::Kind get_item_kind () const override { diff --git a/gcc/rust/hir/rust-ast-lower-extern.h b/gcc/rust/hir/rust-ast-lower-extern.h index 0105e3840284..3dca1b62666f 100644 --- a/gcc/rust/hir/rust-ast-lower-extern.h +++ b/gcc/rust/hir/rust-ast-lower-extern.h @@ -99,7 +99,7 @@ class ASTLoweringExternItem : public ASTLoweringBase = static_cast (param.get_pattern ()); Identifier param_name = param_kind == AST::Pattern::Kind::Identifier ? param_ident.get_ident () - : std::string ("_"); + : Identifier ("_", param.get_locus ()); HIR::Type *param_type = ASTLoweringType::translate (param.get_type ()); diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc index 783638b41717..c396e100dd8d 100644 --- a/gcc/rust/lex/rust-token.cc +++ b/gcc/rust/lex/rust-token.cc @@ -20,6 +20,7 @@ #include "rust-token.h" #include "rust-diagnostics.h" #include "rust-unicode.h" +#include "rust-ast.h" namespace Rust { // Hackily defined way to get token description for enum value using x-macros @@ -235,6 +236,13 @@ escape_special_chars (const std::string &source, Context ctx) } // namespace +TokenPtr +Token::make_identifier (const Identifier &ident) +{ + std::string str = ident; + return make_identifier (ident.get_locus (), std::move (str)); +} + std::string Token::as_string () const { diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index 2abdf27f6c3b..2021aec4e4ca 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -24,6 +24,10 @@ #include "rust-unicode.h" namespace Rust { + +// used by Rust::Token::make_identifier +class Identifier; + // "Primitive core types" in Rust - the different int and float types, as well // as some others enum PrimitiveCoreType @@ -324,6 +328,8 @@ class Token return TokenPtr (new Token (IDENTIFIER, locus, std::move (str))); } + static TokenPtr make_identifier (const Identifier &ident); + // Makes and returns a new TokenPtr of type INT_LITERAL. static TokenPtr make_int (location_t locus, std::string &&str, PrimitiveCoreType type_hint = CORETYPE_UNKNOWN) From 4d376ecfc2062870d25095ccbb27f5b8c63e924a Mon Sep 17 00:00:00 2001 From: Vishruth-Thimmaiah Date: Tue, 22 Apr 2025 20:04:22 +0530 Subject: [PATCH 042/161] parser: fix ICE std::out_of_range with path attrs to nonexisting path Stops an ICE from occuring when path attribute is empty Fixes Rust-GCC#3607. gcc/rust/ChangeLog: * parse/rust-parse.cc (Rust::extract_module_path): Handle empty or whitespace-only path attributes. gcc/testsuite/ChangeLog: * rust/compile/torture/extern_mod2.rs: New test to ensure an error is emitted for empty path attributes. Signed-off-by: Vishruth Thimmaiah --- gcc/rust/parse/rust-parse.cc | 15 +++++++++++---- gcc/testsuite/rust/compile/torture/extern_mod2.rs | 6 ++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc index 4895c6afdaa0..860fd11612ad 100644 --- a/gcc/rust/parse/rust-parse.cc +++ b/gcc/rust/parse/rust-parse.cc @@ -42,8 +42,7 @@ extract_module_path (const AST::AttrVec &inner_attrs, { rust_error_at ( path_attr.get_locus (), - // Split the format string so that -Wformat-diag does not complain... - "path attributes must contain a filename: '%s'", "#![path = \"file\"]"); + "path attributes must contain a filename: %<#[path = \"file\"]%>"); return name; } @@ -67,8 +66,7 @@ extract_module_path (const AST::AttrVec &inner_attrs, { rust_error_at ( path_attr.get_locus (), - // Split the format string so that -Wformat-diag does not complain... - "path attributes must contain a filename: '%s'", "#[path = \"file\"]"); + "path attributes must contain a filename: %<#[path = \"file\"]%>"); return name; } @@ -80,6 +78,15 @@ extract_module_path (const AST::AttrVec &inner_attrs, // a character that is not an equal sign or whitespace auto filename_begin = path_value.find_first_not_of ("=\t "); + // If the path consists of only whitespace, then we have an error + if (filename_begin == std::string::npos) + { + rust_error_at ( + path_attr.get_locus (), + "path attributes must contain a filename: %<#[path = \"file\"]%>"); + return name; + } + auto path = path_value.substr (filename_begin); // On windows, the path might mix '/' and '\' separators. Replace the diff --git a/gcc/testsuite/rust/compile/torture/extern_mod2.rs b/gcc/testsuite/rust/compile/torture/extern_mod2.rs index 4984d5dc2c14..f3a4f799c3ee 100644 --- a/gcc/testsuite/rust/compile/torture/extern_mod2.rs +++ b/gcc/testsuite/rust/compile/torture/extern_mod2.rs @@ -12,6 +12,12 @@ mod no_leading_equal; #[path = "modules/valid_path.rs"] mod extra_spaces; +#[path = ""] // { dg-error "path attributes must contain a filename" } +mod empty_path; // { dg-error "no candidate found" } + +#[path = " "] // { dg-error "path attributes must contain a filename" } +mod path_with_spaces; // { dg-error "no candidate found" } + #[path] // { dg-error "path attributes must contain a filename" } mod error; // { dg-error "no candidate found" } From 3b0e6a8bb4e2348b700d151c4c9dfe89c1b30825 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Thu, 8 May 2025 20:44:47 -0400 Subject: [PATCH 043/161] nr2.0: Improve visibility path handling gcc/rust/ChangeLog: * resolve/rust-forever-stack.h (enum ResolutionMode): New. (ForeverStack::get): Add a private overload that takes a starting node as a parameter. (ForeverStack::resolve_path): Replace boolean parameter has_opening_scope_resolution with ResolutionMode parameter mode. * resolve/rust-forever-stack.hxx (ForeverStack::resolve_path): Likewise. (ForeverStack::get): Add a private overload that takes a starting node as a parameter. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Add Visibility visitor. * resolve/rust-late-name-resolver-2.0.h (Late::visit): Likewise. * resolve/rust-name-resolution-context.h (NameResolutionContext::resolve_path): Rework overloading a bit and accept ResolutionMode parameter. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove entries. Signed-off-by: Owen Avery --- gcc/rust/resolve/rust-forever-stack.h | 12 +- gcc/rust/resolve/rust-forever-stack.hxx | 103 +++++++++--------- .../resolve/rust-late-name-resolver-2.0.cc | 56 ++++++++++ .../resolve/rust-late-name-resolver-2.0.h | 1 + .../resolve/rust-name-resolution-context.h | 93 +++++++++------- gcc/testsuite/rust/compile/nr2/exclude | 2 - 6 files changed, 174 insertions(+), 93 deletions(-) diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 81468e5c386f..3f6f002da688 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -543,6 +543,13 @@ class ForeverStackStore Node root; }; +enum class ResolutionMode +{ + Normal, + FromRoot, + FromExtern, // extern prelude +}; + template class ForeverStack { public: @@ -672,7 +679,7 @@ template class ForeverStack */ template tl::optional resolve_path ( - const std::vector &segments, bool has_opening_scope_resolution, + const std::vector &segments, ResolutionMode mode, std::function insert_segment_resolution, std::vector &collect_errors); @@ -739,6 +746,9 @@ template class ForeverStack tl::optional parent; // `None` only if the node is a root }; + // private overload which allows specifying a starting point + tl::optional get (Node &start, const Identifier &name); + /* Should we keep going upon seeing a Rib? */ enum class KeepGoing { diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 17136b86ffcd..d568682786c2 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -291,12 +291,12 @@ ForeverStack::update_cursor (Node &new_cursor) template tl::optional -ForeverStack::get (const Identifier &name) +ForeverStack::get (Node &start, const Identifier &name) { tl::optional resolved_definition = tl::nullopt; // TODO: Can we improve the API? have `reverse_iter` return an optional? - reverse_iter ([&resolved_definition, &name] (Node ¤t) { + reverse_iter (start, [&resolved_definition, &name] (Node ¤t) { auto candidate = current.rib.get (name.as_string ()); return candidate.map_or ( @@ -318,6 +318,13 @@ ForeverStack::get (const Identifier &name) return resolved_definition; } +template +tl::optional +ForeverStack::get (const Identifier &name) +{ + return get (cursor (), name); +} + template tl::optional ForeverStack::get_lang_prelude (const Identifier &name) @@ -625,23 +632,25 @@ template template tl::optional ForeverStack::resolve_path ( - const std::vector &segments, bool has_opening_scope_resolution, + const std::vector &segments, ResolutionMode mode, std::function insert_segment_resolution, std::vector &collect_errors) { rust_assert (!segments.empty ()); - // handle paths with opening scopes - std::function cleanup_current = [] () {}; - if (has_opening_scope_resolution) + std::reference_wrapper starting_point = cursor (); + switch (mode) { - Node *last_current = &cursor_reference.get (); - if (get_rust_edition () == Edition::E2015) - cursor_reference = root; - else - cursor_reference = extern_prelude; - cleanup_current - = [this, last_current] () { cursor_reference = *last_current; }; + case ResolutionMode::Normal: + break; // default + case ResolutionMode::FromRoot: + starting_point = root; + break; + case ResolutionMode::FromExtern: + starting_point = extern_prelude; + break; + default: + rust_unreachable (); } // if there's only one segment, we just use `get` @@ -654,13 +663,13 @@ ForeverStack::resolve_path ( lang_item.value ()); insert_segment_resolution (seg, seg_id); - cleanup_current (); // TODO: does NonShadowable matter? return Rib::Definition::NonShadowable (seg_id); } tl::optional res - = get (unwrap_type_segment (segments.back ()).as_string ()); + = get (starting_point.get (), + unwrap_type_segment (segments.back ()).as_string ()); if (!res) res = get_lang_prelude ( @@ -668,45 +677,39 @@ ForeverStack::resolve_path ( if (res && !res->is_ambiguous ()) insert_segment_resolution (segments.back (), res->get_node_id ()); - cleanup_current (); return res; } - std::reference_wrapper starting_point = cursor (); + return find_starting_point (segments, starting_point, + insert_segment_resolution, collect_errors) + .and_then ( + [this, &segments, &starting_point, &insert_segment_resolution, + &collect_errors] (typename std::vector::const_iterator iterator) { + return resolve_segments (starting_point.get (), segments, iterator, + insert_segment_resolution, collect_errors); + }) + .and_then ([this, &segments, &insert_segment_resolution] ( + Node &final_node) -> tl::optional { + // leave resolution within impl blocks to type checker + if (final_node.rib.kind == Rib::Kind::TraitOrImpl) + return tl::nullopt; + + auto &seg = unwrap_type_segment (segments.back ()); + std::string seg_name = seg.as_string (); + + // assuming this can't be a lang item segment + tl::optional res + = resolve_final_segment (final_node, seg_name, + seg.is_lower_self_seg ()); + // Ok we didn't find it in the rib, Lets try the prelude... + if (!res) + res = get_lang_prelude (seg_name); - auto res - = find_starting_point (segments, starting_point, insert_segment_resolution, - collect_errors) - .and_then ( - [this, &segments, &starting_point, &insert_segment_resolution, - &collect_errors] (typename std::vector::const_iterator iterator) { - return resolve_segments (starting_point.get (), segments, iterator, - insert_segment_resolution, collect_errors); - }) - .and_then ([this, &segments, &insert_segment_resolution] ( - Node &final_node) -> tl::optional { - // leave resolution within impl blocks to type checker - if (final_node.rib.kind == Rib::Kind::TraitOrImpl) - return tl::nullopt; - - auto &seg = unwrap_type_segment (segments.back ()); - std::string seg_name = seg.as_string (); - - // assuming this can't be a lang item segment - tl::optional res - = resolve_final_segment (final_node, seg_name, - seg.is_lower_self_seg ()); - // Ok we didn't find it in the rib, Lets try the prelude... - if (!res) - res = get_lang_prelude (seg_name); - - if (res && !res->is_ambiguous ()) - insert_segment_resolution (segments.back (), res->get_node_id ()); - - return res; - }); - cleanup_current (); - return res; + if (res && !res->is_ambiguous ()) + insert_segment_resolution (segments.back (), res->get_node_id ()); + + return res; + }); } template diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index c056b726201e..f8f8a8c9f925 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -515,6 +515,62 @@ Late::visit (AST::TypePath &type) Definition (resolved->get_node_id ())); } +void +Late::visit (AST::Visibility &vis) +{ + if (!vis.has_path ()) + return; + + AST::SimplePath &path = vis.get_path (); + + rust_assert (path.get_segments ().size ()); + auto &first_seg = path.get_segments ()[0]; + + auto mode = ResolutionMode::Normal; + + if (path.has_opening_scope_resolution ()) + { + if (get_rust_edition () == Edition::E2015) + mode = ResolutionMode::FromRoot; + else + mode = ResolutionMode::FromExtern; + } + else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg () + && !first_seg.is_lower_self_seg ()) + { + if (get_rust_edition () == Edition::E2015) + { + mode = ResolutionMode::FromRoot; + } + else + { + rust_error_at (path.get_locus (), + "relative paths are not supported in visibilities in " + "2018 edition or later"); + return; + } + } + + auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types); + + if (!res.has_value ()) + { + rust_error_at (path.get_locus (), ErrorCode::E0433, + "could not resolve path %qs", path.as_string ().c_str ()); + return; + } + + // TODO: is this possible? + if (res->is_ambiguous ()) + { + rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous", + path.as_string ().c_str ()); + return; + } + + ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id ())); +} + void Late::visit (AST::Trait &trait) { diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 4b7b1b874112..5b5637d48a91 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -60,6 +60,7 @@ class Late : public DefaultResolver void visit (AST::LoopLabel &) override; void visit (AST::PathInExpression &) override; void visit (AST::TypePath &) override; + void visit (AST::Visibility &) override; void visit (AST::Trait &) override; void visit (AST::StructExprStruct &) override; void visit (AST::StructExprStructBase &) override; diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index cf87c8f1c79b..1509857739e8 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -280,8 +280,7 @@ class NameResolutionContext template tl::optional - resolve_path (const std::vector &segments, - bool has_opening_scope_resolution, + resolve_path (const std::vector &segments, ResolutionMode mode, std::vector &collect_errors, Namespace ns) { std::function insert_segment_resolution @@ -293,17 +292,17 @@ class NameResolutionContext switch (ns) { case Namespace::Values: - return values.resolve_path (segments, has_opening_scope_resolution, - insert_segment_resolution, collect_errors); + return values.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); case Namespace::Types: - return types.resolve_path (segments, has_opening_scope_resolution, - insert_segment_resolution, collect_errors); + return types.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); case Namespace::Macros: - return macros.resolve_path (segments, has_opening_scope_resolution, - insert_segment_resolution, collect_errors); + return macros.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); case Namespace::Labels: - return labels.resolve_path (segments, has_opening_scope_resolution, - insert_segment_resolution, collect_errors); + return labels.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); default: rust_unreachable (); } @@ -311,8 +310,7 @@ class NameResolutionContext template tl::optional - resolve_path (const std::vector &segments, - bool has_opening_scope_resolution, + resolve_path (const std::vector &segments, ResolutionMode mode, tl::optional &> collect_errors, Namespace ns_first, Args... ns_args) { @@ -321,8 +319,7 @@ class NameResolutionContext for (auto ns : namespaces) { std::vector collect_errors_inner; - if (auto ret = resolve_path (segments, has_opening_scope_resolution, - collect_errors_inner, ns)) + if (auto ret = resolve_path (segments, mode, collect_errors_inner, ns)) return ret; if (!collect_errors_inner.empty ()) { @@ -344,52 +341,68 @@ class NameResolutionContext return tl::nullopt; } - template + template tl::optional - resolve_path (const AST::SimplePath &path, + resolve_path (const std::vector &path_segments, + bool has_opening_scope_resolution, tl::optional &> collect_errors, Namespace ns_first, Args... ns_args) { - return resolve_path (path.get_segments (), - path.has_opening_scope_resolution (), collect_errors, - ns_first, ns_args...); + auto mode = ResolutionMode::Normal; + if (has_opening_scope_resolution) + { + if (get_rust_edition () == Edition::E2015) + mode = ResolutionMode::FromRoot; + else + mode = ResolutionMode::FromExtern; + } + return resolve_path (path_segments, mode, collect_errors, ns_first, + ns_args...); } - template + template tl::optional - resolve_path (const AST::PathInExpression &path, - tl::optional &> collect_errors, - Namespace ns_first, Args... ns_args) + resolve_path (const std::vector &path_segments, + bool has_opening_scope_resolution, Namespace ns_first, + Args... ns_args) { - return resolve_path (path.get_segments (), path.opening_scope_resolution (), - collect_errors, ns_first, ns_args...); + return resolve_path (path_segments, has_opening_scope_resolution, + tl::nullopt, ns_first, ns_args...); } - template + template tl::optional - resolve_path (const AST::TypePath &path, - tl::optional &> collect_errors, + resolve_path (const std::vector &path_segments, ResolutionMode mode, Namespace ns_first, Args... ns_args) + { + return resolve_path (path_segments, mode, tl::nullopt, ns_first, + ns_args...); + } + + template + tl::optional resolve_path (const AST::SimplePath &path, + Args &&...args) { return resolve_path (path.get_segments (), - path.has_opening_scope_resolution_op (), - collect_errors, ns_first, ns_args...); + path.has_opening_scope_resolution (), + std::forward (args)...); } - template - tl::optional resolve_path (const P &path, Namespace ns_first, - Args... ns_args) + template + tl::optional resolve_path (const AST::PathInExpression &path, + Args &&...args) { - return resolve_path (path, tl::nullopt, ns_first, ns_args...); + return resolve_path (path.get_segments (), path.opening_scope_resolution (), + std::forward (args)...); } - template - tl::optional - resolve_path (const P &path_segments, bool has_opening_scope_resolution, - Namespace ns_first, Args... ns_args) + template + tl::optional resolve_path (const AST::TypePath &path, + Args &&...args) { - return resolve_path (path_segments, has_opening_scope_resolution, - tl::nullopt, ns_first, ns_args...); + return resolve_path (path.get_segments (), + path.has_opening_scope_resolution_op (), + std::forward (args)...); } private: diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index d4e066a5f723..70c59f9abdd4 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,10 +1,8 @@ canonical_paths1.rs issue-3315-2.rs -privacy5.rs privacy8.rs pub_restricted_1.rs pub_restricted_2.rs -pub_restricted_3.rs issue-2905-2.rs torture/alt_patterns1.rs torture/name_resolve1.rs From f8689e98376b2eefffd4016f4d72cab5e570ea52 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Thu, 15 May 2025 22:04:34 -0400 Subject: [PATCH 044/161] nr2.0: Catch Self in impl block self types gcc/rust/ChangeLog: * resolve/rust-default-resolver.cc (DefaultResolver::visit): Use visit_impl_type to visit the self types of impl blocks. * resolve/rust-default-resolver.h (DefaultResolver::visit_impl_type): New member function declaration. * resolve/rust-late-name-resolver-2.0.cc (Late::Late): Initialize member variable block_big_self. (Late::visit_impl_type): New member function definition. (Late::visit): Check for Self while inside impl block self types. * resolve/rust-late-name-resolver-2.0.h (Late::visit_impl_type): New member function. (Late::block_big_self): New member variable. gcc/testsuite/ChangeLog: * rust/compile/issue-3671.rs: Remove usage of Self. * rust/compile/nr2/exclude: Remove issue-3671.rs. * rust/compile/self-in-impl.rs: New test. Signed-off-by: Owen Avery --- gcc/rust/resolve/rust-default-resolver.cc | 4 ++-- gcc/rust/resolve/rust-default-resolver.h | 1 + .../resolve/rust-late-name-resolver-2.0.cc | 22 ++++++++++++++++++- .../resolve/rust-late-name-resolver-2.0.h | 4 ++++ gcc/testsuite/rust/compile/issue-3671.rs | 2 +- gcc/testsuite/rust/compile/nr2/exclude | 1 - gcc/testsuite/rust/compile/self-in-impl.rs | 17 ++++++++++++++ 7 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/rust/compile/self-in-impl.rs diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 12f6e1c83349..a4793c048708 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -109,7 +109,7 @@ DefaultResolver::visit (AST::InherentImpl &impl) visit (generic); if (impl.has_where_clause ()) visit (impl.get_where_clause ()); - visit (impl.get_type ()); + visit_impl_type (impl.get_type ()); ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_inner); }; @@ -135,7 +135,7 @@ DefaultResolver::visit (AST::TraitImpl &impl) visit (generic); if (impl.has_where_clause ()) visit (impl.get_where_clause ()); - visit (impl.get_type ()); + visit_impl_type (impl.get_type ()); visit (impl.get_trait_path ()); ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_inner); diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 639e87113d4b..f500d9018f2e 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -51,6 +51,7 @@ class DefaultResolver : public AST::DefaultASTVisitor void visit (AST::Trait &) override; // used to handle Self insertion in TopLevel virtual void maybe_insert_big_self (AST::Impl &) {} + virtual void visit_impl_type (AST::Type &type) { visit (type); } void visit (AST::InherentImpl &) override; void visit (AST::TraitImpl &) override; diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index f8f8a8c9f925..5ffff77ef82a 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -34,7 +34,7 @@ namespace Rust { namespace Resolver2_0 { Late::Late (NameResolutionContext &ctx) - : DefaultResolver (ctx), funny_error (false) + : DefaultResolver (ctx), funny_error (false), block_big_self (false) {} static NodeId @@ -473,6 +473,16 @@ Late::visit (AST::PathInExpression &expr) Definition (resolved->get_node_id ())); } +void +Late::visit_impl_type (AST::Type &type) +{ + // TODO: does this have to handle reentrancy? + rust_assert (!block_big_self); + block_big_self = true; + visit (type); + block_big_self = false; +} + void Late::visit (AST::TypePath &type) { @@ -483,6 +493,16 @@ Late::visit (AST::TypePath &type) DefaultResolver::visit (type); + // prevent "impl Self {}" and similar + if (type.get_segments ().size () == 1 + && !type.get_segments ().front ()->is_lang_item () + && type.get_segments ().front ()->is_big_self_seg () && block_big_self) + { + rust_error_at (type.get_locus (), + "% is not valid in the self type of an impl block"); + return; + } + // this *should* mostly work // TODO: make sure typepath-like path resolution (?) is working auto resolved = ctx.resolve_path (type, Namespace::Types); diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 5b5637d48a91..ddf14ff49409 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -59,6 +59,7 @@ class Late : public DefaultResolver void visit (AST::ContinueExpr &) override; void visit (AST::LoopLabel &) override; void visit (AST::PathInExpression &) override; + void visit_impl_type (AST::Type &) override; void visit (AST::TypePath &) override; void visit (AST::Visibility &) override; void visit (AST::Trait &) override; @@ -78,6 +79,9 @@ class Late : public DefaultResolver void setup_builtin_types (); bool funny_error; + + /* used to prevent "impl Self {}", "impl (Self, i32) {}", etc */ + bool block_big_self; }; // TODO: Add missing mappings and data structures diff --git a/gcc/testsuite/rust/compile/issue-3671.rs b/gcc/testsuite/rust/compile/issue-3671.rs index e800d536e02c..8015653c0bc5 100644 --- a/gcc/testsuite/rust/compile/issue-3671.rs +++ b/gcc/testsuite/rust/compile/issue-3671.rs @@ -1,2 +1,2 @@ -impl Self<0> {} +impl Foo<0> {} // { dg-error "could not resolve type path" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 70c59f9abdd4..dc8d5fbcc089 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -6,7 +6,6 @@ pub_restricted_2.rs issue-2905-2.rs torture/alt_patterns1.rs torture/name_resolve1.rs -issue-3671.rs issue-3652.rs issue-1487.rs issue-2015.rs diff --git a/gcc/testsuite/rust/compile/self-in-impl.rs b/gcc/testsuite/rust/compile/self-in-impl.rs new file mode 100644 index 000000000000..f888162a9f06 --- /dev/null +++ b/gcc/testsuite/rust/compile/self-in-impl.rs @@ -0,0 +1,17 @@ +// { dg-additional-options "-frust-name-resolution-2.0" } + +// the error message here is what rustc >=1.66 emits +// rustc <1.66 emits a "cycle detected" error when +// trying to calculate the impl type +// +// since we aren't trying to match error messages too closely +// and the >=1.66 error message is nicer +// we may as well mimic that + +impl ((Self, i32)) {} +// { dg-error ".Self. is not valid in the self" "" { target *-*-* } .-1 } + +trait Foo {} + +impl Foo for ((Self, i32)) {} +// { dg-error ".Self. is not valid in the self" "" { target *-*-* } .-1 } From b1b77f6d4872c9240fc932abeeb8ca56daba79e8 Mon Sep 17 00:00:00 2001 From: Vishruth-Thimmaiah Date: Wed, 28 May 2025 23:03:27 +0530 Subject: [PATCH 045/161] fix: ICE when parsing unterminated raw byte strings Fixes an ICE when a raw byte string is not terminated Fixes Rust-GCC#3731 gcc/rust/ChangeLog: * lex/rust-lex.cc (Lexer::parse_raw_byte_string): Fix infinite looping when a raw byte string is not terminated. gcc/testsuite/ChangeLog: * rust/compile/torture/unended-raw-byte-string.rs: New test to ensure correct error message for unended raw byte string. Signed-off-by: Vishruth Thimmaiah --- gcc/rust/lex/rust-lex.cc | 10 +++++----- .../rust/compile/torture/unended-raw-byte-string.rs | 6 ++++++ 2 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/rust/compile/torture/unended-raw-byte-string.rs diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index 8a5668f38589..76ff15c21bc1 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -1897,6 +1897,11 @@ Lexer::parse_raw_byte_string (location_t loc) break; } } + else if (current_char.is_eof ()) + { + rust_error_at (string_begin_locus, "unended raw byte string literal"); + return Token::make (END_OF_FILE, get_current_location ()); + } else if (current_char.value > 127) { rust_error_at (get_current_location (), @@ -1904,11 +1909,6 @@ Lexer::parse_raw_byte_string (location_t loc) current_char.as_string ().c_str ()); current_char = 0; } - else if (current_char.is_eof ()) - { - rust_error_at (string_begin_locus, "unended raw byte string literal"); - return Token::make (END_OF_FILE, get_current_location ()); - } length++; current_column++; diff --git a/gcc/testsuite/rust/compile/torture/unended-raw-byte-string.rs b/gcc/testsuite/rust/compile/torture/unended-raw-byte-string.rs new file mode 100644 index 000000000000..91a3c9a2ff8e --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/unended-raw-byte-string.rs @@ -0,0 +1,6 @@ +// { dg-excess-errors "...." } +fn main() { + // { dg-error "unended raw byte string literal" "" { target *-*-* } .+1 } + let s = br##"123"# +} + From 5566c8959c0ccf285371e8d0cc20509b27d16aa4 Mon Sep 17 00:00:00 2001 From: Zhi Heng Date: Sat, 7 Jun 2025 22:30:25 +0800 Subject: [PATCH 046/161] gccrs: Lower IdentifierPattern's to_bind to HIR gcc/rust/ChangeLog: * hir/rust-ast-lower-pattern.cc: Lower of IdentifierPattern's to_bind to HIR. * hir/rust-hir-dump.cc: Update IdentifierPattern's dump to properly show to_bind's full full properties. Signed-off-by: Yap Zhi Heng --- gcc/rust/hir/rust-ast-lower-pattern.cc | 5 +++++ gcc/rust/hir/rust-hir-dump.cc | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc index 9be36c8f2a09..cbb2e4c1fa34 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.cc +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -50,6 +50,11 @@ ASTLoweringPattern::visit (AST::IdentifierPattern &pattern) UNKNOWN_LOCAL_DEFID); std::unique_ptr to_bind; + if (pattern.has_pattern_to_bind ()) + { + to_bind = std::unique_ptr ( + ASTLoweringPattern::translate (pattern.get_pattern_to_bind ())); + } translated = new HIR::IdentifierPattern (mapping, pattern.get_ident (), pattern.get_locus (), pattern.get_is_ref (), diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index ee5765e280c5..984e626b90a9 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -2116,7 +2116,7 @@ Dump::visit (IdentifierPattern &e) put_field ("mut", std::to_string (e.is_mut ())); if (e.has_pattern_to_bind ()) - put_field ("to_bind", e.get_to_bind ().as_string ()); + visit_field ("to_bind", e.get_to_bind ()); else put_field ("to_bind", "none"); From ca5cf9d8ab7866d5c69cfa5e7cb99448a21b0c8e Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 2 May 2025 18:38:50 -0400 Subject: [PATCH 047/161] nr2.0: Separate out canonical path handling This should improve our canonical path handling, without requiring further tweaks to ForeverStack. This may also help if, in the future, we have to move canonical path calculation to later compilation phases for proper handling of generics. gcc/rust/ChangeLog: * backend/rust-compile-base.cc (HIRCompileBase::compile_function): Since canonical paths returned from nr2.0 now include the crate name, avoid prepending the crate name again. * backend/rust-compile-implitem.cc (CompileTraitItem::visit): Use NameResolutionContext::to_canonical_path instead of ForeverStack::to_canonical_path. * backend/rust-compile-item.cc (CompileItem::visit): Likewise. * typecheck/rust-hir-type-check-enumitem.cc (TypeCheckEnumItem::visit): Likewise. * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItem::visit): Likewise. * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): Likewise. * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): Likewise. * resolve/rust-default-resolver.cc (DefaultResolver::visit): Add Crate and EnumItem instance visitors, handle canonical path context scoping. * resolve/rust-default-resolver.h (DefaultResolver::visit): Add Crate and EnumItem instance visitors. * resolve/rust-early-name-resolver-2.0.cc (Early::go): Visit instances of Crate using the virtual member function visit. * resolve/rust-forever-stack.h (ForeverStack::to_canonical_path): Remove function declaration. * resolve/rust-forever-stack.hxx (ForeverStack::to_canonical_path): Remove function definition. * resolve/rust-late-name-resolver-2.0.cc (Late::go): Visit instances of Crate using the virtual member function visit. * resolve/rust-name-resolution-context.cc (CanonicalPathRecordCrateRoot::as_path): New function definition. (CanonicalPathRecordNormal::as_path): Likewise. (CanonicalPathRecordLookup::as_path): Likewise. (CanonicalPathRecordImpl::as_path): Likewise. (CanonicalPathRecordTraitImpl::as_path): Likewise. (NameResolutionContext::NameResolutionContext): Initialize member variable canonical_ctx. * resolve/rust-name-resolution-context.h: Include "rust-item.h". (class NameResolutionContext): Forward declare class. (class CanonicalPathRecord): New class. (class CanonicalPathRecordWithParent): Likewise. (class CanonicalPathRecordCrateRoot): Likewise. (class CanonicalPathRecordNormal): Likewise. (class CanonicalPathRecordLookup): Likewise. (class CanonicalPathRecordImpl): Likewise. (class CanonicalPathRecordTraitImpl): Likewise. (class CanonicalPathCtx): Likewise. (NameResolutionContext::canonical_ctx): New member variable. (NameResolutionContext::to_canonical_path): New member function. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::go): Visit instances of Crate with the virtual member function visit. (TopLevel::visit): Handle canonical path context scoping for external crates, use DefaultResolver::visit when visiting instances of StructStruct. * util/rust-canonical-path.h (CanonicalPath::new_seg): Take path parameter by-value, as a duplicate instance will be constructed regardless. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove canonical_paths1.rs. --- gcc/rust/backend/rust-compile-base.cc | 5 - gcc/rust/backend/rust-compile-implitem.cc | 6 +- gcc/rust/backend/rust-compile-item.cc | 11 +- gcc/rust/resolve/rust-default-resolver.cc | 169 ++++++++++-- gcc/rust/resolve/rust-default-resolver.h | 5 + .../resolve/rust-early-name-resolver-2.0.cc | 5 +- gcc/rust/resolve/rust-forever-stack.h | 3 - gcc/rust/resolve/rust-forever-stack.hxx | 61 ----- .../resolve/rust-late-name-resolver-2.0.cc | 3 +- .../resolve/rust-name-resolution-context.cc | 57 +++- .../resolve/rust-name-resolution-context.h | 250 ++++++++++++++++++ .../rust-toplevel-name-resolver-2.0.cc | 24 +- .../typecheck/rust-hir-type-check-enumitem.cc | 8 +- .../typecheck/rust-hir-type-check-implitem.cc | 4 +- .../typecheck/rust-hir-type-check-item.cc | 26 +- gcc/rust/typecheck/rust-hir-type-check.cc | 2 +- gcc/rust/util/rust-canonical-path.h | 5 +- gcc/testsuite/rust/compile/nr2/exclude | 1 - 18 files changed, 493 insertions(+), 152 deletions(-) diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index 12b956168bd3..84c4bcd3fe43 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -687,11 +687,6 @@ HIRCompileBase::compile_function ( } std::string asm_name = fn_name; - auto &mappings = Analysis::Mappings::get (); - - if (flag_name_resolution_2_0) - ir_symbol_name = mappings.get_current_crate_name () + "::" + ir_symbol_name; - unsigned int flags = 0; tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, "" /* asm_name */, flags, locus); diff --git a/gcc/rust/backend/rust-compile-implitem.cc b/gcc/rust/backend/rust-compile-implitem.cc index 1230c85c57ca..f9172c5282c6 100644 --- a/gcc/rust/backend/rust-compile-implitem.cc +++ b/gcc/rust/backend/rust-compile-implitem.cc @@ -33,8 +33,8 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - canonical_path = nr_ctx.values.to_canonical_path ( - constant.get_mappings ().get_nodeid ()); + canonical_path + = nr_ctx.to_canonical_path (constant.get_mappings ().get_nodeid ()); } else { @@ -103,7 +103,7 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func) = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.values.to_canonical_path (func.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (func.get_mappings ().get_nodeid ()); } else { diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc index 96669903fd55..3e7ea9a25e93 100644 --- a/gcc/rust/backend/rust-compile-item.cc +++ b/gcc/rust/backend/rust-compile-item.cc @@ -58,7 +58,7 @@ CompileItem::visit (HIR::StaticItem &var) = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.values.to_canonical_path (var.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (var.get_mappings ().get_nodeid ()); } else { @@ -124,8 +124,7 @@ CompileItem::visit (HIR::ConstantItem &constant) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - canonical_path - = nr_ctx.values.to_canonical_path (mappings.get_nodeid ()).value (); + canonical_path = nr_ctx.to_canonical_path (mappings.get_nodeid ()); } else { @@ -218,10 +217,8 @@ CompileItem::visit (HIR::Function &function) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto path = nr_ctx.values.to_canonical_path ( - function.get_mappings ().get_nodeid ()); - - canonical_path = path.value (); + canonical_path + = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ()); } else { diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index a4793c048708..969711c29950 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -24,6 +24,21 @@ namespace Rust { namespace Resolver2_0 { +void +DefaultResolver::visit (AST::Crate &crate) +{ + auto inner_fn = [this, &crate] () { AST::DefaultASTVisitor::visit (crate); }; + + auto &mappings = Analysis::Mappings::get (); + + auto crate_num = mappings.lookup_crate_num (crate.get_node_id ()); + rust_assert (crate_num.has_value ()); + auto crate_name = mappings.get_crate_name (*crate_num); + rust_assert (crate_name.has_value ()); + + ctx.canonical_ctx.scope_crate (crate.get_node_id (), *crate_name, inner_fn); +} + void DefaultResolver::visit (AST::BlockExpr &expr) { @@ -38,19 +53,32 @@ DefaultResolver::visit (AST::BlockExpr &expr) void DefaultResolver::visit (AST::Module &module) { - auto item_fn = [this, &module] () { AST::DefaultASTVisitor::visit (module); }; + auto item_fn_1 + = [this, &module] () { AST::DefaultASTVisitor::visit (module); }; - ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn, + auto item_fn_2 = [this, &module, &item_fn_1] () { + ctx.canonical_ctx.scope (module.get_node_id (), module.get_name (), + std::move (item_fn_1)); + }; + + ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn_2, module.get_name ()); } void DefaultResolver::visit (AST::Function &function) { - auto def_fn + auto def_fn_1 = [this, &function] () { AST::DefaultASTVisitor::visit (function); }; - ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn); + auto def_fn_2 = [this, &function, &def_fn_1] () { + ctx.canonical_ctx.scope (function.get_node_id (), + function.get_function_name (), + std::move (def_fn_1)); + }; + + ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn_2, + function.get_function_name ()); } void @@ -85,9 +113,15 @@ DefaultResolver::visit (AST::IfLetExpr &expr) void DefaultResolver::visit (AST::Trait &trait) { - auto inner_fn = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); }; + auto inner_fn_1 + = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); }; + + auto inner_fn_2 = [this, &trait, &inner_fn_1] () { + ctx.canonical_ctx.scope (trait.get_node_id (), trait.get_identifier (), + std::move (inner_fn_1)); + }; - ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn, + ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn_2, trait.get_identifier () /* FIXME: Is that valid?*/); } @@ -98,12 +132,12 @@ DefaultResolver::visit (AST::InherentImpl &impl) visit (impl.get_visibility ()); visit_inner_attrs (impl); - auto inner_fn_inner = [this, &impl] () { + auto inner_fn_1 = [this, &impl] () { for (auto &item : impl.get_impl_items ()) visit (item); }; - auto inner_fn_outer = [this, &impl, &inner_fn_inner] () { + auto inner_fn_2 = [this, &impl, &inner_fn_1] () { maybe_insert_big_self (impl); for (auto &generic : impl.get_generic_params ()) visit (generic); @@ -111,10 +145,14 @@ DefaultResolver::visit (AST::InherentImpl &impl) visit (impl.get_where_clause ()); visit_impl_type (impl.get_type ()); - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_inner); + ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1); }; - ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_outer); + auto inner_fn_3 = [this, &impl, &inner_fn_2] () { + ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2)); + }; + + ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3); } void @@ -124,12 +162,12 @@ DefaultResolver::visit (AST::TraitImpl &impl) visit (impl.get_visibility ()); visit_inner_attrs (impl); - auto inner_fn_inner = [this, &impl] () { + auto inner_fn_1 = [this, &impl] () { for (auto &item : impl.get_impl_items ()) visit (item); }; - auto inner_fn_outer = [this, &impl, &inner_fn_inner] () { + auto inner_fn_2 = [this, &impl, &inner_fn_1] () { maybe_insert_big_self (impl); for (auto &generic : impl.get_generic_params ()) visit (generic); @@ -138,55 +176,120 @@ DefaultResolver::visit (AST::TraitImpl &impl) visit_impl_type (impl.get_type ()); visit (impl.get_trait_path ()); - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_inner); + ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1); + }; + + auto inner_fn_3 = [this, &impl, &inner_fn_2] () { + ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2)); }; - ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_outer); + ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3); } void DefaultResolver::visit (AST::StructStruct &type) { - auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - inner_fn, type.get_struct_name ()); + inner_fn_2, type.get_struct_name ()); } void DefaultResolver::visit (AST::TupleStruct &type) { - auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - inner_fn, type.get_struct_name ()); + inner_fn_2, type.get_struct_name ()); +} + +void +DefaultResolver::visit (AST::EnumItem &item) +{ + auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + inner_fn); +} + +void +DefaultResolver::visit (AST::EnumItemTuple &item) +{ + auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + inner_fn); +} + +void +DefaultResolver::visit (AST::EnumItemStruct &item) +{ + auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + inner_fn); +} + +void +DefaultResolver::visit (AST::EnumItemDiscriminant &item) +{ + auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + inner_fn); } void DefaultResolver::visit (AST::Enum &type) { - auto variant_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - variant_fn, type.get_identifier ()); + inner_fn_2, type.get_identifier ()); } void DefaultResolver::visit (AST::Union &type) { - auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - inner_fn, type.get_identifier ()); + inner_fn_2, type.get_identifier ()); } void DefaultResolver::visit (AST::TypeAlias &type) { - auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_new_type_name (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - inner_fn, type.get_new_type_name ()); + inner_fn_2, type.get_new_type_name ()); } void @@ -221,21 +324,31 @@ DefaultResolver::visit (AST::ConstantItem &item) { if (item.has_expr ()) { - auto expr_vis + auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + auto expr_vis_2 = [this, &item, &expr_vis_1] () { + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + std::move (expr_vis_1)); + }; + // FIXME: Why do we need a Rib here? - ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis); + ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2); } } void DefaultResolver::visit (AST::StaticItem &item) { - auto expr_vis = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + auto expr_vis_2 = [this, &item, &expr_vis_1] () { + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + std::move (expr_vis_1)); + }; // FIXME: Why do we need a Rib here? - ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis); + ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2); } void diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index f500d9018f2e..e80d77440b15 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -39,6 +39,7 @@ class DefaultResolver : public AST::DefaultASTVisitor virtual ~DefaultResolver () {} + void visit (AST::Crate &) override; // First, our lexical scope expressions - these visit their sub nodes, always // these nodes create new scopes and ribs - they are often used to declare new // variables, such as a for loop's iterator, or a function's arguments @@ -60,6 +61,10 @@ class DefaultResolver : public AST::DefaultASTVisitor // type dec nodes, which visit their fields or variants by default void visit (AST::StructStruct &) override; void visit (AST::TupleStruct &) override; + void visit (AST::EnumItem &) override; + void visit (AST::EnumItemTuple &) override; + void visit (AST::EnumItemStruct &) override; + void visit (AST::EnumItemDiscriminant &) override; void visit (AST::Enum &) override; void visit (AST::Union &) override; void visit (AST::TypeAlias &) override; diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index b00bd1ee7f8e..c10379a65eb4 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -62,8 +62,9 @@ Early::go (AST::Crate &crate) // We now proceed with resolving macros, which can be nested in almost any // items textual_scope.push (); - for (auto &item : crate.items) - item->accept_vis (*this); + + visit (crate); + textual_scope.pop (); } diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 3f6f002da688..75dd87395bef 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -683,9 +683,6 @@ template class ForeverStack std::function insert_segment_resolution, std::vector &collect_errors); - // FIXME: Documentation - tl::optional to_canonical_path (NodeId id) const; - // FIXME: Documentation tl::optional to_rib (NodeId rib_id); tl::optional to_rib (NodeId rib_id) const; diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index d568682786c2..df3df1059fcb 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -773,67 +773,6 @@ ForeverStack::dfs (const ForeverStack::Node &starting_point, return tl::nullopt; } -template -tl::optional -ForeverStack::to_canonical_path (NodeId id) const -{ - // find the id in the current forever stack, starting from the root, - // performing either a BFS or DFS once the Node containing the ID is found, go - // back up to the root (parent().parent().parent()...) accumulate link - // segments reverse them that's your canonical path - - return dfs (root, id).map ([this, id] (ConstDfsResult tuple) { - auto containing_node = tuple.first; - auto name = tuple.second; - - auto segments = std::vector (); - - reverse_iter (containing_node, [&segments] (const Node ¤t) { - if (current.is_root ()) - return KeepGoing::No; - - auto children = current.parent.value ().children; - const Link *outer_link = nullptr; - - for (auto &kv : children) - { - auto &link = kv.first; - auto &child = kv.second; - - if (current.id == child.id) - { - outer_link = &link; - break; - } - } - - rust_assert (outer_link); - - outer_link->path.map ([&segments, outer_link] (Identifier path) { - segments.emplace (segments.begin (), - Resolver::CanonicalPath::new_seg (outer_link->id, - path.as_string ())); - }); - - return KeepGoing::Yes; - }); - - auto &mappings = Analysis::Mappings::get (); - CrateNum crate_num = mappings.lookup_crate_num (root.id).value (); - auto path = Resolver::CanonicalPath::new_seg ( - root.id, mappings.get_crate_name (crate_num).value ()); - path.set_crate_num (crate_num); - - for (const auto &segment : segments) - path = path.append (segment); - - // Finally, append the name - path = path.append (Resolver::CanonicalPath::new_seg (id, name)); - - return path; - }); -} - template tl::optional ForeverStack::dfs_rib (ForeverStack::Node &starting_point, NodeId to_find) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 5ffff77ef82a..2c6a469a9add 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -116,8 +116,7 @@ Late::go (AST::Crate &crate) { setup_builtin_types (); - for (auto &item : crate.items) - item->accept_vis (*this); + visit (crate); } void diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc index f098e4880e59..34615ed97c32 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -82,8 +82,63 @@ BindingLayer::get_source () const return source; } +Resolver::CanonicalPath +CanonicalPathRecordCrateRoot::as_path (const NameResolutionContext &) +{ + auto ret = Resolver::CanonicalPath::new_seg (node_id, seg); + ret.set_crate_num (crate_num); + return ret; +} + +Resolver::CanonicalPath +CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx) +{ + auto parent_path = get_parent ().as_path (ctx); + return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg)); +} + +Resolver::CanonicalPath +CanonicalPathRecordLookup::as_path (const NameResolutionContext &ctx) +{ + if (!cache) + { + auto res = ctx.lookup (lookup_id).and_then ( + [&ctx] (NodeId id) { return ctx.canonical_ctx.get_record_opt (id); }); + + if (!res) + { + // HACK: use a dummy value + // this should bring us roughly to parity with nr1.0 + // since nr1.0 doesn't seem to handle canonical paths for generics + // quite right anyways + return Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "XXX"); + } + + cache = res.value (); + } + return cache->as_path (ctx); +} + +Resolver::CanonicalPath +CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx) +{ + auto parent_path = get_parent ().as_path (ctx); + return parent_path.append ( + Resolver::CanonicalPath::inherent_impl_seg (impl_id, + type_record.as_path (ctx))); +} + +Resolver::CanonicalPath +CanonicalPathRecordTraitImpl::as_path (const NameResolutionContext &ctx) +{ + auto parent_path = get_parent ().as_path (ctx); + return parent_path.append ( + Resolver::CanonicalPath::trait_impl_projection_seg ( + impl_id, trait_path_record.as_path (ctx), type_record.as_path (ctx))); +} + NameResolutionContext::NameResolutionContext () - : mappings (Analysis::Mappings::get ()) + : mappings (Analysis::Mappings::get ()), canonical_ctx (*this) {} tl::expected diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index 1509857739e8..bb8519a04933 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -24,6 +24,7 @@ #include "rust-hir-map.h" #include "rust-rib.h" #include "rust-stacked-contexts.h" +#include "rust-item.h" namespace Rust { namespace Resolver2_0 { @@ -214,6 +215,248 @@ class BindingLayer BindingSource get_source () const; }; +class NameResolutionContext; +/* + * Used to handle canonical paths + * Similar to ForeverStack, but namespace independent and more specialized + */ +class CanonicalPathRecord +{ +public: + virtual Resolver::CanonicalPath as_path (const NameResolutionContext &) = 0; + + virtual bool is_root () const = 0; + + virtual ~CanonicalPathRecord () = default; +}; + +class CanonicalPathRecordWithParent : public CanonicalPathRecord +{ +public: + CanonicalPathRecordWithParent (CanonicalPathRecord &parent) : parent (&parent) + {} + + CanonicalPathRecord &get_parent () { return *parent; } + + bool is_root () const override final { return false; } + +private: + CanonicalPathRecord *parent; +}; + +class CanonicalPathRecordCrateRoot : public CanonicalPathRecord +{ +public: + CanonicalPathRecordCrateRoot (NodeId node_id, std::string seg) + : node_id (node_id), seg (std::move (seg)) + { + rust_assert (Analysis::Mappings::get ().node_is_crate (node_id)); + crate_num = Analysis::Mappings::get ().lookup_crate_num (node_id).value (); + } + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + + bool is_root () const override final { return true; } + +private: + NodeId node_id; + CrateNum crate_num; + std::string seg; +}; + +class CanonicalPathRecordNormal : public CanonicalPathRecordWithParent +{ +public: + CanonicalPathRecordNormal (CanonicalPathRecord &parent, NodeId node_id, + std::string seg) + : CanonicalPathRecordWithParent (parent), node_id (node_id), + seg (std::move (seg)) + { + rust_assert (!Analysis::Mappings::get ().node_is_crate (node_id)); + } + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + +private: + NodeId node_id; + std::string seg; +}; + +class CanonicalPathRecordLookup : public CanonicalPathRecord +{ +public: + CanonicalPathRecordLookup (NodeId lookup_id) + : lookup_id (lookup_id), cache (nullptr) + {} + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + + bool is_root () const override final { return true; } + +private: + NodeId lookup_id; + CanonicalPathRecord *cache; +}; + +class CanonicalPathRecordImpl : public CanonicalPathRecordWithParent +{ +public: + CanonicalPathRecordImpl (CanonicalPathRecord &parent, NodeId impl_id, + NodeId type_id) + : CanonicalPathRecordWithParent (parent), impl_id (impl_id), + type_record (type_id) + {} + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + +private: + NodeId impl_id; + CanonicalPathRecordLookup type_record; +}; + +class CanonicalPathRecordTraitImpl : public CanonicalPathRecordWithParent +{ +public: + CanonicalPathRecordTraitImpl (CanonicalPathRecord &parent, NodeId impl_id, + NodeId type_id, NodeId trait_path_id) + : CanonicalPathRecordWithParent (parent), impl_id (impl_id), + type_record (type_id), trait_path_record (trait_path_id) + {} + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + +private: + NodeId impl_id; + CanonicalPathRecordLookup type_record; + CanonicalPathRecordLookup trait_path_record; +}; + +class CanonicalPathCtx +{ +public: + CanonicalPathCtx (const NameResolutionContext &ctx) + : current_record (nullptr), nr_ctx (&ctx) + {} + + Resolver::CanonicalPath get_path (NodeId id) const + { + return get_record (id).as_path (*nr_ctx); + } + + CanonicalPathRecord &get_record (NodeId id) const + { + auto it = records.find (id); + rust_assert (it != records.end ()); + return *it->second; + } + + tl::optional get_record_opt (NodeId id) const + { + auto it = records.find (id); + if (it == records.end ()) + return tl::nullopt; + else + return it->second.get (); + } + + void insert_record (NodeId id, const Identifier &ident) + { + insert_record (id, ident.as_string ()); + } + + void insert_record (NodeId id, std::string seg) + { + rust_assert (current_record != nullptr); + + auto it = records.find (id); + if (it == records.end ()) + { + auto record = new CanonicalPathRecordNormal (*current_record, id, + std::move (seg)); + bool ok + = records.emplace (id, std::unique_ptr (record)) + .second; + rust_assert (ok); + } + } + + template void scope (NodeId id, const Identifier &ident, F &&f) + { + scope (id, ident.as_string (), std::forward (f)); + } + + template void scope (NodeId id, std::string seg, F &&f) + { + rust_assert (current_record != nullptr); + + scope_inner (id, std::forward (f), [this, id, &seg] () { + return new CanonicalPathRecordNormal (*current_record, id, + std::move (seg)); + }); + } + + template void scope_impl (AST::InherentImpl &impl, F &&f) + { + rust_assert (current_record != nullptr); + + NodeId id = impl.get_node_id (); + scope_inner (id, std::forward (f), [this, id, &impl] () { + return new CanonicalPathRecordImpl (*current_record, id, + impl.get_type ().get_node_id ()); + }); + } + + template void scope_impl (AST::TraitImpl &impl, F &&f) + { + rust_assert (current_record != nullptr); + + NodeId id = impl.get_node_id (); + scope_inner (id, std::forward (f), [this, id, &impl] () { + return new CanonicalPathRecordTraitImpl ( + *current_record, id, impl.get_type ().get_node_id (), + impl.get_trait_path ().get_node_id ()); + }); + } + + template + void scope_crate (NodeId node_id, std::string crate_name, F &&f) + { + scope_inner (node_id, std::forward (f), [node_id, &crate_name] () { + return new CanonicalPathRecordCrateRoot (node_id, std::move (crate_name)); + }); + } + +private: + template + void scope_inner (NodeId id, FCallback &&f_callback, FCreate &&f_create) + { + auto it = records.find (id); + if (it == records.end ()) + { + CanonicalPathRecord *record = std::forward (f_create) (); + it = records.emplace (id, std::unique_ptr (record)) + .first; + } + + rust_assert (it->second->is_root () + || &static_cast (*it->second) + .get_parent () + == current_record); + + CanonicalPathRecord *stash = it->second.get (); + std::swap (stash, current_record); + + std::forward (f_callback) (); + + std::swap (stash, current_record); + } + + std::unordered_map> records; + CanonicalPathRecord *current_record; + + const NameResolutionContext *nr_ctx; +}; + // Now our resolver, which keeps track of all the `ForeverStack`s we could want class NameResolutionContext { @@ -272,12 +515,19 @@ class NameResolutionContext Analysis::Mappings &mappings; StackedContexts bindings; + CanonicalPathCtx canonical_ctx; + // TODO: Rename // TODO: Use newtype pattern for Usage and Definition void map_usage (Usage usage, Definition definition); tl::optional lookup (NodeId usage) const; + Resolver::CanonicalPath to_canonical_path (NodeId id) const + { + return canonical_ctx.get_path (id); + } + template tl::optional resolve_path (const std::vector &segments, ResolutionMode mode, diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index 4d88ad1eb370..3e5ed534e4e6 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -95,8 +95,7 @@ TopLevel::go (AST::Crate &crate) // times in a row in a fixed-point fashion, so it would make the code // responsible for this ugly and perfom a lot of error checking. - for (auto &item : crate.items) - item->accept_vis (*this); + visit (crate); } void @@ -194,7 +193,7 @@ TopLevel::visit (AST::ExternCrate &crate) auto derive_macros = mappings.lookup_derive_proc_macros (num); - auto sub_visitor = [&] () { + auto sub_visitor_1 = [&] () { // TODO: Find a way to keep this part clean without the double dispatch. if (derive_macros.has_value ()) { @@ -216,11 +215,17 @@ TopLevel::visit (AST::ExternCrate &crate) } }; + auto sub_visitor_2 = [&] () { + ctx.canonical_ctx.scope_crate (crate.get_node_id (), + crate.get_referenced_crate (), + std::move (sub_visitor_1)); + }; + if (crate.has_as_clause ()) - ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor, + ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor_2, crate.get_as_clause ()); else - ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor, + ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor_2, crate.get_referenced_crate ()); } @@ -298,14 +303,7 @@ TopLevel::visit (AST::ExternalStaticItem &static_item) void TopLevel::visit (AST::StructStruct &struct_item) { - auto generic_vis = [this, &struct_item] () { - for (auto &g : struct_item.get_generic_params ()) - { - g->accept_vis (*this); - } - }; - - ctx.scoped (Rib::Kind::Item, struct_item.get_node_id (), generic_vis); + DefaultResolver::visit (struct_item); insert_or_error_out (struct_item.get_struct_name (), struct_item, Namespace::Types); diff --git a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc index c80a12f8f84e..2dbd84d254ae 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc @@ -87,7 +87,7 @@ TypeCheckEnumItem::visit (HIR::EnumItem &item) = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ()); } else { @@ -131,7 +131,7 @@ TypeCheckEnumItem::visit (HIR::EnumItemDiscriminant &item) = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ()); } else { @@ -193,7 +193,7 @@ TypeCheckEnumItem::visit (HIR::EnumItemTuple &item) = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ()); } else { @@ -253,7 +253,7 @@ TypeCheckEnumItem::visit (HIR::EnumItemStruct &item) = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ()); } else { diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc index 168a934fa540..00f0cc669747 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc @@ -345,8 +345,8 @@ TypeCheckImplItem::visit (HIR::Function &function) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - canonical_path = nr_ctx.values.to_canonical_path ( - function.get_mappings ().get_nodeid ()); + canonical_path + = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ()); } else { diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index aaa04af628f4..5595dad22cc5 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -203,9 +203,8 @@ TypeCheckItem::visit (HIR::TupleStruct &struct_decl) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - path = nr_ctx.values - .to_canonical_path (struct_decl.get_mappings ().get_nodeid ()) - .value (); + path + = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ()); } else { @@ -283,12 +282,8 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl) { auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto canonical_path = nr_ctx.types.to_canonical_path ( - struct_decl.get_mappings ().get_nodeid ()); - - if (!canonical_path.has_value ()) - rust_unreachable (); - path = canonical_path.value (); + path + = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ()); } else { @@ -375,8 +370,8 @@ TypeCheckItem::visit (HIR::Enum &enum_decl) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - canonical_path = nr_ctx.types.to_canonical_path ( - enum_decl.get_mappings ().get_nodeid ()); + canonical_path + = nr_ctx.to_canonical_path (enum_decl.get_mappings ().get_nodeid ()); } else { @@ -439,8 +434,8 @@ TypeCheckItem::visit (HIR::Union &union_decl) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - canonical_path = nr_ctx.types.to_canonical_path ( - union_decl.get_mappings ().get_nodeid ()); + canonical_path + = nr_ctx.to_canonical_path (union_decl.get_mappings ().get_nodeid ()); } else { @@ -614,10 +609,7 @@ TypeCheckItem::visit (HIR::Function &function) { auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto canonical_path = nr_ctx.values.to_canonical_path ( - function.get_mappings ().get_nodeid ()); - - path = canonical_path.value (); + path = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ()); } else { diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index d386fda036bb..27879e3d4e9d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -284,7 +284,7 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.values.to_canonical_path (fn.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (fn.get_mappings ().get_nodeid ()); } else { diff --git a/gcc/rust/util/rust-canonical-path.h b/gcc/rust/util/rust-canonical-path.h index ee37befb2e04..079ae76eadba 100644 --- a/gcc/rust/util/rust-canonical-path.h +++ b/gcc/rust/util/rust-canonical-path.h @@ -57,10 +57,11 @@ class CanonicalPath return *this; } - static CanonicalPath new_seg (NodeId id, const std::string &path) + static CanonicalPath new_seg (NodeId id, std::string path) { rust_assert (!path.empty ()); - return CanonicalPath ({std::pair (id, path)}, + return CanonicalPath ({std::pair (id, + std::move (path))}, UNKNOWN_CRATENUM); } diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index dc8d5fbcc089..9d5b7dfbbd30 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,4 +1,3 @@ -canonical_paths1.rs issue-3315-2.rs privacy8.rs pub_restricted_1.rs From 49ee109eb97e1dcf27e2107285e1e6ad8de7bc1d Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Mon, 9 Jun 2025 17:11:39 -0400 Subject: [PATCH 048/161] Add new function ClosureExpr::get_definition_expr gcc/rust/ChangeLog: * ast/rust-expr.h (ClosureExpr::get_definition_expr): New virtual member function. (ClosureExprInner::get_definition_expr): Add override specifier. (ClosureExprInnerTyped::get_definition_block): Rename to... (ClosureExprInnerTyped::get_definition_expr): ...here and add override specifier. * ast/rust-ast-collector.cc (TokenCollector::visit): Handle rename of ClosureExprInnerTyped::get_definition_block to ClosureExprInnerTyped::get_definition_expr. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. * expand/rust-cfg-strip.cc (CfgStrip::visit): Likewise. * expand/rust-expand-visitor.cc (ExpandVisitor::visit): Likewise. * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise. * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): Likewise. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise. Signed-off-by: Owen Avery --- gcc/rust/ast/rust-ast-collector.cc | 2 +- gcc/rust/ast/rust-ast-visitor.cc | 2 +- gcc/rust/ast/rust-expr.h | 6 ++++-- gcc/rust/expand/rust-cfg-strip.cc | 2 +- gcc/rust/expand/rust-expand-visitor.cc | 2 +- gcc/rust/hir/rust-ast-lower-expr.cc | 2 +- gcc/rust/resolve/rust-ast-resolve-expr.cc | 2 +- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 2 +- 8 files changed, 11 insertions(+), 9 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index c6ec0e7bb9be..94a0240b510b 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -1291,7 +1291,7 @@ TokenCollector::visit (ClosureExprInnerTyped &expr) visit_closure_common (expr); push (Rust::Token::make (RETURN_TYPE, expr.get_locus ())); visit (expr.get_return_type ()); - visit (expr.get_definition_block ()); + visit (expr.get_definition_expr ()); } void diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index bd1b65aaec91..ab6a022ccee1 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -474,7 +474,7 @@ DefaultASTVisitor::visit (AST::ClosureExprInnerTyped &expr) for (auto ¶m : expr.get_params ()) visit (param); visit (expr.get_return_type ()); - visit (expr.get_definition_block ()); + visit (expr.get_definition_expr ()); } void diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index ba20bfaa6014..8f44d5878bbf 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -2506,6 +2506,8 @@ class ClosureExpr : public ExprWithoutBlock bool get_has_move () const { return has_move; } Expr::Kind get_expr_kind () const override { return Expr::Kind::Closure; } + + virtual Expr &get_definition_expr () = 0; }; // Represents a non-type-specified closure expression AST node @@ -2565,7 +2567,7 @@ class ClosureExprInner : public ClosureExpr return closure_inner == nullptr; } - Expr &get_definition_expr () + Expr &get_definition_expr () override { rust_assert (closure_inner != nullptr); return *closure_inner; @@ -2932,7 +2934,7 @@ class ClosureExprInnerTyped : public ClosureExpr bool is_marked_for_strip () const override { return expr == nullptr; } // TODO: is this better? Or is a "vis_block" better? - BlockExpr &get_definition_block () + BlockExpr &get_definition_expr () override { rust_assert (expr != nullptr); return *expr; diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index f761f9916c9a..916a695ad267 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -1192,7 +1192,7 @@ CfgStrip::visit (AST::ClosureExprInnerTyped &expr) rust_error_at (type.get_locus (), "cannot strip type in this position"); // can't strip expression itself, but can strip sub-expressions - auto &definition_block = expr.get_definition_block (); + auto &definition_block = expr.get_definition_expr (); definition_block.accept_vis (*this); if (definition_block.is_marked_for_strip ()) rust_error_at (definition_block.get_locus (), diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index 42df5e1ee118..ba7bac12ddf4 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -641,7 +641,7 @@ ExpandVisitor::visit (AST::ClosureExprInnerTyped &expr) maybe_expand_type (expr.get_return_type_ptr ()); - visit (expr.get_definition_block ()); + visit (expr.get_definition_expr ()); } void diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc index 16e80a0841aa..3f3d6007e461 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.cc +++ b/gcc/rust/hir/rust-ast-lower-expr.cc @@ -836,7 +836,7 @@ ASTLoweringExpr::visit (AST::ClosureExprInnerTyped &expr) { HIR::Type *closure_return_type = nullptr; HIR::Expr *closure_expr - = ASTLoweringExpr::translate (expr.get_definition_block ()); + = ASTLoweringExpr::translate (expr.get_definition_expr ()); std::vector closure_params; for (auto ¶m : expr.get_params ()) diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc index 8482123e891c..ffce8ba76007 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc @@ -786,7 +786,7 @@ ResolveExpr::visit (AST::ClosureExprInnerTyped &expr) resolver->push_closure_context (expr.get_node_id ()); - ResolveExpr::go (expr.get_definition_block (), prefix, canonical_prefix); + ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix); resolver->pop_closure_context (); diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 2c6a469a9add..a0435ff12d78 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -730,7 +730,7 @@ Late::visit (AST::ClosureExprInnerTyped &closure) ctx.bindings.exit (); visit (closure.get_return_type ()); - visit (closure.get_definition_block ()); + visit (closure.get_definition_expr ()); } } // namespace Resolver2_0 From aa5b7dfd3276a9327d5e43b5a96f25ea65f7b9e6 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 23 May 2025 16:19:59 -0400 Subject: [PATCH 049/161] nr2.0: Improve StructPatternFieldIdent handling gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Use visit_identifier_as_pattern to handle IdentifierPattern and StructPatternFieldIdent. (visit_identifier_as_pattern): New function. Signed-off-by: Owen Avery --- .../resolve/rust-late-name-resolver-2.0.cc | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index a0435ff12d78..50a29292444c 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -208,45 +208,53 @@ Late::visit (AST::LetStmt &let) // let.get_node_id (), [] () {}); } -void -Late::visit (AST::IdentifierPattern &identifier) +static void +visit_identifier_as_pattern (NameResolutionContext &ctx, + const Identifier &ident, location_t locus, + NodeId node_id) { // 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? - if (ctx.bindings.peek ().is_and_bound (identifier.get_ident ())) + if (ctx.bindings.peek ().is_and_bound (ident)) { if (ctx.bindings.peek ().get_source () == BindingSource::Param) rust_error_at ( - identifier.get_locus (), ErrorCode::E0415, + locus, ErrorCode::E0415, "identifier %qs is bound more than once in the same parameter list", - identifier.as_string ().c_str ()); + ident.as_string ().c_str ()); else rust_error_at ( - identifier.get_locus (), ErrorCode::E0416, + locus, ErrorCode::E0416, "identifier %qs is bound more than once in the same pattern", - identifier.as_string ().c_str ()); + ident.as_string ().c_str ()); return; } - ctx.bindings.peek ().insert_ident (identifier.get_ident ()); + ctx.bindings.peek ().insert_ident (ident); - if (ctx.bindings.peek ().is_or_bound (identifier.get_ident ())) + if (ctx.bindings.peek ().is_or_bound (ident)) { // FIXME: map usage instead - std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), - identifier.get_node_id ()); + std::ignore = ctx.values.insert_shadowable (ident, node_id); } else { // We do want to ignore duplicated data because some situations rely on // it. - std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), - identifier.get_node_id ()); + std::ignore = ctx.values.insert_shadowable (ident, node_id); } } +void +Late::visit (AST::IdentifierPattern &identifier) +{ + visit_identifier_as_pattern (ctx, identifier.get_ident (), + identifier.get_locus (), + identifier.get_node_id ()); +} + void Late::visit (AST::AltPattern &pattern) { @@ -274,9 +282,8 @@ Late::visit_function_params (AST::Function &function) void Late::visit (AST::StructPatternFieldIdent &field) { - // We do want to ignore duplicated data because some situations rely on it. - std::ignore = ctx.values.insert_shadowable (field.get_identifier (), - field.get_node_id ()); + visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (), + field.get_node_id ()); } void From 4ed0c9210ee487ebed7072cb5b956d548114a1cd Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Sat, 17 May 2025 22:26:20 -0400 Subject: [PATCH 050/161] nr2.0: Adjust pub_restricted tests gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove entries. * rust/compile/pub_restricted_1.rs: Adjust expected error messages and only run with name resolution 2.0 enabled. * rust/compile/pub_restricted_2.rs: Likewise. Signed-off-by: Owen Avery --- gcc/testsuite/rust/compile/nr2/exclude | 2 -- gcc/testsuite/rust/compile/pub_restricted_1.rs | 8 +++++--- gcc/testsuite/rust/compile/pub_restricted_2.rs | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 9d5b7dfbbd30..c02805fd2271 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,7 +1,5 @@ issue-3315-2.rs privacy8.rs -pub_restricted_1.rs -pub_restricted_2.rs issue-2905-2.rs torture/alt_patterns1.rs torture/name_resolve1.rs diff --git a/gcc/testsuite/rust/compile/pub_restricted_1.rs b/gcc/testsuite/rust/compile/pub_restricted_1.rs index 9bda96824032..44989a887e93 100644 --- a/gcc/testsuite/rust/compile/pub_restricted_1.rs +++ b/gcc/testsuite/rust/compile/pub_restricted_1.rs @@ -1,3 +1,5 @@ +// { dg-additional-options "-frust-name-resolution-2.0" } + pub mod foo { pub mod bar { pub fn baz() {} @@ -6,8 +8,8 @@ pub mod foo { } } -pub(in foo::fah::baz) struct A1; // { dg-error "cannot find simple path segment .fah." } -pub(in fro::bulator::saindoux) struct A2; // { dg-error "cannot find simple path segment .fro." } -pub(in foo::bar::saindoux) struct A3; // { dg-error "cannot find simple path segment .saindoux." } +pub(in foo::fah::baz) struct A1; // { dg-error "could not resolve path .foo::fah::baz." } +pub(in fro::bulator::saindoux) struct A2; // { dg-error "could not resolve path .fro::bulator::saindoux." } +pub(in foo::bar::saindoux) struct A3; // { dg-error "could not resolve path .foo::bar::saindoux." } fn main() {} diff --git a/gcc/testsuite/rust/compile/pub_restricted_2.rs b/gcc/testsuite/rust/compile/pub_restricted_2.rs index 8588f2775cac..91f072e890f8 100644 --- a/gcc/testsuite/rust/compile/pub_restricted_2.rs +++ b/gcc/testsuite/rust/compile/pub_restricted_2.rs @@ -1,18 +1,18 @@ -// { dg-additional-options "-w" } +// { dg-additional-options "-w -frust-name-resolution-2.0" } mod foo { mod bar { mod baz { - pub(in baz) struct A0; - pub(in bar::baz) struct A1; + pub(in super::baz) struct A0; + pub(in super::super::bar::baz) struct A1; pub(in foo::bar::baz) struct A2; mod sain { mod doux {} } - pub(in sain) struct A3; // { dg-error "restricted path is not an ancestor of the current module" } - pub(in sain::doux) struct A4; // { dg-error "restricted path is not an ancestor of the current module" } + pub(in self::sain) struct A3; // { dg-error "restricted path is not an ancestor of the current module" } + pub(in self::sain::doux) struct A4; // { dg-error "restricted path is not an ancestor of the current module" } } } } From c110aadd66e2e9549b13b41f9e21dd142593193c Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Sat, 29 Mar 2025 19:50:28 -0400 Subject: [PATCH 051/161] nr2.0: Improve handling of single segment paths gcc/rust/ChangeLog: * resolve/rust-forever-stack.hxx (ForeverStack::resolve_path): Handle single segment paths "crate", "self", and "super". gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove entries. Signed-off-by: Owen Avery --- gcc/rust/resolve/rust-forever-stack.hxx | 50 +++++++++++++++++++++---- gcc/testsuite/rust/compile/nr2/exclude | 2 - 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index df3df1059fcb..8721386a2402 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -656,27 +656,61 @@ ForeverStack::resolve_path ( // if there's only one segment, we just use `get` if (segments.size () == 1) { - auto &seg = segments.front (); - if (auto lang_item = unwrap_segment_get_lang_item (seg)) + auto &outer_seg = segments.front (); + if (auto lang_item = unwrap_segment_get_lang_item (outer_seg)) { NodeId seg_id = Analysis::Mappings::get ().get_lang_item_node ( lang_item.value ()); - insert_segment_resolution (seg, seg_id); + insert_segment_resolution (outer_seg, seg_id); // TODO: does NonShadowable matter? return Rib::Definition::NonShadowable (seg_id); } + auto &seg = unwrap_type_segment (outer_seg); + tl::optional res - = get (starting_point.get (), - unwrap_type_segment (segments.back ()).as_string ()); + = get (starting_point.get (), seg.as_string ()); if (!res) - res = get_lang_prelude ( - unwrap_type_segment (segments.back ()).as_string ()); + res = get_lang_prelude (seg.as_string ()); + + if (!res && N == Namespace::Types) + { + if (seg.is_crate_path_seg ()) + { + insert_segment_resolution (outer_seg, root.id); + // TODO: does NonShadowable matter? + return Rib::Definition::NonShadowable (root.id); + } + else if (seg.is_lower_self_seg ()) + { + NodeId id = find_closest_module (starting_point.get ()).id; + insert_segment_resolution (outer_seg, id); + // TODO: does NonShadowable matter? + return Rib::Definition::NonShadowable (id); + } + else if (seg.is_super_path_seg ()) + { + Node &closest_module + = find_closest_module (starting_point.get ()); + if (closest_module.is_root ()) + { + rust_error_at (seg.get_locus (), ErrorCode::E0433, + "too many leading % keywords"); + return tl::nullopt; + } + + NodeId id + = find_closest_module (closest_module.parent.value ()).id; + insert_segment_resolution (outer_seg, id); + // TODO: does NonShadowable matter? + return Rib::Definition::NonShadowable (id); + } + } if (res && !res->is_ambiguous ()) - insert_segment_resolution (segments.back (), res->get_node_id ()); + insert_segment_resolution (outer_seg, res->get_node_id ()); return res; } diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index c02805fd2271..31d7a26be4e3 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,6 +1,4 @@ issue-3315-2.rs -privacy8.rs -issue-2905-2.rs torture/alt_patterns1.rs torture/name_resolve1.rs issue-3652.rs From 064b37d3cfdc6af59917b30cdd4ab3ae84a245be Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Wed, 14 May 2025 21:40:04 -0400 Subject: [PATCH 052/161] nr2.0: Fix closure parameter scoping gcc/rust/ChangeLog: * resolve/rust-default-resolver.cc (DefaultResolver::visit_closure_params): New member function definition. (DefaultResolver::visit): New visiting function definition for ClosureExpr called from visiting functions for ClosureExprInner and ClosureExprInnerTyped. * resolve/rust-default-resolver.h (DefaultResolver::visit_closure_params): New member function declaration. (DefaultResolver::visit): New visiting function declaration for ClosureExpr. * resolve/rust-late-name-resolver-2.0.cc (add_captures): Remove function. (Late::visit): New visiting function definition for ClosureExpr, remove visiting function definitions for ClosureExprInner and ClosureExprInnerTyped. (Late::visit_closure_params): New member function definition. * resolve/rust-late-name-resolver-2.0.h (Late::visit): New visiting function declaration for ClosureExpr, remove visiting function declarations for ClosureExprInner and ClosureExprInnerTyped. (Late::visit_closure_params): New member function declaration. Signed-off-by: Owen Avery --- gcc/rust/resolve/rust-default-resolver.cc | 25 ++++++++++- gcc/rust/resolve/rust-default-resolver.h | 2 + .../resolve/rust-late-name-resolver-2.0.cc | 44 +++++-------------- .../resolve/rust-late-name-resolver-2.0.h | 4 +- 4 files changed, 37 insertions(+), 38 deletions(-) diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 969711c29950..01906cf0a32d 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -292,13 +292,33 @@ DefaultResolver::visit (AST::TypeAlias &type) inner_fn_2, type.get_new_type_name ()); } +void +DefaultResolver::visit_closure_params (AST::ClosureExpr &expr) +{ + for (auto ¶m : expr.get_params ()) + visit (param); +} + +void +DefaultResolver::visit (AST::ClosureExpr &expr) +{ + auto expr_fn = [this, &expr] () { + visit_closure_params (expr); + visit (expr.get_definition_expr ()); + }; + + visit_outer_attrs (expr); + + ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), expr_fn); +} + void DefaultResolver::visit (AST::ClosureExprInner &expr) { if (expr.is_marked_for_strip ()) return; - AST::DefaultASTVisitor::visit (expr); + visit (static_cast (expr)); } void @@ -307,7 +327,8 @@ DefaultResolver::visit (AST::ClosureExprInnerTyped &expr) if (expr.is_marked_for_strip ()) return; - AST::DefaultASTVisitor::visit (expr); + visit (static_cast (expr)); + visit (expr.get_return_type ()); } void diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index e80d77440b15..99fd8e77a48d 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -70,6 +70,8 @@ class DefaultResolver : public AST::DefaultASTVisitor void visit (AST::TypeAlias &) override; // Visitors that visit their expression node(s) + virtual void visit_closure_params (AST::ClosureExpr &); + virtual void visit (AST::ClosureExpr &); void visit (AST::ClosureExprInner &) override; void visit (AST::ClosureExprInnerTyped &) override; void visit (AST::MatchExpr &) override; diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 50a29292444c..227aa203d9f1 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -693,51 +693,27 @@ Late::visit (AST::GenericArg &arg) DefaultResolver::visit (arg); } -template -static void -add_captures (Closure &closure, NameResolutionContext &ctx) -{ - auto vals = ctx.values.peek ().get_values (); - for (auto &val : vals) - { - ctx.mappings.add_capture (closure.get_node_id (), - val.second.get_node_id ()); - } -} - void -Late::visit (AST::ClosureExprInner &closure) +Late::visit_closure_params (AST::ClosureExpr &closure) { - add_captures (closure, ctx); - - visit_outer_attrs (closure); - ctx.bindings.enter (BindingSource::Param); - for (auto ¶m : closure.get_params ()) - visit (param); + DefaultResolver::visit_closure_params (closure); ctx.bindings.exit (); - - visit (closure.get_definition_expr ()); } void -Late::visit (AST::ClosureExprInnerTyped &closure) +Late::visit (AST::ClosureExpr &expr) { - add_captures (closure, ctx); - - visit_outer_attrs (closure); - - ctx.bindings.enter (BindingSource::Param); - - for (auto ¶m : closure.get_params ()) - visit (param); - - ctx.bindings.exit (); + // add captures + auto vals = ctx.values.peek ().get_values (); + for (auto &val : vals) + { + ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ()); + } - visit (closure.get_return_type ()); - visit (closure.get_definition_expr ()); + DefaultResolver::visit (expr); } } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index ddf14ff49409..f2907c90514e 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -69,8 +69,8 @@ class Late : public DefaultResolver void visit (AST::StructStruct &) override; void visit (AST::GenericArgs &) override; void visit (AST::GenericArg &); - void visit (AST::ClosureExprInner &) override; - void visit (AST::ClosureExprInnerTyped &) override; + void visit_closure_params (AST::ClosureExpr &) override; + void visit (AST::ClosureExpr &) override; private: void resolve_label (AST::Lifetime &lifetime); From 0bfcbc2ea9254802ec65da407988f58186a61475 Mon Sep 17 00:00:00 2001 From: Zhi Heng Date: Sat, 7 Jun 2025 22:24:03 +0800 Subject: [PATCH 053/161] gccrs: Support compilation of IdentifierPattern's subpatterns gcc/rust/ChangeLog: * backend/rust-compile-pattern.cc: Add CheckExpr compilation for IdentifierPattern with subpattern. * backend/rust-compile-pattern.h: Modify IdentifierPattern's visit func to support the above. * typecheck/rust-hir-type-check-pattern.cc: Add typechecking support for the changes above. Signed-off-by: Yap Zhi Heng --- gcc/rust/backend/rust-compile-pattern.cc | 11 +++++++++++ gcc/rust/backend/rust-compile-pattern.h | 5 +---- gcc/rust/typecheck/rust-hir-type-check-pattern.cc | 5 +++++ gcc/testsuite/rust/compile/match-identifierpattern.rs | 9 +++++++++ .../rust/execute/torture/match-identifierpattern.rs | 10 ++++++++++ 5 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/rust/compile/match-identifierpattern.rs create mode 100644 gcc/testsuite/rust/execute/torture/match-identifierpattern.rs diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index 7b937c766e2a..f81e910b2b2d 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -434,6 +434,17 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) } } +void CompilePatternCheckExpr::visit (HIR::IdentifierPattern &pattern) +{ + if (pattern.has_pattern_to_bind()) + { + check_expr = CompilePatternCheckExpr::Compile (pattern.get_to_bind(), match_scrutinee_expr, ctx); + } else + { + check_expr = boolean_true_node; + } +} + // setup the bindings void diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h index 85c82b8458f8..4dd7d559e6eb 100644 --- a/gcc/rust/backend/rust-compile-pattern.h +++ b/gcc/rust/backend/rust-compile-pattern.h @@ -45,12 +45,9 @@ class CompilePatternCheckExpr : public HIRCompileBase, void visit (HIR::StructPattern &) override; void visit (HIR::TupleStructPattern &) override; void visit (HIR::TuplePattern &) override; + void visit (HIR::IdentifierPattern &) override; // Always succeeds - void visit (HIR::IdentifierPattern &) override - { - check_expr = boolean_true_node; - } void visit (HIR::WildcardPattern &) override { check_expr = boolean_true_node; diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index 102083bd84c3..c1037ecd54e8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -546,6 +546,11 @@ TypeCheckPattern::visit (HIR::RangePattern &pattern) void TypeCheckPattern::visit (HIR::IdentifierPattern &pattern) { + if (pattern.has_pattern_to_bind ()) + { + TypeCheckPattern::Resolve (pattern.get_to_bind (), parent); + } + if (!pattern.get_is_ref ()) { infered = parent; diff --git a/gcc/testsuite/rust/compile/match-identifierpattern.rs b/gcc/testsuite/rust/compile/match-identifierpattern.rs new file mode 100644 index 000000000000..6c558ac065b9 --- /dev/null +++ b/gcc/testsuite/rust/compile/match-identifierpattern.rs @@ -0,0 +1,9 @@ +fn main() { + let x = 1; + + match x { + 2 => {}, + a @ 3 => {}, + _ => {}, + } +} diff --git a/gcc/testsuite/rust/execute/torture/match-identifierpattern.rs b/gcc/testsuite/rust/execute/torture/match-identifierpattern.rs new file mode 100644 index 000000000000..b102ad1ec417 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/match-identifierpattern.rs @@ -0,0 +1,10 @@ +fn main() -> i32 { + let mut x = 2; + + match x { + a @ 2 => { x = a + 1 }, + _ => {} + } + + x - 3 +} From dd4592d34768d6a86d71451f37c9b3c8f112b1e8 Mon Sep 17 00:00:00 2001 From: Zhi Heng Date: Mon, 9 Jun 2025 20:18:28 +0800 Subject: [PATCH 054/161] gccrs: Rename IdentifierPattern's to_bind to subpattern gcc/rust/ChangeLog: * ast/rust-ast-collector.cc: Rename to_bind to subpattern. * ast/rust-ast-visitor.cc: Ditto. * ast/rust-pattern.cc: Ditto. * ast/rust-pattern.h: Ditto. * backend/rust-compile-pattern.cc: Ditto. * expand/rust-cfg-strip.cc: Ditto. * hir/rust-ast-lower-pattern.cc: Ditto. * hir/rust-hir-dump.cc: Ditto. * hir/tree/rust-hir-pattern.h: Ditto. * hir/tree/rust-hir.cc: Ditto. * typecheck/rust-hir-type-check-pattern.cc: Ditto. Signed-off-by: Yap Zhi Heng --- gcc/rust/ast/rust-ast-collector.cc | 2 +- gcc/rust/ast/rust-ast-visitor.cc | 2 +- gcc/rust/ast/rust-pattern.cc | 4 +-- gcc/rust/ast/rust-pattern.h | 26 +++++++++---------- gcc/rust/backend/rust-compile-pattern.cc | 19 ++++++++------ gcc/rust/expand/rust-cfg-strip.cc | 2 +- gcc/rust/hir/rust-ast-lower-pattern.cc | 8 +++--- gcc/rust/hir/rust-hir-dump.cc | 6 ++--- gcc/rust/hir/tree/rust-hir-pattern.h | 18 ++++++------- gcc/rust/hir/tree/rust-hir.cc | 4 +-- .../typecheck/rust-hir-type-check-pattern.cc | 4 +-- 11 files changed, 49 insertions(+), 46 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 94a0240b510b..b0e06ab85dbc 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -2482,7 +2482,7 @@ TokenCollector::visit (IdentifierPattern &pattern) auto id = pattern.get_ident ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); - if (pattern.has_pattern_to_bind ()) + if (pattern.has_subpattern ()) { push (Rust::Token::make (PATTERN_BIND, UNDEF_LOCATION)); visit (pattern.get_pattern_to_bind ()); diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index ab6a022ccee1..02f4f1664d62 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -1199,7 +1199,7 @@ DefaultASTVisitor::visit (AST::LiteralPattern &pattern) void DefaultASTVisitor::visit (AST::IdentifierPattern &pattern) { - if (pattern.has_pattern_to_bind ()) + if (pattern.has_subpattern ()) visit (pattern.get_pattern_to_bind ()); } diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc index fc7b6107be0e..62bf6f2c5e89 100644 --- a/gcc/rust/ast/rust-pattern.cc +++ b/gcc/rust/ast/rust-pattern.cc @@ -65,8 +65,8 @@ IdentifierPattern::as_string () const str += variable_ident.as_string (); - if (has_pattern_to_bind ()) - str += " @ " + to_bind->as_string (); + if (has_subpattern ()) + str += " @ " + subpattern->as_string (); return str; } diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index e6cd8f1eb047..195a08f4fcd9 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -74,7 +74,7 @@ class IdentifierPattern : public Pattern bool is_mut; // bool has_pattern; - std::unique_ptr to_bind; + std::unique_ptr subpattern; location_t locus; NodeId node_id; @@ -82,22 +82,22 @@ class IdentifierPattern : public Pattern std::string as_string () const override; // Returns whether the IdentifierPattern has a pattern to bind. - bool has_pattern_to_bind () const { return to_bind != nullptr; } + bool has_subpattern () const { return subpattern != nullptr; } // Constructor IdentifierPattern (Identifier ident, location_t locus, bool is_ref = false, bool is_mut = false, - std::unique_ptr to_bind = nullptr) + std::unique_ptr subpattern = nullptr) : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), - is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), + is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} IdentifierPattern (NodeId node_id, Identifier ident, location_t locus, bool is_ref = false, bool is_mut = false, - std::unique_ptr to_bind = nullptr) + std::unique_ptr subpattern = nullptr) : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), - is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), + is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus), node_id (node_id) {} @@ -107,8 +107,8 @@ class IdentifierPattern : public Pattern is_mut (other.is_mut), locus (other.locus), node_id (other.node_id) { // fix to get prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); } // Overload assignment operator to use clone @@ -121,10 +121,10 @@ class IdentifierPattern : public Pattern node_id = other.node_id; // fix to prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); else - to_bind = nullptr; + subpattern = nullptr; return *this; } @@ -140,8 +140,8 @@ class IdentifierPattern : public Pattern // TODO: is this better? Or is a "vis_pattern" better? Pattern &get_pattern_to_bind () { - rust_assert (has_pattern_to_bind ()); - return *to_bind; + rust_assert (has_subpattern ()); + return *subpattern; } Identifier get_ident () const { return variable_ident; } diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index f81e910b2b2d..e19aa678497d 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -434,15 +434,18 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) } } -void CompilePatternCheckExpr::visit (HIR::IdentifierPattern &pattern) +void +CompilePatternCheckExpr::visit (HIR::IdentifierPattern &pattern) { - if (pattern.has_pattern_to_bind()) - { - check_expr = CompilePatternCheckExpr::Compile (pattern.get_to_bind(), match_scrutinee_expr, ctx); - } else - { - check_expr = boolean_true_node; - } + if (pattern.has_subpattern ()) + { + check_expr = CompilePatternCheckExpr::Compile (pattern.get_subpattern (), + match_scrutinee_expr, ctx); + } + else + { + check_expr = boolean_true_node; + } } // setup the bindings diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index 916a695ad267..0db6122d5c33 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -2262,7 +2262,7 @@ void CfgStrip::visit (AST::IdentifierPattern &pattern) { // can only strip sub-patterns of the inner pattern to bind - if (!pattern.has_pattern_to_bind ()) + if (!pattern.has_subpattern ()) return; AST::DefaultASTVisitor::visit (pattern); diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc index cbb2e4c1fa34..9baf81d6ee91 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.cc +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -49,10 +49,10 @@ ASTLoweringPattern::visit (AST::IdentifierPattern &pattern) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - std::unique_ptr to_bind; - if (pattern.has_pattern_to_bind ()) + std::unique_ptr subpattern; + if (pattern.has_subpattern ()) { - to_bind = std::unique_ptr ( + subpattern = std::unique_ptr ( ASTLoweringPattern::translate (pattern.get_pattern_to_bind ())); } translated @@ -60,7 +60,7 @@ ASTLoweringPattern::visit (AST::IdentifierPattern &pattern) pattern.get_locus (), pattern.get_is_ref (), pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm, - std::move (to_bind)); + std::move (subpattern)); } void diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index 984e626b90a9..38079c76f9a9 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -2115,10 +2115,10 @@ Dump::visit (IdentifierPattern &e) put_field ("is_ref", std::to_string (e.get_is_ref ())); put_field ("mut", std::to_string (e.is_mut ())); - if (e.has_pattern_to_bind ()) - visit_field ("to_bind", e.get_to_bind ()); + if (e.has_subpattern ()) + visit_field ("subpattern", e.get_subpattern ()); else - put_field ("to_bind", "none"); + put_field ("subpattern", "none"); end ("IdentifierPattern"); } diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h index 5cc5c9512ecc..9c636caeb25a 100644 --- a/gcc/rust/hir/tree/rust-hir-pattern.h +++ b/gcc/rust/hir/tree/rust-hir-pattern.h @@ -80,7 +80,7 @@ class IdentifierPattern : public Pattern Identifier variable_ident; bool is_ref; Mutability mut; - std::unique_ptr to_bind; + std::unique_ptr subpattern; location_t locus; Analysis::NodeMapping mappings; @@ -88,15 +88,15 @@ class IdentifierPattern : public Pattern std::string as_string () const override; // Returns whether the IdentifierPattern has a pattern to bind. - bool has_pattern_to_bind () const { return to_bind != nullptr; } + bool has_subpattern () const { return subpattern != nullptr; } // Constructor IdentifierPattern (Analysis::NodeMapping mappings, Identifier ident, location_t locus, bool is_ref = false, Mutability mut = Mutability::Imm, - std::unique_ptr to_bind = nullptr) + std::unique_ptr subpattern = nullptr) : variable_ident (std::move (ident)), is_ref (is_ref), mut (mut), - to_bind (std::move (to_bind)), locus (locus), mappings (mappings) + subpattern (std::move (subpattern)), locus (locus), mappings (mappings) {} // Copy constructor with clone @@ -105,8 +105,8 @@ class IdentifierPattern : public Pattern mut (other.mut), locus (other.locus), mappings (other.mappings) { // fix to get prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); } // Overload assignment operator to use clone @@ -119,8 +119,8 @@ class IdentifierPattern : public Pattern mappings = other.mappings; // fix to get prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); return *this; } @@ -133,7 +133,7 @@ class IdentifierPattern : public Pattern bool is_mut () const { return mut == Mutability::Mut; } bool get_is_ref () const { return is_ref; } - Pattern &get_to_bind () { return *to_bind; } + Pattern &get_subpattern () { return *subpattern; } void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRPatternVisitor &vis) override; diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index 2b9c9ea081a1..dc94fb5b1eb7 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -2608,9 +2608,9 @@ IdentifierPattern::as_string () const str += variable_ident.as_string (); - if (has_pattern_to_bind ()) + if (has_subpattern ()) { - str += " @ " + to_bind->as_string (); + str += " @ " + subpattern->as_string (); } return str; diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index c1037ecd54e8..15d8620dc2ad 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -546,9 +546,9 @@ TypeCheckPattern::visit (HIR::RangePattern &pattern) void TypeCheckPattern::visit (HIR::IdentifierPattern &pattern) { - if (pattern.has_pattern_to_bind ()) + if (pattern.has_subpattern ()) { - TypeCheckPattern::Resolve (pattern.get_to_bind (), parent); + TypeCheckPattern::Resolve (pattern.get_subpattern (), parent); } if (!pattern.get_is_ref ()) From 9f90da0555f2ba39866ec1a37291f615584daff9 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 23 May 2025 16:29:59 -0400 Subject: [PATCH 055/161] nr2.0: Adjust alternate identifier handling gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (visit_identifier_as_pattern): Make sure to map identifiers inside or-bindings to prior identifiers. Signed-off-by: Owen Avery --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 227aa203d9f1..f8f1eb5c1b05 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -236,8 +236,9 @@ visit_identifier_as_pattern (NameResolutionContext &ctx, if (ctx.bindings.peek ().is_or_bound (ident)) { - // FIXME: map usage instead - std::ignore = ctx.values.insert_shadowable (ident, node_id); + auto res = ctx.values.get (ident); + rust_assert (res.has_value () && !res->is_ambiguous ()); + ctx.map_usage (Usage (node_id), Definition (res->get_node_id ())); } else { From e733c005f49b4221af46de869dc3314e98fab635 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 27 May 2025 13:47:04 +0100 Subject: [PATCH 056/161] gccrs: Fix bad type canonicalization on ARRAY_TYPES Fixes Rust-GCC#3660 gcc/rust/ChangeLog: * backend/rust-compile-type.cc (TyTyResolveCompile::visit): reuse GCC's build_array_type gcc/testsuite/ChangeLog: * rust/compile/const_generics_3.rs: * rust/compile/issue-3660.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/backend/rust-compile-type.cc | 13 ++++++++----- gcc/testsuite/rust/compile/const_generics_3.rs | 2 +- gcc/testsuite/rust/compile/issue-3660.rs | 3 +++ 3 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/rust/compile/issue-3660.rs diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index 00b21fbbf952..7e56a0f4e1be 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -17,11 +17,11 @@ // . #include "rust-compile-type.h" -#include "rust-compile-expr.h" #include "rust-constexpr.h" -#include "rust-gcc.h" +#include "rust-compile-base.h" #include "tree.h" +#include "fold-const.h" #include "stor-layout.h" namespace Rust { @@ -480,9 +480,12 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type) tree folded_capacity_expr = fold_expr (capacity_expr); - translated = Backend::array_type (element_type, folded_capacity_expr); - if (translated != error_mark_node) - translated = ctx->insert_compiled_type (translated); + // build_index_type takes the maximum index, which is one less than + // the length. + tree index_type_tree = build_index_type ( + fold_build2 (MINUS_EXPR, sizetype, folded_capacity_expr, size_one_node)); + + translated = build_array_type (element_type, index_type_tree, false); } void diff --git a/gcc/testsuite/rust/compile/const_generics_3.rs b/gcc/testsuite/rust/compile/const_generics_3.rs index 524d48d5bcf5..bd9172949846 100644 --- a/gcc/testsuite/rust/compile/const_generics_3.rs +++ b/gcc/testsuite/rust/compile/const_generics_3.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-w -frust-name-resolution-2.0" } +// { dg-additional-options "-w -frust-name-resolution-2.0 -frust-compile-until=compilation" } #[lang = "sized"] trait Sized {} diff --git a/gcc/testsuite/rust/compile/issue-3660.rs b/gcc/testsuite/rust/compile/issue-3660.rs new file mode 100644 index 000000000000..1f1c583cb5b6 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3660.rs @@ -0,0 +1,3 @@ +pub static A: [u32; 2] = [1, 2]; + +pub static B: [u8; 2] = [3, 4]; From 4713b9eb0555f9b2db711246b80fb4fbee7e0203 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 14 Jun 2025 20:34:33 +0100 Subject: [PATCH 057/161] gccrs: Fix bug in query type stopping PartialOrd There was a complex recurisve type query hierarchy here but the type was resolved so we can just do an early return here gcc/rust/ChangeLog: * typecheck/rust-type-util.cc (query_type): early return. gcc/testsuite/ChangeLog: * rust/execute/torture/basic_partial_ord1.rs: New test. * rust/execute/torture/basic_partial_ord2.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/typecheck/rust-type-util.cc | 6 +- .../execute/torture/basic_partial_ord1.rs | 176 +++++++++++++++++ .../execute/torture/basic_partial_ord2.rs | 184 ++++++++++++++++++ 3 files changed, 363 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs create mode 100644 gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc index c6c5b4bb55fa..a549449dcef0 100644 --- a/gcc/rust/typecheck/rust-type-util.cc +++ b/gcc/rust/typecheck/rust-type-util.cc @@ -40,12 +40,12 @@ query_type (HirId reference, TyTy::BaseType **result) auto &resolver = *Resolver::get (); TypeCheckContext *context = TypeCheckContext::get (); - if (context->query_in_progress (reference)) - return false; - if (context->lookup_type (reference, result)) return true; + if (context->query_in_progress (reference)) + return false; + context->insert_query (reference); std::pair enum_candidiate diff --git a/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs b/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs new file mode 100644 index 000000000000..efb825bc908c --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs @@ -0,0 +1,176 @@ +/* { dg-output "less\r*" }*/ +mod core { + mod option { + pub enum Option { + None, + Some(T), + } + } + + mod marker { + #[lang = "phantom_data"] + pub struct PhantomData; + + #[lang = "structural_peq"] + pub trait StructuralPartialEq {} + + #[lang = "structural_teq"] + pub trait StructuralEq {} + + #[lang = "sized"] + pub trait Sized {} + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + pub enum Ordering { + Less = -1, + Equal = 0, + Greater = 1, + } + + #[lang = "eq"] + pub trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + pub trait Eq: PartialEq { + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + pub trait PartialOrd: PartialEq { + fn partial_cmp(&self, other: &Rhs) -> Option; + + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) | Option::Some(Ordering::Equal) => true, + _ => false, + } + } + + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) | Option::Some(Ordering::Equal) => true, + _ => false, + } + } + } + + pub trait Ord: Eq + PartialOrd { + fn cmp(&self, other: &Self) -> Ordering; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::option::Option; + +// Needed impls for primitives +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self < *other { + Option::Some(Ordering::Less) + } else if *self > *other { + Option::Some(Ordering::Greater) + } else { + Option::Some(Ordering::Equal) + } + } +} + +impl Eq for i32 {} +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self < *other { + Ordering::Less + } else if *self > *other { + Ordering::Greater + } else { + Ordering::Equal + } + } +} + +// Manual impl for struct Bar +struct Bar { + a: i32, + b: i32, +} + +impl PartialEq for Bar { + fn eq(&self, other: &Self) -> bool { + self.a.eq(&other.a) && self.b.eq(&other.b) + } +} + +impl Eq for Bar {} + +impl PartialOrd for Bar { + fn partial_cmp(&self, other: &Self) -> Option { + match self.a.partial_cmp(&other.a) { + Option::Some(Ordering::Equal) => self.b.partial_cmp(&other.b), + ord => ord, + } + } +} + +impl Ord for Bar { + fn cmp(&self, other: &Self) -> Ordering { + match self.a.cmp(&other.a) { + Ordering::Equal => self.b.cmp(&other.b), + ord => ord, + } + } +} + +// External print shim +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let x = Bar { a: 1, b: 2 }; + let y = Bar { a: 1, b: 3 }; + + match x.partial_cmp(&y) { + Option::Some(Ordering::Less) => print("less"), + Option::Some(Ordering::Greater) => print("greater"), + Option::Some(Ordering::Equal) => print("equal"), + _ => print("none"), + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs b/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs new file mode 100644 index 000000000000..b8c367255fa1 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs @@ -0,0 +1,184 @@ +/* { dg-output "<><=>=\r*" } */ +/* { dg-options "-w" } */ +mod core { + mod option { + pub enum Option { + None, + Some(T), + } + } + + mod marker { + #[lang = "phantom_data"] + pub struct PhantomData; + + #[lang = "structural_peq"] + pub trait StructuralPartialEq {} + + #[lang = "structural_teq"] + pub trait StructuralEq {} + + #[lang = "sized"] + pub trait Sized {} + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + pub enum Ordering { + Less = -1, + Equal = 0, + Greater = 1, + } + + #[lang = "eq"] + pub trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + pub trait Eq: PartialEq { + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + pub trait PartialOrd: PartialEq { + fn partial_cmp(&self, other: &Rhs) -> Option; + + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) | Option::Some(Ordering::Equal) => true, + _ => false, + } + } + + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) | Option::Some(Ordering::Equal) => true, + _ => false, + } + } + } + + pub trait Ord: Eq + PartialOrd { + fn cmp(&self, other: &Self) -> Ordering; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::option::Option; + +// Needed impls for primitives +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self < *other { + Option::Some(Ordering::Less) + } else if *self > *other { + Option::Some(Ordering::Greater) + } else { + Option::Some(Ordering::Equal) + } + } +} + +impl Eq for i32 {} +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self < *other { + Ordering::Less + } else if *self > *other { + Ordering::Greater + } else { + Ordering::Equal + } + } +} + +// Manual impl for struct Bar +struct Bar { + a: i32, + b: i32, +} + +impl PartialEq for Bar { + fn eq(&self, other: &Self) -> bool { + self.a.eq(&other.a) && self.b.eq(&other.b) + } +} + +impl Eq for Bar {} + +impl PartialOrd for Bar { + fn partial_cmp(&self, other: &Self) -> Option { + match self.a.partial_cmp(&other.a) { + Option::Some(Ordering::Equal) => self.b.partial_cmp(&other.b), + ord => ord, + } + } +} + +impl Ord for Bar { + fn cmp(&self, other: &Self) -> Ordering { + match self.a.cmp(&other.a) { + Ordering::Equal => self.b.cmp(&other.b), + ord => ord, + } + } +} + +// External print shim +extern "C" { + fn printf(s: *const i8); +} + +fn print(s: &str) { + unsafe { + printf(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let a = Bar { a: 1, b: 2 }; + let b = Bar { a: 1, b: 3 }; + let c = Bar { a: 1, b: 2 }; + + if a < b { + print("<"); + } + if b > a { + print(">"); + } + if a <= c { + print("<="); + } + if b >= c { + print(">="); + } + + 0 +} From e38b2748e6bd27ef4593f55bb6ed802da5d657b2 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 27 May 2025 13:25:01 +0200 Subject: [PATCH 058/161] rib: Add all kinds of Ribs to pretty-printing gcc/rust/ChangeLog: * resolve/rust-rib.h: Add missing switch cases. --- gcc/rust/resolve/rust-rib.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h index 62189f7a6d10..140c991e2ab5 100644 --- a/gcc/rust/resolve/rust-rib.h +++ b/gcc/rust/resolve/rust-rib.h @@ -216,9 +216,13 @@ class Rib return "Forward type param ban"; case Rib::Kind::ConstParamType: return "Const Param Type"; - default: - rust_unreachable (); + case Kind::Prelude: + return "Prelude"; + case Kind::Generics: + return "Generics"; } + + rust_unreachable (); } Rib (Kind kind); From 69b3ebc42d1562ec28bf2412d1ce9d37215ed0a5 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 7 Mar 2025 14:31:38 +0000 Subject: [PATCH 059/161] derive: chore: Add missing override qualifiers gcc/rust/ChangeLog: * expand/rust-derive-clone.h: Add missing override qualifiers to DeriveVisitor methods. * expand/rust-derive-copy.h: Likewise. * expand/rust-derive-eq.h: Likewise. * expand/rust-derive-hash.h: Likewise. * expand/rust-derive-partial-eq.h: Likewise. --- gcc/rust/expand/rust-derive-clone.h | 10 +++++----- gcc/rust/expand/rust-derive-copy.h | 8 ++++---- gcc/rust/expand/rust-derive-eq.h | 10 +++++----- gcc/rust/expand/rust-derive-hash.h | 10 +++++----- gcc/rust/expand/rust-derive-partial-eq.h | 10 +++++----- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/gcc/rust/expand/rust-derive-clone.h b/gcc/rust/expand/rust-derive-clone.h index 61224ba527b6..a3320c77f306 100644 --- a/gcc/rust/expand/rust-derive-clone.h +++ b/gcc/rust/expand/rust-derive-clone.h @@ -29,7 +29,7 @@ class DeriveClone : DeriveVisitor public: DeriveClone (location_t loc); - std::unique_ptr go (Item &item); + std::unique_ptr go (Item &item); private: std::unique_ptr expanded; @@ -80,10 +80,10 @@ class DeriveClone : DeriveVisitor MatchCase clone_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive-copy.h b/gcc/rust/expand/rust-derive-copy.h index 71972ebf6f72..664a8e0e290b 100644 --- a/gcc/rust/expand/rust-derive-copy.h +++ b/gcc/rust/expand/rust-derive-copy.h @@ -44,10 +44,10 @@ class DeriveCopy : DeriveVisitor copy_impl (std::string name, const std::vector> &type_generics); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive-eq.h b/gcc/rust/expand/rust-derive-eq.h index 17af52653dea..fb187ccb02cb 100644 --- a/gcc/rust/expand/rust-derive-eq.h +++ b/gcc/rust/expand/rust-derive-eq.h @@ -31,7 +31,7 @@ class DeriveEq : DeriveVisitor public: DeriveEq (location_t loc); - std::vector> go (Item &item); + std::vector> go (Item &item); private: std::vector> expanded; @@ -70,10 +70,10 @@ class DeriveEq : DeriveVisitor */ std::unique_ptr assert_type_is_eq (std::unique_ptr &&type); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive-hash.h b/gcc/rust/expand/rust-derive-hash.h index 02b0bee10a5d..67170d0c8a01 100644 --- a/gcc/rust/expand/rust-derive-hash.h +++ b/gcc/rust/expand/rust-derive-hash.h @@ -29,7 +29,7 @@ class DeriveHash : DeriveVisitor public: DeriveHash (location_t loc); - std::unique_ptr go (Item &item); + std::unique_ptr go (Item &item); private: std::unique_ptr expanded; @@ -49,10 +49,10 @@ class DeriveHash : DeriveVisitor MatchCase match_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive-partial-eq.h b/gcc/rust/expand/rust-derive-partial-eq.h index ac963a63c8aa..12d793d81bca 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.h +++ b/gcc/rust/expand/rust-derive-partial-eq.h @@ -30,7 +30,7 @@ class DerivePartialEq : DeriveVisitor public: DerivePartialEq (location_t loc); - std::vector> go (Item &item); + std::vector> go (Item &item); private: std::vector> expanded; @@ -73,10 +73,10 @@ class DerivePartialEq : DeriveVisitor MatchCase match_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST From 8bf353b99366880772822062ea29623f7f2a03e6 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 7 Mar 2025 17:08:34 +0000 Subject: [PATCH 060/161] derive(Ord, PartialOrd): Add base for deriving them. gcc/rust/ChangeLog: * Make-lang.in: Compile it. * expand/rust-derive.cc (DeriveVisitor::derive): Call them. * expand/rust-derive-ord.cc: New file. * expand/rust-derive-ord.h: New file. --- gcc/rust/Make-lang.in | 1 + gcc/rust/expand/rust-derive-ord.cc | 172 +++++++++++++++++++++++++++++ gcc/rust/expand/rust-derive-ord.h | 74 +++++++++++++ gcc/rust/expand/rust-derive.cc | 6 +- 4 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 gcc/rust/expand/rust-derive-ord.cc create mode 100644 gcc/rust/expand/rust-derive-ord.h diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 399271a3bc74..c919b3d43e25 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -100,6 +100,7 @@ GRS_OBJS = \ rust/rust-derive-default.o \ rust/rust-derive-partial-eq.o \ rust/rust-derive-eq.o \ + rust/rust-derive-ord.o \ rust/rust-derive-hash.o \ rust/rust-proc-macro.o \ rust/rust-macro-invoc-lexer.o \ diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc new file mode 100644 index 000000000000..7eaaa474d1bf --- /dev/null +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -0,0 +1,172 @@ +// Copyright (C) 2025 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 +// . + +#include "rust-derive-ord.h" +#include "rust-ast-dump.h" +#include "rust-ast.h" +#include "rust-derive.h" +#include "rust-item.h" + +namespace Rust { +namespace AST { + +DeriveOrd::DeriveOrd (Ordering ordering, location_t loc) + : DeriveVisitor (loc), ordering (ordering) +{} + +std::unique_ptr +DeriveOrd::go (Item &item) +{ + item.accept_vis (*this); + + AST::Dump::debug (*expanded); + + return std::move (expanded); +} + +std::unique_ptr +DeriveOrd::cmp_impl ( + std::unique_ptr &&fn_block, Identifier type_name, + const std::vector> &type_generics) +{ + auto fn = cmp_fn (std::move (fn_block), type_name); + + auto trait = ordering == Ordering::Partial ? "PartialOrd" : "Ord"; + auto trait_path = builder.type_path ({"core", "cmp", trait}, true); + + auto trait_bound + = builder.trait_bound (builder.type_path ({"core", "cmp", trait}, true)); + + auto trait_items = vec (std::move (fn)); + + auto cmp_generics + = setup_impl_generics (type_name.as_string (), type_generics, + std::move (trait_bound)); + + return builder.trait_impl (trait_path, std::move (cmp_generics.self_type), + std::move (trait_items), + std::move (cmp_generics.impl)); +} + +std::unique_ptr +DeriveOrd::cmp_fn (std::unique_ptr &&block, Identifier type_name) +{ + // Ordering + auto return_type = builder.type_path ({"core", "cmp", "Ordering"}, true); + + // In the case of PartialOrd, we return an Option + if (ordering == Ordering::Partial) + { + auto generic = GenericArg::create_type (ptrify (return_type)); + + auto generic_seg = builder.type_path_segment_generic ( + "Option", GenericArgs ({}, {generic}, {}, loc)); + auto core = builder.type_path_segment ("core"); + auto option = builder.type_path_segment ("option"); + + return_type + = builder.type_path (vec (std::move (core), std::move (option), + std::move (generic_seg)), + true); + } + + // &self, other: &Self + auto params = vec ( + builder.self_ref_param (), + builder.function_param (builder.identifier_pattern ("other"), + builder.reference_type (ptrify ( + builder.type_path (type_name.as_string ()))))); + + auto function_name = ordering == Ordering::Partial ? "partial_cmp" : "cmp"; + + return builder.function (function_name, std::move (params), + ptrify (return_type), std::move (block)); +} +std::unique_ptr +recursive_match () +{ + return nullptr; +} + +// we need to do a recursive match expression for all of the fields used in a +// struct so for something like struct Foo { a: i32, b: i32, c: i32 } we must +// first compare each `a` field, then `b`, then `c`, like this: +// +// match cmp_fn(self., other.) { +// Ordering::Equal => , +// cmp => cmp, +// } +// +// and the recurse will be the exact same expression, on the next field. so that +// our result looks like this: +// +// match cmp_fn(self.a, other.a) { +// Ordering::Equal => match cmp_fn(self.b, other.b) { +// Ordering::Equal =>cmp_fn(self.c, other.c), +// cmp => cmp, +// } +// cmp => cmp, +// } +// +// the last field comparison needs not to be a match but just the function call. +// this is going to be annoying lol +void +DeriveOrd::visit_struct (StructStruct &item) +{ + // FIXME: Put cmp_fn call inside cmp_impl, pass a block to cmp_impl instead - + // this avoids repeating the same parameter twice (the type name) + expanded = cmp_impl (builder.block (), item.get_identifier (), + item.get_generic_params ()); +} + +// same as structs, but for each field index instead of each field name - +// straightforward once we have `visit_struct` working +void +DeriveOrd::visit_tuple (TupleStruct &item) +{} + +// for enums, we need to generate a match for each of the enum's variant that +// contains data and then do the same thing as visit_struct or visit_enum. if +// the two aren't the same variant, then compare the two discriminant values for +// all the dataless enum variants and in the general case. +// +// so for enum Foo { A(i32, i32), B, C } we need to do the following +// +// match (self, other) { +// (A(self_0, self_1), A(other_0, other_1)) => { +// match cmp_fn(self_0, other_0) { +// Ordering::Equal => cmp_fn(self_1, other_1), +// cmp => cmp, +// }, +// _ => cmp_fn(discr_value(self), discr_value(other)) +// } +void +DeriveOrd::visit_enum (Enum &item) +{} + +void +DeriveOrd::visit_union (Union &item) +{ + auto trait_name = ordering == Ordering::Total ? "Ord" : "PartialOrd"; + + rust_error_at (item.get_locus (), "derive(%s) cannot be used on unions", + trait_name); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/expand/rust-derive-ord.h b/gcc/rust/expand/rust-derive-ord.h new file mode 100644 index 000000000000..fae13261e7c4 --- /dev/null +++ b/gcc/rust/expand/rust-derive-ord.h @@ -0,0 +1,74 @@ +// Copyright (C) 2025 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 +// . + +#ifndef RUST_DERIVE_ORD_H +#define RUST_DERIVE_ORD_H + +#include "rust-ast.h" +#include "rust-derive.h" + +namespace Rust { +namespace AST { + +/** + * DeriveOrd is a bit special as the expansion of both `PartialOrd` and `Ord` + * is extremely similar. The only difference is that `PartialOrd` concerns + * partial-ordering, and thus its main method returns an `Option`, + * while `Ord` concerns total-ordering, and its main method returns an + * `Ordering`. Otherwise, the expansion logic is the same, so we factor both + * derives into one. + */ +class DeriveOrd : public DeriveVisitor +{ +public: + enum class Ordering + { + Total, + Partial + }; + + DeriveOrd (Ordering ordering, location_t loc); + + std::unique_ptr go (Item &item); + +private: + std::unique_ptr expanded; + + Ordering ordering; + + /** + * Create the recursive matching structure used when implementing the + * comparison function on multiple sub items (fields, tuple indexes...) */ + std::unique_ptr recursive_match (); + + std::unique_ptr + cmp_impl (std::unique_ptr &&fn_block, Identifier type_name, + const std::vector> &type_generics); + std::unique_ptr cmp_fn (std::unique_ptr &&block, + Identifier type_name); + + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DERIVE_ORD_H diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc index 0e8a67c17a34..69081db29ada 100644 --- a/gcc/rust/expand/rust-derive.cc +++ b/gcc/rust/expand/rust-derive.cc @@ -22,6 +22,7 @@ #include "rust-derive-debug.h" #include "rust-derive-default.h" #include "rust-derive-eq.h" +#include "rust-derive-ord.h" #include "rust-derive-partial-eq.h" #include "rust-derive-hash.h" @@ -59,10 +60,11 @@ DeriveVisitor::derive (Item &item, const Attribute &attr, case BuiltinMacro::Hash: return vec (DeriveHash (loc).go (item)); case BuiltinMacro::Ord: + return vec (DeriveOrd (DeriveOrd::Ordering::Total, loc).go (item)); case BuiltinMacro::PartialOrd: + return vec (DeriveOrd (DeriveOrd::Ordering::Partial, loc).go (item)); default: - rust_sorry_at (loc, "unimplemented builtin derive macro"); - return {}; + rust_unreachable (); }; } From 80ba197d06385f6476b617b8ee715cc38d3cc86f Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 9 Apr 2025 11:18:06 +0200 Subject: [PATCH 061/161] derive: Add const generics when deriving impls gcc/rust/ChangeLog: * ast/rust-ast-builder.cc (Builder::new_const_param): New function. * ast/rust-ast-builder.h (vec): New function for creating 3 elts vector. * expand/rust-derive.cc: Use the new_const_param builder. * ast/rust-path.h: Add get_default_value() method. --- gcc/rust/ast/rust-ast-builder.cc | 10 ++++++++++ gcc/rust/ast/rust-ast-builder.h | 16 ++++++++++++++++ gcc/rust/ast/rust-path.h | 7 +++++++ gcc/rust/expand/rust-derive.cc | 30 +++++++++++++++--------------- 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index fbc8f273d812..7e017d53629c 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -554,6 +554,16 @@ Builder::new_lifetime_param (LifetimeParam ¶m) return std::unique_ptr (p); } +std::unique_ptr +Builder::new_const_param (ConstGenericParam ¶m) const +{ + return std::make_unique (param.get_name (), + param.get_type ().clone_type (), + param.get_default_value (), + param.get_outer_attrs (), + param.get_locus ()); +} + std::unique_ptr Builder::new_type_param ( TypeParam ¶m, std::vector> extra_bounds) diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index a5115b685ace..d1b6529599f7 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -51,6 +51,19 @@ vec (std::unique_ptr &&t1, std::unique_ptr &&t2) return v; } +template +std::vector> +vec (std::unique_ptr &&t1, std::unique_ptr &&t2, std::unique_ptr &&t3) +{ + auto v = std::vector> (); + + v.emplace_back (std::move (t1)); + v.emplace_back (std::move (t2)); + v.emplace_back (std::move (t3)); + + return v; +} + /* Pointer-ify something */ template static std::unique_ptr @@ -294,6 +307,9 @@ class Builder static std::unique_ptr new_lifetime_param (LifetimeParam ¶m); + std::unique_ptr + new_const_param (ConstGenericParam ¶m) const; + static std::unique_ptr new_type_param ( TypeParam ¶m, std::vector> extra_trait_bounds = {}); diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 11f72480fe07..de895a2f8384 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -391,6 +391,13 @@ class ConstGenericParam : public GenericParam return default_value.value (); } + tl::optional &get_default_value () { return default_value; } + + const tl::optional &get_default_value () const + { + return default_value; + } + std::string as_string () const override; void accept_vis (ASTVisitor &vis) override; diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc index 69081db29ada..8b4327ac3650 100644 --- a/gcc/rust/expand/rust-derive.cc +++ b/gcc/rust/expand/rust-derive.cc @@ -81,8 +81,7 @@ DeriveVisitor::setup_impl_generics ( { switch (generic->get_kind ()) { - case GenericParam::Kind::Lifetime: - { + case GenericParam::Kind::Lifetime: { LifetimeParam &lifetime_param = (LifetimeParam &) *generic.get (); Lifetime l = builder.new_lifetime (lifetime_param.get_lifetime ()); @@ -94,8 +93,7 @@ DeriveVisitor::setup_impl_generics ( } break; - case GenericParam::Kind::Type: - { + case GenericParam::Kind::Type: { TypeParam &type_param = (TypeParam &) *generic.get (); std::unique_ptr associated_type = builder.single_type_path ( @@ -108,7 +106,8 @@ DeriveVisitor::setup_impl_generics ( std::vector> extra_bounds; if (extra_bound) - extra_bounds.emplace_back (std::move (*extra_bound)); + extra_bounds.emplace_back ( + extra_bound.value ()->clone_type_param_bound ()); auto impl_type_param = builder.new_type_param (type_param, std::move (extra_bounds)); @@ -117,18 +116,19 @@ DeriveVisitor::setup_impl_generics ( } break; - case GenericParam::Kind::Const: - { - rust_unreachable (); + case GenericParam::Kind::Const: { + ConstGenericParam &const_param + = (ConstGenericParam &) *generic.get (); - // TODO - // const ConstGenericParam *const_param - // = (const ConstGenericParam *) generic.get (); - // std::unique_ptr const_expr = nullptr; + std::unique_ptr associated_type + = builder.single_type_path (const_param.get_name ().as_string ()); - // GenericArg type_arg - // = GenericArg::create_const (std::move (const_expr)); - // generic_args.push_back (std::move (type_arg)); + GenericArg type_arg + = GenericArg::create_type (std::move (associated_type)); + generic_args.push_back (std::move (type_arg)); + + auto impl_const_param = builder.new_const_param (const_param); + impl_generics.push_back (std::move (impl_const_param)); } break; } From cb881a14e697df8e8aa163fa33a1380ddfd93c79 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 18 Apr 2025 18:18:06 +0200 Subject: [PATCH 062/161] builder: Add match_case() function and new block() one gcc/rust/ChangeLog: * ast/rust-ast-builder.cc (Builder::block): New function. (Builder::match_case): Likewise. * ast/rust-ast-builder.h: Declare them. --- gcc/rust/ast/rust-ast-builder.cc | 13 ++++++++++++- gcc/rust/ast/rust-ast-builder.h | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 7e017d53629c..2692684a9bac 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -331,6 +331,12 @@ Builder::block () const return block (std::move (stmts)); } +std::unique_ptr +Builder::block (std::unique_ptr &&tail_expr) const +{ + return block (tl::nullopt, std::move (tail_expr)); +} + std::unique_ptr Builder::block (std::vector> &&stmts, std::unique_ptr &&tail_expr) const @@ -490,9 +496,14 @@ MatchCase Builder::match_case (std::unique_ptr &&pattern, std::unique_ptr &&expr) { - return MatchCase (match_arm (std::move (pattern)), std::move (expr)); + return match_case (match_arm (std::move (pattern)), std::move (expr)); } +MatchCase +Builder::match_case (MatchArm &&arm, std::unique_ptr &&expr) +{ + return MatchCase (std::move (arm), std::move (expr)); +} std::unique_ptr Builder::loop (std::vector> &&stmts) { diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index d1b6529599f7..cb922dba6589 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -130,6 +130,9 @@ class Builder /* Create an empty block */ std::unique_ptr block () const; + /* Create a block with just a tail expression */ + std::unique_ptr block (std::unique_ptr &&tail_expr) const; + /* Create an early return expression with an optional expression */ std::unique_ptr return_expr (std::unique_ptr &&to_return = nullptr); @@ -285,6 +288,7 @@ class Builder MatchArm match_arm (std::unique_ptr &&pattern); MatchCase match_case (std::unique_ptr &&pattern, std::unique_ptr &&expr); + MatchCase match_case (MatchArm &&arm, std::unique_ptr &&expr); /* Create a loop expression */ std::unique_ptr loop (std::vector> &&stmts); From 4699bbd38dba27ee5fcf7e76ca4df9ac89dcbf43 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 18 Apr 2025 18:18:40 +0200 Subject: [PATCH 063/161] derive: Add common comparison derive class gcc/rust/ChangeLog: * expand/rust-derive-cmp-common.cc: New file. * expand/rust-derive-cmp-common.h: New file. * Make-lang.in: Compile them. --- gcc/rust/Make-lang.in | 1 + gcc/rust/expand/rust-derive-cmp-common.cc | 69 +++++++++++++++++++++++ gcc/rust/expand/rust-derive-cmp-common.h | 50 ++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 gcc/rust/expand/rust-derive-cmp-common.cc create mode 100644 gcc/rust/expand/rust-derive-cmp-common.h diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index c919b3d43e25..85614b3e2246 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -94,6 +94,7 @@ GRS_OBJS = \ rust/rust-ast-builder.o \ rust/rust-ast-builder-type.o \ rust/rust-derive.o \ + rust/rust-derive-cmp-common.o \ rust/rust-derive-clone.o \ rust/rust-derive-copy.o \ rust/rust-derive-debug.o \ diff --git a/gcc/rust/expand/rust-derive-cmp-common.cc b/gcc/rust/expand/rust-derive-cmp-common.cc new file mode 100644 index 000000000000..ba260c532911 --- /dev/null +++ b/gcc/rust/expand/rust-derive-cmp-common.cc @@ -0,0 +1,69 @@ +// Copyright (C) 2025 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 +// . + +#include "rust-derive-cmp-common.h" +#include "rust-ast-builder.h" + +namespace Rust { +namespace AST { + +SelfOther +SelfOther::index (Builder builder, int idx) +{ + return SelfOther{ + builder.tuple_idx ("self", idx), + builder.tuple_idx ("other", idx), + }; +} + +std::vector +SelfOther::indexes (Builder builder, int limit) +{ + std::vector vec; + + for (int i = 0; i < limit; i++) + { + vec.emplace_back (SelfOther::index (builder, i)); + } + + return vec; +} + +SelfOther +SelfOther::field (Builder builder, const std::string &field_name) +{ + return SelfOther{ + builder.field_access (builder.identifier ("self"), field_name), + builder.field_access (builder.identifier ("other"), field_name), + }; +} + +std::vector +SelfOther::fields (Builder builder, const std::vector &fields) +{ + std::vector vec; + + for (auto &field : fields) + vec.emplace_back ( + SelfOther::field (builder, field.get_field_name ().as_string ())); + + return vec; +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/expand/rust-derive-cmp-common.h b/gcc/rust/expand/rust-derive-cmp-common.h new file mode 100644 index 000000000000..2353c71292f3 --- /dev/null +++ b/gcc/rust/expand/rust-derive-cmp-common.h @@ -0,0 +1,50 @@ +// Copyright (C) 2025 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 +// . + +#ifndef RUST_DERIVE_CMP_COMMON_H +#define RUST_DERIVE_CMP_COMMON_H + +#include "rust-ast.h" +#include "rust-ast-builder.h" + +namespace Rust { +namespace AST { + +/** + * A pair of two expressions from each instance being compared. E.g. this + * could be `self.0` and `other.0`, or `self.field` and `other.field` + */ +struct SelfOther +{ + std::unique_ptr self_expr; + std::unique_ptr other_expr; + + /* Create a and an expression */ + static SelfOther index (Builder builder, int idx); + static std::vector indexes (Builder builder, int limit); + + /* Create a and an expression */ + static SelfOther field (Builder builder, const std::string &field_name); + static std::vector fields (Builder builder, + const std::vector &fields); +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DERIVE_CMP_COMMON_H From 7c47bc786093d086f6b3cda88e19c96fd4860911 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 18 Apr 2025 18:19:18 +0200 Subject: [PATCH 064/161] derive(PartialEq): Use that common class gcc/rust/ChangeLog: * expand/rust-derive-partial-eq.cc (DerivePartialEq::tuple_indexes): Remove. (DerivePartialEq::field_acccesses): Remove. (DerivePartialEq::visit_tuple): Use new API. (DerivePartialEq::visit_struct): Likewise. * expand/rust-derive-partial-eq.h: Remove declarations. --- gcc/rust/expand/rust-derive-partial-eq.cc | 22 ++-------------------- gcc/rust/expand/rust-derive-partial-eq.h | 14 +------------- 2 files changed, 3 insertions(+), 33 deletions(-) diff --git a/gcc/rust/expand/rust-derive-partial-eq.cc b/gcc/rust/expand/rust-derive-partial-eq.cc index 22368bcb2b01..13a09fce059d 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.cc +++ b/gcc/rust/expand/rust-derive-partial-eq.cc @@ -83,24 +83,6 @@ DerivePartialEq::eq_fn (std::unique_ptr &&cmp_expression, std::move (block)); } -DerivePartialEq::SelfOther -DerivePartialEq::tuple_indexes (int idx) -{ - return SelfOther{ - builder.tuple_idx ("self", idx), - builder.tuple_idx ("other", idx), - }; -} - -DerivePartialEq::SelfOther -DerivePartialEq::field_acccesses (const std::string &field_name) -{ - return SelfOther{ - builder.field_access (builder.identifier ("self"), field_name), - builder.field_access (builder.identifier ("other"), field_name), - }; -} - std::unique_ptr DerivePartialEq::build_eq_expression ( std::vector &&field_expressions) @@ -137,7 +119,7 @@ DerivePartialEq::visit_tuple (TupleStruct &item) auto fields = std::vector (); for (size_t idx = 0; idx < item.get_fields ().size (); idx++) - fields.emplace_back (tuple_indexes (idx)); + fields.emplace_back (SelfOther::index (builder, idx)); auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name); @@ -153,7 +135,7 @@ DerivePartialEq::visit_struct (StructStruct &item) for (auto &field : item.get_fields ()) fields.emplace_back ( - field_acccesses (field.get_field_name ().as_string ())); + SelfOther::field (builder, field.get_field_name ().as_string ())); auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name); diff --git a/gcc/rust/expand/rust-derive-partial-eq.h b/gcc/rust/expand/rust-derive-partial-eq.h index 12d793d81bca..fdfe4dacb85a 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.h +++ b/gcc/rust/expand/rust-derive-partial-eq.h @@ -21,6 +21,7 @@ #include "rust-derive.h" #include "rust-path.h" +#include "rust-derive-cmp-common.h" namespace Rust { namespace AST { @@ -46,19 +47,6 @@ class DerivePartialEq : DeriveVisitor std::unique_ptr eq_fn (std::unique_ptr &&cmp_expression, std::string type_name); - /** - * A pair of two expressions from each instance being compared. E.g. this - * could be `self.0` and `other.0`, or `self.field` and `other.field` - */ - struct SelfOther - { - std::unique_ptr self_expr; - std::unique_ptr other_expr; - }; - - SelfOther tuple_indexes (int idx); - SelfOther field_acccesses (const std::string &field_name); - /** * Build a suite of equality arithmetic expressions chained together by a * boolean AND operator From c8001dc46b80999ecda3bbf2c4372f3d8be49ebf Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 18 Apr 2025 18:19:31 +0200 Subject: [PATCH 065/161] derive(Ord, PartialOrd): Implement proper recursive match logic gcc/rust/ChangeLog: * expand/rust-derive-ord.cc (DeriveOrd::make_cmp_arms): New function. (is_last): Likewise. (recursive_match): Likewise. (DeriveOrd::recursive_match): Likewise. (DeriveOrd::visit_struct): Add proper implementation. (DeriveOrd::visit_union): Likewise. * expand/rust-derive-ord.h: Declare these new functions. --- gcc/rust/expand/rust-derive-ord.cc | 90 +++++++++++++++++++++++++++--- gcc/rust/expand/rust-derive-ord.h | 37 +++++++++++- 2 files changed, 116 insertions(+), 11 deletions(-) diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc index 7eaaa474d1bf..2403e9c2a33d 100644 --- a/gcc/rust/expand/rust-derive-ord.cc +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -92,15 +92,85 @@ DeriveOrd::cmp_fn (std::unique_ptr &&block, Identifier type_name) builder.reference_type (ptrify ( builder.type_path (type_name.as_string ()))))); - auto function_name = ordering == Ordering::Partial ? "partial_cmp" : "cmp"; + auto function_name = fn (ordering); return builder.function (function_name, std::move (params), ptrify (return_type), std::move (block)); } + +std::pair +DeriveOrd::make_cmp_arms () +{ + // All comparison results other than Ordering::Equal + auto non_equal = builder.identifier_pattern (DeriveOrd::not_equal); + + std::unique_ptr equal = ptrify ( + builder.path_in_expression ({"core", "cmp", "Ordering", "Equal"}, true)); + + // We need to wrap the pattern in Option::Some if we are doing total ordering + if (ordering == Ordering::Total) + { + auto pattern_items = std::unique_ptr ( + new TupleStructItemsNoRange (vec (std::move (equal)))); + + equal + = std::make_unique (builder.path_in_expression ( + LangItem::Kind::OPTION_SOME), + std::move (pattern_items)); + } + + return {builder.match_arm (std::move (equal)), + builder.match_arm (std::move (non_equal))}; +} + +template +inline bool +is_last (T &elt, std::vector &vec) +{ + rust_assert (!vec.empty ()); + + return &elt == &vec.back (); +} + std::unique_ptr -recursive_match () +DeriveOrd::recursive_match (std::vector &&members) { - return nullptr; + std::unique_ptr final_expr = nullptr; + + for (auto it = members.rbegin (); it != members.rend (); it++) + { + auto &member = *it; + + auto cmp_fn_path = builder.path_in_expression ( + {"core", "cmp", trait (ordering), fn (ordering)}, true); + + auto cmp_call = builder.call (ptrify (cmp_fn_path), + vec (std::move (member.self_expr), + std::move (member.other_expr))); + + // For the last member (so the first iterator), we just create a call + // expression + if (it == members.rbegin ()) + { + final_expr = std::move (cmp_call); + continue; + } + + // If we aren't dealing with the last member, then we need to wrap all of + // that in a big match expression and keep going + auto match_arms = make_cmp_arms (); + + auto match_cases + = {builder.match_case (std::move (match_arms.first), + std::move (final_expr)), + builder.match_case (std::move (match_arms.second), + builder.identifier (DeriveOrd::not_equal))}; + + final_expr + = builder.match (std::move (cmp_call), std::move (match_cases)); + } + + return final_expr; } // we need to do a recursive match expression for all of the fields used in a @@ -128,10 +198,12 @@ recursive_match () void DeriveOrd::visit_struct (StructStruct &item) { - // FIXME: Put cmp_fn call inside cmp_impl, pass a block to cmp_impl instead - - // this avoids repeating the same parameter twice (the type name) - expanded = cmp_impl (builder.block (), item.get_identifier (), - item.get_generic_params ()); + auto fields = SelfOther::fields (builder, item.get_fields ()); + + auto match_expr = recursive_match (std::move (fields)); + + expanded = cmp_impl (builder.block (std::move (match_expr)), + item.get_identifier (), item.get_generic_params ()); } // same as structs, but for each field index instead of each field name - @@ -162,10 +234,10 @@ DeriveOrd::visit_enum (Enum &item) void DeriveOrd::visit_union (Union &item) { - auto trait_name = ordering == Ordering::Total ? "Ord" : "PartialOrd"; + auto trait_name = trait (ordering); rust_error_at (item.get_locus (), "derive(%s) cannot be used on unions", - trait_name); + trait_name.c_str ()); } } // namespace AST diff --git a/gcc/rust/expand/rust-derive-ord.h b/gcc/rust/expand/rust-derive-ord.h index fae13261e7c4..047ebfb0c01c 100644 --- a/gcc/rust/expand/rust-derive-ord.h +++ b/gcc/rust/expand/rust-derive-ord.h @@ -20,6 +20,7 @@ #define RUST_DERIVE_ORD_H #include "rust-ast.h" +#include "rust-derive-cmp-common.h" #include "rust-derive.h" namespace Rust { @@ -42,6 +43,22 @@ class DeriveOrd : public DeriveVisitor Partial }; + std::string fn (Ordering ordering) + { + if (ordering == Ordering::Total) + return "cmp"; + else + return "partial_cmp"; + } + + std::string trait (Ordering ordering) + { + if (ordering == Ordering::Total) + return "Ord"; + else + return "PartialOrd"; + } + DeriveOrd (Ordering ordering, location_t loc); std::unique_ptr go (Item &item); @@ -51,10 +68,26 @@ class DeriveOrd : public DeriveVisitor Ordering ordering; + /* Identifier patterns for the non-equal match arms */ + constexpr static const char *not_equal = "non_eq"; + /** * Create the recursive matching structure used when implementing the - * comparison function on multiple sub items (fields, tuple indexes...) */ - std::unique_ptr recursive_match (); + * comparison function on multiple sub items (fields, tuple indexes...) + */ + std::unique_ptr recursive_match (std::vector &&members); + + /** + * Make the match arms for one inner match in a comparison function block. + * This returns the "equal" match arm and the "rest" match arm, so something + * like `Ordering::Equal` and `non_eq` in the following match expression: + * + * match cmp(...) { + * Ordering::Equal => match cmp(...) { ... } + * non_eq => non_eq, + * } + */ + std::pair make_cmp_arms (); std::unique_ptr cmp_impl (std::unique_ptr &&fn_block, Identifier type_name, From a1a39a7d124798495d286738f04b44b311e5f65f Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 18 Apr 2025 18:30:19 +0200 Subject: [PATCH 066/161] derive(PartialEq): chore: Refactor using new SelfOther APIs gcc/rust/ChangeLog: * expand/rust-derive-cmp-common.cc (SelfOther::indexes): Fix formatting. (SelfOther::fields): Make iterator const. * expand/rust-derive-cmp-common.h (struct SelfOther): New declaration for indexes. * expand/rust-derive-partial-eq.cc (DerivePartialEq::visit_tuple): Use the new API. (DerivePartialEq::visit_struct): Likewise. --- gcc/rust/expand/rust-derive-cmp-common.cc | 10 ++++------ gcc/rust/expand/rust-derive-cmp-common.h | 3 ++- gcc/rust/expand/rust-derive-partial-eq.cc | 11 ++--------- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/gcc/rust/expand/rust-derive-cmp-common.cc b/gcc/rust/expand/rust-derive-cmp-common.cc index ba260c532911..752f7ce47780 100644 --- a/gcc/rust/expand/rust-derive-cmp-common.cc +++ b/gcc/rust/expand/rust-derive-cmp-common.cc @@ -32,14 +32,12 @@ SelfOther::index (Builder builder, int idx) } std::vector -SelfOther::indexes (Builder builder, int limit) +SelfOther::indexes (Builder builder, const std::vector &fields) { std::vector vec; - for (int i = 0; i < limit; i++) - { - vec.emplace_back (SelfOther::index (builder, i)); - } + for (size_t i = 0; i < fields.size (); i++) + vec.emplace_back (SelfOther::index (builder, i)); return vec; } @@ -58,7 +56,7 @@ SelfOther::fields (Builder builder, const std::vector &fields) { std::vector vec; - for (auto &field : fields) + for (const auto &field : fields) vec.emplace_back ( SelfOther::field (builder, field.get_field_name ().as_string ())); diff --git a/gcc/rust/expand/rust-derive-cmp-common.h b/gcc/rust/expand/rust-derive-cmp-common.h index 2353c71292f3..bb7ae842a6fc 100644 --- a/gcc/rust/expand/rust-derive-cmp-common.h +++ b/gcc/rust/expand/rust-derive-cmp-common.h @@ -36,7 +36,8 @@ struct SelfOther /* Create a and an expression */ static SelfOther index (Builder builder, int idx); - static std::vector indexes (Builder builder, int limit); + static std::vector indexes (Builder builder, + const std::vector &fields); /* Create a and an expression */ static SelfOther field (Builder builder, const std::string &field_name); diff --git a/gcc/rust/expand/rust-derive-partial-eq.cc b/gcc/rust/expand/rust-derive-partial-eq.cc index 13a09fce059d..1f2fa35b284e 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.cc +++ b/gcc/rust/expand/rust-derive-partial-eq.cc @@ -116,10 +116,7 @@ void DerivePartialEq::visit_tuple (TupleStruct &item) { auto type_name = item.get_struct_name ().as_string (); - auto fields = std::vector (); - - for (size_t idx = 0; idx < item.get_fields ().size (); idx++) - fields.emplace_back (SelfOther::index (builder, idx)); + auto fields = SelfOther::indexes (builder, item.get_fields ()); auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name); @@ -131,11 +128,7 @@ void DerivePartialEq::visit_struct (StructStruct &item) { auto type_name = item.get_struct_name ().as_string (); - auto fields = std::vector (); - - for (auto &field : item.get_fields ()) - fields.emplace_back ( - SelfOther::field (builder, field.get_field_name ().as_string ())); + auto fields = SelfOther::fields (builder, item.get_fields ()); auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name); From 2c0520611f116f0328486d291cc304d2747c3c9b Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 18 Apr 2025 18:30:46 +0200 Subject: [PATCH 067/161] derive(Ord, PartialOrd): Handle tuples properly gcc/rust/ChangeLog: * expand/rust-derive-ord.cc (is_last): Remove. (DeriveOrd::visit_tuple): Fix implementation. --- gcc/rust/expand/rust-derive-ord.cc | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc index 2403e9c2a33d..e39c6b44ca46 100644 --- a/gcc/rust/expand/rust-derive-ord.cc +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -123,15 +123,6 @@ DeriveOrd::make_cmp_arms () builder.match_arm (std::move (non_equal))}; } -template -inline bool -is_last (T &elt, std::vector &vec) -{ - rust_assert (!vec.empty ()); - - return &elt == &vec.back (); -} - std::unique_ptr DeriveOrd::recursive_match (std::vector &&members) { @@ -210,7 +201,14 @@ DeriveOrd::visit_struct (StructStruct &item) // straightforward once we have `visit_struct` working void DeriveOrd::visit_tuple (TupleStruct &item) -{} +{ + auto fields = SelfOther::indexes (builder, item.get_fields ()); + + auto match_expr = recursive_match (std::move (fields)); + + expanded = cmp_impl (builder.block (std::move (match_expr)), + item.get_identifier (), item.get_generic_params ()); +} // for enums, we need to generate a match for each of the enum's variant that // contains data and then do the same thing as visit_struct or visit_enum. if From a9b48cde1578c540b17ff15cbcb406cad456248b Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 22 Apr 2025 20:02:47 +0200 Subject: [PATCH 068/161] builder: Add Builder::discriminant_value gcc/rust/ChangeLog: * ast/rust-ast-builder.cc (Builder::discriminant_value): New function. * ast/rust-ast-builder.h: Declare it. --- gcc/rust/ast/rust-ast-builder.cc | 10 ++++++++++ gcc/rust/ast/rust-ast-builder.h | 17 ++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 2692684a9bac..914b321279f5 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -542,6 +542,16 @@ Builder::generic_type_param ( std::vector ()); } +std::unique_ptr +Builder::discriminant_value (std::string binding_name, std::string instance) +{ + auto intrinsic = ptrify ( + path_in_expression ({"core", "intrinsics", "discriminant_value"}, true)); + + return let (identifier_pattern (binding_name), nullptr, + call (std::move (intrinsic), identifier (instance))); +} + std::unique_ptr Builder::new_type (Type &type) { diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index cb922dba6589..36c3bc0ce901 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -24,6 +24,7 @@ #include "rust-ast.h" #include "rust-item.h" #include "rust-operators.h" +#include namespace Rust { namespace AST { @@ -306,6 +307,14 @@ class Builder std::vector> &&bounds, std::unique_ptr &&type = nullptr); + /** + * Create a let statement with the discriminant value of a given enum + * instance. This helper exists since it is a common operation in a lot of the + * derive implementations, and it sucks to repeat all the steps every time. + */ + std::unique_ptr discriminant_value (std::string binding_name, + std::string instance = "self"); + static std::unique_ptr new_type (Type &type); static std::unique_ptr @@ -323,10 +332,12 @@ class Builder static GenericArgs new_generic_args (GenericArgs &args); private: - /** - * Location of the generated AST nodes - */ + /* Location of the generated AST nodes */ location_t loc; + + /* Some constexpr helpers for some of the builders */ + static constexpr std::initializer_list discriminant_value_path + = {"core", "intrinsics", "discriminant_value"}; }; } // namespace AST From f8d0221522ec7af1f73d74898d4f54fc16ab8fe6 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 22 Apr 2025 20:02:56 +0200 Subject: [PATCH 069/161] derive(Hash): Use new Builder API gcc/rust/ChangeLog: * expand/rust-derive-hash.cc (DeriveHash::visit_enum): Use new APIs. --- gcc/rust/expand/rust-derive-hash.cc | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/gcc/rust/expand/rust-derive-hash.cc b/gcc/rust/expand/rust-derive-hash.cc index 0c9b0f7b1057..94aede2fe030 100644 --- a/gcc/rust/expand/rust-derive-hash.cc +++ b/gcc/rust/expand/rust-derive-hash.cc @@ -231,14 +231,7 @@ DeriveHash::visit_enum (Enum &item) auto cases = std::vector (); auto type_name = item.get_identifier ().as_string (); - auto intrinsic = ptrify ( - builder.path_in_expression ({"core", "intrinsics", "discriminant_value"}, - true)); - - auto let_discr - = builder.let (builder.identifier_pattern (DeriveHash::discr), nullptr, - builder.call (std::move (intrinsic), - builder.identifier ("self"))); + auto let_discr = builder.discriminant_value (DeriveHash::discr); auto discr_hash = builder.statementify ( hash_call (builder.ref (builder.identifier (DeriveHash::discr)))); From dae220cad6da9fc4b6591d6dd4c990399e4c042e Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 22 Apr 2025 20:03:16 +0200 Subject: [PATCH 070/161] derive(Ord): Add handling for ordering of discriminant values gcc/rust/ChangeLog: * expand/rust-derive-ord.cc (DeriveOrd::cmp_call): New function. (DeriveOrd::recursive_match): Use it. (DeriveOrd::visit_enum): Likewise. * expand/rust-derive-ord.h: Declare it. --- gcc/rust/expand/rust-derive-ord.cc | 68 +++++++++++++++++++++++++----- gcc/rust/expand/rust-derive-ord.h | 16 ++++++- 2 files changed, 73 insertions(+), 11 deletions(-) diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc index e39c6b44ca46..1f39c94d87bb 100644 --- a/gcc/rust/expand/rust-derive-ord.cc +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -39,6 +39,17 @@ DeriveOrd::go (Item &item) return std::move (expanded); } +std::unique_ptr +DeriveOrd::cmp_call (std::unique_ptr &&self_expr, + std::unique_ptr &&other_expr) +{ + auto cmp_fn_path = builder.path_in_expression ( + {"core", "cmp", trait (ordering), fn (ordering)}, true); + + return builder.call (ptrify (cmp_fn_path), + vec (std::move (self_expr), std::move (other_expr))); +} + std::unique_ptr DeriveOrd::cmp_impl ( std::unique_ptr &&fn_block, Identifier type_name, @@ -132,18 +143,14 @@ DeriveOrd::recursive_match (std::vector &&members) { auto &member = *it; - auto cmp_fn_path = builder.path_in_expression ( - {"core", "cmp", trait (ordering), fn (ordering)}, true); - - auto cmp_call = builder.call (ptrify (cmp_fn_path), - vec (std::move (member.self_expr), - std::move (member.other_expr))); + auto call = cmp_call (std::move (member.self_expr), + std::move (member.other_expr)); // For the last member (so the first iterator), we just create a call // expression if (it == members.rbegin ()) { - final_expr = std::move (cmp_call); + final_expr = std::move (call); continue; } @@ -157,8 +164,7 @@ DeriveOrd::recursive_match (std::vector &&members) builder.match_case (std::move (match_arms.second), builder.identifier (DeriveOrd::not_equal))}; - final_expr - = builder.match (std::move (cmp_call), std::move (match_cases)); + final_expr = builder.match (std::move (call), std::move (match_cases)); } return final_expr; @@ -227,7 +233,49 @@ DeriveOrd::visit_tuple (TupleStruct &item) // } void DeriveOrd::visit_enum (Enum &item) -{} +{ + auto cases = std::vector (); + auto type_name = item.get_identifier ().as_string (); + + auto let_sd = builder.discriminant_value (DeriveOrd::self_discr, "self"); + auto other_sd = builder.discriminant_value (DeriveOrd::other_discr, "other"); + + auto discr_cmp = cmp_call (builder.identifier (DeriveOrd::self_discr), + builder.identifier (DeriveOrd::other_discr)); + + for (auto &variant : item.get_variants ()) + { + auto variant_path + = builder.variant_path (type_name, + variant->get_identifier ().as_string ()); + + switch (variant->get_enum_item_kind ()) + { + case EnumItem::Kind::Tuple: + case EnumItem::Kind::Struct: + case EnumItem::Kind::Identifier: + case EnumItem::Kind::Discriminant: + // We don't need to do anything for these, as they are handled by the + // discriminant value comparison + break; + } + } + + // Add the last case which compares the discriminant values in case `self` and + // `other` are actually different variants of the enum + cases.emplace_back ( + builder.match_case (builder.wildcard (), std::move (discr_cmp))); + + auto match + = builder.match (builder.tuple (vec (builder.identifier ("self"), + builder.identifier ("other"))), + std::move (cases)); + + expanded + = cmp_impl (builder.block (vec (std::move (let_sd), std::move (other_sd)), + std::move (match)), + type_name, item.get_generic_params ()); +} void DeriveOrd::visit_union (Union &item) diff --git a/gcc/rust/expand/rust-derive-ord.h b/gcc/rust/expand/rust-derive-ord.h index 047ebfb0c01c..a360dd26d974 100644 --- a/gcc/rust/expand/rust-derive-ord.h +++ b/gcc/rust/expand/rust-derive-ord.h @@ -69,7 +69,9 @@ class DeriveOrd : public DeriveVisitor Ordering ordering; /* Identifier patterns for the non-equal match arms */ - constexpr static const char *not_equal = "non_eq"; + constexpr static const char *not_equal = "#non_eq"; + constexpr static const char *self_discr = "#self_discr"; + constexpr static const char *other_discr = "#other_discr"; /** * Create the recursive matching structure used when implementing the @@ -89,6 +91,18 @@ class DeriveOrd : public DeriveVisitor */ std::pair make_cmp_arms (); + MatchCase match_enum_tuple (PathInExpression variant_path, + const EnumItemTuple &variant); + MatchCase match_enum_struct (PathInExpression variant_path, + const EnumItemStruct &variant); + + /** + * Generate a call to the proper trait function, based on the ordering, in + * order to compare two given expressions + */ + std::unique_ptr cmp_call (std::unique_ptr &&self_expr, + std::unique_ptr &&other_expr); + std::unique_ptr cmp_impl (std::unique_ptr &&fn_block, Identifier type_name, const std::vector> &type_generics); From bf5f1853c2c47ae9aace0444c9cbfe62618ffdd1 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 22 Apr 2025 22:18:01 +0200 Subject: [PATCH 071/161] ast-builder: Make location public gcc/rust/ChangeLog: * ast/rust-ast-builder.h: Put `loc` member in public. --- gcc/rust/ast/rust-ast-builder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index 36c3bc0ce901..fa3c95ce4fdf 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -331,10 +331,10 @@ class Builder static GenericArgs new_generic_args (GenericArgs &args); -private: /* Location of the generated AST nodes */ location_t loc; +private: /* Some constexpr helpers for some of the builders */ static constexpr std::initializer_list discriminant_value_path = {"core", "intrinsics", "discriminant_value"}; From 8868af735849d5f9b2168b2e384cab57b4808ea1 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 22 Apr 2025 22:17:18 +0200 Subject: [PATCH 072/161] derive-cmp: Add EnumMatchBuilder class gcc/rust/ChangeLog: * expand/rust-derive-cmp-common.h (class EnumMatchBuilder): New helper class. * expand/rust-derive-cmp-common.cc (EnumMatchBuilder::tuple): New function. (EnumMatchBuilder::strukt): New function. --- gcc/rust/expand/rust-derive-cmp-common.cc | 115 ++++++++++++++++++++++ gcc/rust/expand/rust-derive-cmp-common.h | 44 +++++++++ 2 files changed, 159 insertions(+) diff --git a/gcc/rust/expand/rust-derive-cmp-common.cc b/gcc/rust/expand/rust-derive-cmp-common.cc index 752f7ce47780..83913784e971 100644 --- a/gcc/rust/expand/rust-derive-cmp-common.cc +++ b/gcc/rust/expand/rust-derive-cmp-common.cc @@ -18,6 +18,7 @@ #include "rust-derive-cmp-common.h" #include "rust-ast-builder.h" +#include "rust-item.h" namespace Rust { namespace AST { @@ -63,5 +64,119 @@ SelfOther::fields (Builder builder, const std::vector &fields) return vec; } +MatchCase +EnumMatchBuilder::tuple (EnumItem &variant_raw) +{ + auto &variant = static_cast (variant_raw); + + auto self_patterns = std::vector> (); + auto other_patterns = std::vector> (); + + auto self_other_exprs = std::vector (); + + for (size_t i = 0; i < variant.get_tuple_fields ().size (); i++) + { + // The patterns we're creating for each field are `self_` and + // `other_` where `i` is the index of the field. It doesn't actually + // matter what we use, as long as it's ordered, unique, and that we can + // reuse it in the match case's return expression to check that they are + // equal. + + auto self_pattern_str = "__self_" + std::to_string (i); + auto other_pattern_str = "__other_" + std::to_string (i); + + self_patterns.emplace_back ( + builder.identifier_pattern (self_pattern_str)); + other_patterns.emplace_back ( + builder.identifier_pattern (other_pattern_str)); + + self_other_exprs.emplace_back (SelfOther{ + builder.identifier (self_pattern_str), + builder.identifier (other_pattern_str), + }); + } + + auto self_pattern_items = std::unique_ptr ( + new TupleStructItemsNoRange (std::move (self_patterns))); + auto other_pattern_items = std::unique_ptr ( + new TupleStructItemsNoRange (std::move (other_patterns))); + + auto self_pattern = std::unique_ptr ( + new ReferencePattern (std::unique_ptr (new TupleStructPattern ( + variant_path, std::move (self_pattern_items))), + false, false, builder.loc)); + auto other_pattern = std::unique_ptr ( + new ReferencePattern (std::unique_ptr (new TupleStructPattern ( + variant_path, std::move (other_pattern_items))), + false, false, builder.loc)); + + auto tuple_items = std::make_unique ( + vec (std::move (self_pattern), std::move (other_pattern))); + + auto pattern + = std::make_unique (std::move (tuple_items), builder.loc); + + auto expr = fn (std::move (self_other_exprs)); + + return builder.match_case (std::move (pattern), std::move (expr)); +} + +MatchCase +EnumMatchBuilder::strukt (EnumItem &variant_raw) +{ + auto &variant = static_cast (variant_raw); + + auto self_fields = std::vector> (); + auto other_fields = std::vector> (); + + auto self_other_exprs = std::vector (); + + for (auto &field : variant.get_struct_fields ()) + { + // The patterns we're creating for each field are `self_` and + // `other_` where `field` is the name of the field. It doesn't + // actually matter what we use, as long as it's ordered, unique, and that + // we can reuse it in the match case's return expression to check that + // they are equal. + + auto field_name = field.get_field_name ().as_string (); + + auto self_pattern_str = "__self_" + field_name; + auto other_pattern_str = "__other_" + field_name; + + self_fields.emplace_back (builder.struct_pattern_ident_pattern ( + field_name, builder.identifier_pattern (self_pattern_str))); + other_fields.emplace_back (builder.struct_pattern_ident_pattern ( + field_name, builder.identifier_pattern (other_pattern_str))); + + self_other_exprs.emplace_back (SelfOther{ + builder.identifier (self_pattern_str), + builder.identifier (other_pattern_str), + }); + } + + auto self_elts = StructPatternElements (std::move (self_fields)); + auto other_elts = StructPatternElements (std::move (other_fields)); + + auto self_pattern = std::unique_ptr ( + new ReferencePattern (std::unique_ptr (new StructPattern ( + variant_path, builder.loc, std::move (self_elts))), + false, false, builder.loc)); + auto other_pattern = std::unique_ptr ( + new ReferencePattern (std::unique_ptr (new StructPattern ( + variant_path, builder.loc, std::move (other_elts))), + false, false, builder.loc)); + + auto tuple_items = std::make_unique ( + vec (std::move (self_pattern), std::move (other_pattern))); + + auto pattern + = std::make_unique (std::move (tuple_items), builder.loc); + + auto expr = fn (std::move (self_other_exprs)); + + return builder.match_case (std::move (pattern), std::move (expr)); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/expand/rust-derive-cmp-common.h b/gcc/rust/expand/rust-derive-cmp-common.h index bb7ae842a6fc..5902bb03b036 100644 --- a/gcc/rust/expand/rust-derive-cmp-common.h +++ b/gcc/rust/expand/rust-derive-cmp-common.h @@ -21,6 +21,8 @@ #include "rust-ast.h" #include "rust-ast-builder.h" +#include "rust-item.h" +#include "rust-path.h" namespace Rust { namespace AST { @@ -45,6 +47,48 @@ struct SelfOther const std::vector &fields); }; +/** + * Builder for common match cases used when comparing two enum instances. This + * builder takes care of creating the unique patterns for the `self` instance + * and `other` instance, as well as the entire `MatchCase` required for building + * a proper comparision expression for an implementation of a comparision trait + * for an enum type. The functions take a lambda to use when creating the + * expression of the generated `MatchCase`. + */ +class EnumMatchBuilder +{ +public: + /** + * The type of functions to call when creating the resulting expression in the + * generated `MatchCase` + */ + using ExprFn + = std::function (std::vector &&)>; + + EnumMatchBuilder (PathInExpression &variant_path, ExprFn fn, Builder &builder) + : variant_path (variant_path), fn (fn), builder (builder) + {} + + /** + * Generate a `MatchCase` for an enum tuple variant + * + * (&Enum::Tuple(self0, self1), &Enum::Tuple(other0, other1)) => + */ + MatchCase tuple (EnumItem &variant); + + /** + * Generate a `MatchCase` for an enum struct variant + * + * (&Enum::Struct { a: self_a }, &Enum::Struct { a: other_a }) => + */ + MatchCase strukt (EnumItem &variant); + +private: + PathInExpression &variant_path; + ExprFn fn; + Builder &builder; +}; + } // namespace AST } // namespace Rust From 190234a259d09938a28da7a9a76b310b60677283 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 22 Apr 2025 22:21:01 +0200 Subject: [PATCH 073/161] derive(PartialEq): Implement proper discriminant comparison And use the new EnumMatchBuilder class to do so. gcc/rust/ChangeLog: * expand/rust-derive-partial-eq.cc (DerivePartialEq::eq_fn): Change signature. (DerivePartialEq::visit_tuple): Use new eq_fn API. (DerivePartialEq::visit_struct): Likewise. (DerivePartialEq::visit_enum): Implement proper discriminant comparison. * expand/rust-derive-partial-eq.h: Change eq_fn signature. gcc/testsuite/ChangeLog: * rust/execute/torture/derive-partialeq2.rs: Add declaration for discriminant_value. --- gcc/rust/expand/rust-derive-partial-eq.cc | 54 +++++++++++-------- gcc/rust/expand/rust-derive-partial-eq.h | 5 +- .../rust/execute/torture/derive-partialeq2.rs | 14 +++++ 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/gcc/rust/expand/rust-derive-partial-eq.cc b/gcc/rust/expand/rust-derive-partial-eq.cc index 1f2fa35b284e..ea6a995c4f10 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.cc +++ b/gcc/rust/expand/rust-derive-partial-eq.cc @@ -64,11 +64,9 @@ DerivePartialEq::partialeq_impls ( } std::unique_ptr -DerivePartialEq::eq_fn (std::unique_ptr &&cmp_expression, +DerivePartialEq::eq_fn (std::unique_ptr &&block, std::string type_name) { - auto block = builder.block (tl::nullopt, std::move (cmp_expression)); - auto self_type = std::unique_ptr (new TypePath (builder.type_path ("Self"))); @@ -118,7 +116,8 @@ DerivePartialEq::visit_tuple (TupleStruct &item) auto type_name = item.get_struct_name ().as_string (); auto fields = SelfOther::indexes (builder, item.get_fields ()); - auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name); + auto fn = eq_fn (builder.block (build_eq_expression (std::move (fields))), + type_name); expanded = partialeq_impls (std::move (fn), type_name, item.get_generic_params ()); @@ -130,7 +129,8 @@ DerivePartialEq::visit_struct (StructStruct &item) auto type_name = item.get_struct_name ().as_string (); auto fields = SelfOther::fields (builder, item.get_fields ()); - auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name); + auto fn = eq_fn (builder.block (build_eq_expression (std::move (fields))), + type_name); expanded = partialeq_impls (std::move (fn), type_name, item.get_generic_params ()); @@ -270,46 +270,58 @@ DerivePartialEq::visit_enum (Enum &item) auto cases = std::vector (); auto type_name = item.get_identifier ().as_string (); + auto eq_expr_fn = [this] (std::vector &&fields) { + return build_eq_expression (std::move (fields)); + }; + + auto let_sd + = builder.discriminant_value (DerivePartialEq::self_discr, "self"); + auto let_od + = builder.discriminant_value (DerivePartialEq::other_discr, "other"); + + auto discr_cmp + = builder.comparison_expr (builder.identifier (DerivePartialEq::self_discr), + builder.identifier ( + DerivePartialEq::other_discr), + ComparisonOperator::EQUAL); + for (auto &variant : item.get_variants ()) { auto variant_path = builder.variant_path (type_name, variant->get_identifier ().as_string ()); + auto enum_builder = EnumMatchBuilder (variant_path, eq_expr_fn, builder); + switch (variant->get_enum_item_kind ()) { - case EnumItem::Kind::Identifier: - case EnumItem::Kind::Discriminant: - cases.emplace_back (match_enum_identifier (variant_path, variant)); - break; case EnumItem::Kind::Tuple: - cases.emplace_back ( - match_enum_tuple (variant_path, - static_cast (*variant))); + cases.emplace_back (enum_builder.tuple (*variant)); break; case EnumItem::Kind::Struct: - cases.emplace_back ( - match_enum_struct (variant_path, - static_cast (*variant))); + cases.emplace_back (enum_builder.strukt (*variant)); + break; + case EnumItem::Kind::Identifier: + case EnumItem::Kind::Discriminant: + // We don't need to do anything for these, as they are handled by the + // discriminant value comparison break; } } - // NOTE: Mention using discriminant_value and skipping that last case, and - // instead skipping all identifiers/discriminant enum items and returning - // `true` in the wildcard case - // In case the two instances of `Self` don't have the same discriminant, // automatically return false. cases.emplace_back ( - builder.match_case (builder.wildcard (), builder.literal_bool (false))); + builder.match_case (builder.wildcard (), std::move (discr_cmp))); auto match = builder.match (builder.tuple (vec (builder.identifier ("self"), builder.identifier ("other"))), std::move (cases)); - auto fn = eq_fn (std::move (match), type_name); + auto fn = eq_fn (builder.block (vec (std::move (let_sd), std::move (let_od)), + std::move (match)), + type_name); expanded = partialeq_impls (std::move (fn), type_name, item.get_generic_params ()); diff --git a/gcc/rust/expand/rust-derive-partial-eq.h b/gcc/rust/expand/rust-derive-partial-eq.h index fdfe4dacb85a..7985414c2528 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.h +++ b/gcc/rust/expand/rust-derive-partial-eq.h @@ -44,7 +44,7 @@ class DerivePartialEq : DeriveVisitor std::unique_ptr &&eq_fn, std::string name, const std::vector> &type_generics); - std::unique_ptr eq_fn (std::unique_ptr &&cmp_expression, + std::unique_ptr eq_fn (std::unique_ptr &&block, std::string type_name); /** @@ -61,6 +61,9 @@ class DerivePartialEq : DeriveVisitor MatchCase match_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant); + constexpr static const char *self_discr = "#self_discr"; + constexpr static const char *other_discr = "#other_discr"; + virtual void visit_struct (StructStruct &item) override; virtual void visit_tuple (TupleStruct &item) override; virtual void visit_enum (Enum &item) override; diff --git a/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs b/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs index 70ed7dcd93d9..e316017753a2 100644 --- a/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs +++ b/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs @@ -2,6 +2,20 @@ #![feature(intrinsics)] +pub mod core { + pub mod intrinsics { + #[lang = "discriminant_kind"] + pub trait DiscriminantKind { + #[lang = "discriminant_type"] + type Discriminant; + } + + extern "rust-intrinsic" { + pub fn discriminant_value(v: &T) -> ::Discriminant; + } + } +} + #[lang = "sized"] trait Sized {} From 7f255d54f3829db1c9718e7624f8d6e4ba907f35 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 22 Apr 2025 22:22:29 +0200 Subject: [PATCH 074/161] [NEEDS TEST] derive(Ord, PartialOrd): Finish implementation gcc/rust/ChangeLog: * expand/rust-derive-ord.cc: Finish implementation for enums. * expand/rust-derive-ord.h: Likewise. --- gcc/rust/expand/rust-derive-ord.cc | 24 ++++++++++++++++++------ gcc/rust/expand/rust-derive-ord.h | 5 ----- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc index 1f39c94d87bb..68a9c53ab1c9 100644 --- a/gcc/rust/expand/rust-derive-ord.cc +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -17,10 +17,11 @@ // . #include "rust-derive-ord.h" -#include "rust-ast-dump.h" #include "rust-ast.h" +#include "rust-derive-cmp-common.h" #include "rust-derive.h" #include "rust-item.h" +#include "rust-system.h" namespace Rust { namespace AST { @@ -34,8 +35,6 @@ DeriveOrd::go (Item &item) { item.accept_vis (*this); - AST::Dump::debug (*expanded); - return std::move (expanded); } @@ -234,25 +233,38 @@ DeriveOrd::visit_tuple (TupleStruct &item) void DeriveOrd::visit_enum (Enum &item) { + // NOTE: We can factor this even further with DerivePartialEq, but this is + // getting out of scope for this PR surely + auto cases = std::vector (); auto type_name = item.get_identifier ().as_string (); auto let_sd = builder.discriminant_value (DeriveOrd::self_discr, "self"); - auto other_sd = builder.discriminant_value (DeriveOrd::other_discr, "other"); + auto let_od = builder.discriminant_value (DeriveOrd::other_discr, "other"); auto discr_cmp = cmp_call (builder.identifier (DeriveOrd::self_discr), builder.identifier (DeriveOrd::other_discr)); + auto recursive_match_fn = [this] (std::vector &&fields) { + return recursive_match (std::move (fields)); + }; + for (auto &variant : item.get_variants ()) { auto variant_path = builder.variant_path (type_name, variant->get_identifier ().as_string ()); + auto enum_builder + = EnumMatchBuilder (variant_path, recursive_match_fn, builder); switch (variant->get_enum_item_kind ()) { - case EnumItem::Kind::Tuple: case EnumItem::Kind::Struct: + cases.emplace_back (enum_builder.strukt (*variant)); + break; + case EnumItem::Kind::Tuple: + cases.emplace_back (enum_builder.tuple (*variant)); + break; case EnumItem::Kind::Identifier: case EnumItem::Kind::Discriminant: // We don't need to do anything for these, as they are handled by the @@ -272,7 +284,7 @@ DeriveOrd::visit_enum (Enum &item) std::move (cases)); expanded - = cmp_impl (builder.block (vec (std::move (let_sd), std::move (other_sd)), + = cmp_impl (builder.block (vec (std::move (let_sd), std::move (let_od)), std::move (match)), type_name, item.get_generic_params ()); } diff --git a/gcc/rust/expand/rust-derive-ord.h b/gcc/rust/expand/rust-derive-ord.h index a360dd26d974..20086afe9b7f 100644 --- a/gcc/rust/expand/rust-derive-ord.h +++ b/gcc/rust/expand/rust-derive-ord.h @@ -91,11 +91,6 @@ class DeriveOrd : public DeriveVisitor */ std::pair make_cmp_arms (); - MatchCase match_enum_tuple (PathInExpression variant_path, - const EnumItemTuple &variant); - MatchCase match_enum_struct (PathInExpression variant_path, - const EnumItemStruct &variant); - /** * Generate a call to the proper trait function, based on the ordering, in * order to compare two given expressions From 3693622bea1d8c289683b9232d46919a42007840 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 23 Apr 2025 12:37:57 +0200 Subject: [PATCH 075/161] derive(Ord): Fix condition for matching on Option::Some instead gcc/rust/ChangeLog: * expand/rust-derive-ord.cc (DeriveOrd::make_cmp_arms): Fix condition. --- gcc/rust/expand/rust-derive-ord.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc index 68a9c53ab1c9..ffe269c3c0a4 100644 --- a/gcc/rust/expand/rust-derive-ord.cc +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -117,8 +117,9 @@ DeriveOrd::make_cmp_arms () std::unique_ptr equal = ptrify ( builder.path_in_expression ({"core", "cmp", "Ordering", "Equal"}, true)); - // We need to wrap the pattern in Option::Some if we are doing total ordering - if (ordering == Ordering::Total) + // We need to wrap the pattern in Option::Some if we are doing partial + // ordering + if (ordering == Ordering::Partial) { auto pattern_items = std::unique_ptr ( new TupleStructItemsNoRange (vec (std::move (equal)))); From 25c0aff47a01885e00244b44d6da5459a48949ea Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 28 Apr 2025 11:35:53 +0200 Subject: [PATCH 076/161] derive(Ord): Fix cmp call to use references instead of values gcc/rust/ChangeLog: * expand/rust-derive-ord.cc (DeriveOrd::cmp_call): Use references. --- gcc/rust/expand/rust-derive-ord.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc index ffe269c3c0a4..1623495b8b60 100644 --- a/gcc/rust/expand/rust-derive-ord.cc +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -46,7 +46,8 @@ DeriveOrd::cmp_call (std::unique_ptr &&self_expr, {"core", "cmp", trait (ordering), fn (ordering)}, true); return builder.call (ptrify (cmp_fn_path), - vec (std::move (self_expr), std::move (other_expr))); + vec (builder.ref (std::move (self_expr)), + builder.ref (std::move (other_expr)))); } std::unique_ptr From f370a7182ae30a95b7b7b7eeecddebfc15630e89 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 27 May 2025 14:23:39 +0200 Subject: [PATCH 077/161] derive(Ord): Handle unit structs properly gcc/rust/ChangeLog: * expand/rust-derive-ord.cc (DeriveOrd::make_cmp_arms): Use new make_equal function. (DeriveOrd::make_equal): New function. (DeriveOrd::recursive_match): Handle the unit struct/tuple case. * expand/rust-derive-ord.h: Declare make_equal. --- gcc/rust/expand/rust-derive-ord.cc | 31 +++++++++++++++++++++++++----- gcc/rust/expand/rust-derive-ord.h | 6 ++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc index 1623495b8b60..dfc014446fa2 100644 --- a/gcc/rust/expand/rust-derive-ord.cc +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -109,12 +109,9 @@ DeriveOrd::cmp_fn (std::unique_ptr &&block, Identifier type_name) ptrify (return_type), std::move (block)); } -std::pair -DeriveOrd::make_cmp_arms () +std::unique_ptr +DeriveOrd::make_equal () { - // All comparison results other than Ordering::Equal - auto non_equal = builder.identifier_pattern (DeriveOrd::not_equal); - std::unique_ptr equal = ptrify ( builder.path_in_expression ({"core", "cmp", "Ordering", "Equal"}, true)); @@ -131,6 +128,16 @@ DeriveOrd::make_cmp_arms () std::move (pattern_items)); } + return equal; +} + +std::pair +DeriveOrd::make_cmp_arms () +{ + // All comparison results other than Ordering::Equal + auto non_equal = builder.identifier_pattern (DeriveOrd::not_equal); + auto equal = make_equal (); + return {builder.match_arm (std::move (equal)), builder.match_arm (std::move (non_equal))}; } @@ -138,6 +145,20 @@ DeriveOrd::make_cmp_arms () std::unique_ptr DeriveOrd::recursive_match (std::vector &&members) { + if (members.empty ()) + { + std::unique_ptr value = ptrify ( + builder.path_in_expression ({"core", "cmp", "Ordering", "Equal"}, + true)); + + if (ordering == Ordering::Partial) + value = builder.call (ptrify (builder.path_in_expression ( + LangItem::Kind::OPTION_SOME)), + std::move (value)); + + return value; + } + std::unique_ptr final_expr = nullptr; for (auto it = members.rbegin (); it != members.rend (); it++) diff --git a/gcc/rust/expand/rust-derive-ord.h b/gcc/rust/expand/rust-derive-ord.h index 20086afe9b7f..90ce9c8ca6f1 100644 --- a/gcc/rust/expand/rust-derive-ord.h +++ b/gcc/rust/expand/rust-derive-ord.h @@ -79,6 +79,12 @@ class DeriveOrd : public DeriveVisitor */ std::unique_ptr recursive_match (std::vector &&members); + /** + * Create a pattern for the `Ordering::Equal` case. In the case of partial + * ordering, `Option::Some(Ordering::Equal)`. + */ + std::unique_ptr make_equal (); + /** * Make the match arms for one inner match in a comparison function block. * This returns the "equal" match arm and the "rest" match arm, so something From 5ced019206669ad2b83286577368c0352d420785 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 10 Jun 2025 15:03:03 +0200 Subject: [PATCH 078/161] derive(Ord, Eq): Use different node IDs for variant paths gcc/rust/ChangeLog: * expand/rust-derive-cmp-common.cc (EnumMatchBuilder::tuple): Create two different variant paths. (EnumMatchBuilder::strukt): Likewise. * expand/rust-derive-cmp-common.h: Change API. * expand/rust-derive-ord.cc (DeriveOrd::visit_enum): Use new EnumMatchBuilder API. * expand/rust-derive-partial-eq.cc (DerivePartialEq::visit_enum): Likewise. gcc/testsuite/ChangeLog: * rust/compile/derive_partial_ord1.rs: New test. --- gcc/rust/expand/rust-derive-cmp-common.cc | 31 +- gcc/rust/expand/rust-derive-cmp-common.h | 10 +- gcc/rust/expand/rust-derive-ord.cc | 6 +- gcc/rust/expand/rust-derive-partial-eq.cc | 8 +- .../rust/compile/derive_partial_ord1.rs | 464 ++++++++++++++++++ 5 files changed, 496 insertions(+), 23 deletions(-) create mode 100644 gcc/testsuite/rust/compile/derive_partial_ord1.rs diff --git a/gcc/rust/expand/rust-derive-cmp-common.cc b/gcc/rust/expand/rust-derive-cmp-common.cc index 83913784e971..22ca16f17729 100644 --- a/gcc/rust/expand/rust-derive-cmp-common.cc +++ b/gcc/rust/expand/rust-derive-cmp-common.cc @@ -96,6 +96,10 @@ EnumMatchBuilder::tuple (EnumItem &variant_raw) }); } + // TODO: Replace with `reconstruct()` instead of building these twice + auto self_variant_path = builder.variant_path (enum_path, variant_path); + auto other_variant_path = builder.variant_path (enum_path, variant_path); + auto self_pattern_items = std::unique_ptr ( new TupleStructItemsNoRange (std::move (self_patterns))); auto other_pattern_items = std::unique_ptr ( @@ -103,12 +107,12 @@ EnumMatchBuilder::tuple (EnumItem &variant_raw) auto self_pattern = std::unique_ptr ( new ReferencePattern (std::unique_ptr (new TupleStructPattern ( - variant_path, std::move (self_pattern_items))), - false, false, builder.loc)); - auto other_pattern = std::unique_ptr ( - new ReferencePattern (std::unique_ptr (new TupleStructPattern ( - variant_path, std::move (other_pattern_items))), + self_variant_path, std::move (self_pattern_items))), false, false, builder.loc)); + auto other_pattern = std::unique_ptr (new ReferencePattern ( + std::unique_ptr (new TupleStructPattern ( + other_variant_path, std::move (other_pattern_items))), + false, false, builder.loc)); auto tuple_items = std::make_unique ( vec (std::move (self_pattern), std::move (other_pattern))); @@ -155,16 +159,21 @@ EnumMatchBuilder::strukt (EnumItem &variant_raw) }); } + // TODO: Replace with `reconstruct()` instead of building these twice + auto self_variant_path = builder.variant_path (enum_path, variant_path); + auto other_variant_path = builder.variant_path (enum_path, variant_path); + auto self_elts = StructPatternElements (std::move (self_fields)); auto other_elts = StructPatternElements (std::move (other_fields)); - auto self_pattern = std::unique_ptr ( - new ReferencePattern (std::unique_ptr (new StructPattern ( - variant_path, builder.loc, std::move (self_elts))), - false, false, builder.loc)); + auto self_pattern = std::unique_ptr (new ReferencePattern ( + std::unique_ptr (new StructPattern (self_variant_path, builder.loc, + std::move (self_elts))), + false, false, builder.loc)); auto other_pattern = std::unique_ptr ( - new ReferencePattern (std::unique_ptr (new StructPattern ( - variant_path, builder.loc, std::move (other_elts))), + new ReferencePattern (std::unique_ptr ( + new StructPattern (other_variant_path, builder.loc, + std::move (other_elts))), false, false, builder.loc)); auto tuple_items = std::make_unique ( diff --git a/gcc/rust/expand/rust-derive-cmp-common.h b/gcc/rust/expand/rust-derive-cmp-common.h index 5902bb03b036..4efbed82aaa0 100644 --- a/gcc/rust/expand/rust-derive-cmp-common.h +++ b/gcc/rust/expand/rust-derive-cmp-common.h @@ -65,8 +65,11 @@ class EnumMatchBuilder using ExprFn = std::function (std::vector &&)>; - EnumMatchBuilder (PathInExpression &variant_path, ExprFn fn, Builder &builder) - : variant_path (variant_path), fn (fn), builder (builder) + EnumMatchBuilder (const std::string &enum_path, + const std::string &variant_path, ExprFn fn, + Builder &builder) + : enum_path (enum_path), variant_path (variant_path), fn (fn), + builder (builder) {} /** @@ -84,7 +87,8 @@ class EnumMatchBuilder MatchCase strukt (EnumItem &variant); private: - PathInExpression &variant_path; + const std::string &enum_path; + const std::string &variant_path; ExprFn fn; Builder &builder; }; diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc index dfc014446fa2..afc4b71676a1 100644 --- a/gcc/rust/expand/rust-derive-ord.cc +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -274,11 +274,9 @@ DeriveOrd::visit_enum (Enum &item) for (auto &variant : item.get_variants ()) { - auto variant_path - = builder.variant_path (type_name, - variant->get_identifier ().as_string ()); auto enum_builder - = EnumMatchBuilder (variant_path, recursive_match_fn, builder); + = EnumMatchBuilder (type_name, variant->get_identifier ().as_string (), + recursive_match_fn, builder); switch (variant->get_enum_item_kind ()) { diff --git a/gcc/rust/expand/rust-derive-partial-eq.cc b/gcc/rust/expand/rust-derive-partial-eq.cc index ea6a995c4f10..a0bf87a32ddb 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.cc +++ b/gcc/rust/expand/rust-derive-partial-eq.cc @@ -287,11 +287,9 @@ DerivePartialEq::visit_enum (Enum &item) for (auto &variant : item.get_variants ()) { - auto variant_path - = builder.variant_path (type_name, - variant->get_identifier ().as_string ()); - - auto enum_builder = EnumMatchBuilder (variant_path, eq_expr_fn, builder); + auto enum_builder + = EnumMatchBuilder (type_name, variant->get_identifier ().as_string (), + eq_expr_fn, builder); switch (variant->get_enum_item_kind ()) { diff --git a/gcc/testsuite/rust/compile/derive_partial_ord1.rs b/gcc/testsuite/rust/compile/derive_partial_ord1.rs new file mode 100644 index 000000000000..1f74b4dc9031 --- /dev/null +++ b/gcc/testsuite/rust/compile/derive_partial_ord1.rs @@ -0,0 +1,464 @@ +// { dg-additional-options "-frust-compile-until=typecheck" } + +#![feature(intrinsics)] + +mod core { + mod option { + // #[rustc_diagnostic_item = "option_type"] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Option { + /// No value + #[lang = "None"] + #[stable(feature = "rust1", since = "1.0.0")] + None, + /// Some value `T` + #[lang = "Some"] + #[stable(feature = "rust1", since = "1.0.0")] + Some(#[stable(feature = "rust1", since = "1.0.0")] T), + } + } + + mod marker { + #[lang = "phantom_data"] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct PhantomData; + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] + #[lang = "structural_peq"] + pub trait StructuralPartialEq { + // Empty. + } + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] + #[lang = "structural_teq"] + pub trait StructuralEq { + // Empty. + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[lang = "sized"] + // #[rustc_on_unimplemented( + // message = "the size for values of type `{Self}` cannot be known at compilation time", + // label = "doesn't have a size known at compile-time" + // )] + // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable + // #[rustc_specialization_trait] + pub trait Sized { + // Empty. + } + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + // #[derive(Clone, Copy, PartialEq, Debug, Hash)] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Ordering { + /// An ordering where a compared value is less than another. + #[stable(feature = "rust1", since = "1.0.0")] + Less = -1, + /// An ordering where a compared value is equal to another. + #[stable(feature = "rust1", since = "1.0.0")] + Equal = 0, + /// An ordering where a compared value is greater than another. + #[stable(feature = "rust1", since = "1.0.0")] + Greater = 1, + } + + #[lang = "eq"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = "==")] + #[doc(alias = "!=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} == {Rhs}`" + // )] + pub trait PartialEq { + /// This method tests for `self` and `other` values to be equal, and is used + /// by `==`. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + #[doc(alias = "==")] + #[doc(alias = "!=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Eq: PartialEq { + // this method is used solely by #[deriving] to assert + // that every component of a type implements #[deriving] + // itself, the current deriving infrastructure means doing this + // assertion without using a method on this trait is nearly + // impossible. + // + // This should never be implemented by hand. + #[doc(hidden)] + #[stable(feature = "rust1", since = "1.0.0")] + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = ">")] + #[doc(alias = "<")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`" + // )] + pub trait PartialOrd: PartialEq { + /// This method returns an ordering between `self` and `other` values if one exists. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = 1.0.partial_cmp(&2.0); + /// assert_eq!(result, Some(Ordering::Less)); + /// + /// let result = 1.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Equal)); + /// + /// let result = 2.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Greater)); + /// ``` + /// + /// When comparison is impossible: + /// + /// ``` + /// let result = f64::NAN.partial_cmp(&1.0); + /// assert_eq!(result, None); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn partial_cmp(&self, other: &Rhs) -> Option; + + /// This method tests less than (for `self` and `other`) and is used by the `<` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 < 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 < 1.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 <= 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 <= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less | Ordering::Equal) => true, + _ => false, + } + } + + /// This method tests greater than (for `self` and `other`) and is used by the `>` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 > 2.0; + /// assert_eq!(result, false); + /// + /// let result = 2.0 > 2.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 2.0 >= 1.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 >= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater | Ordering::Equal) => true, + _ => false, + } + } + } + + #[doc(alias = "<")] + #[doc(alias = ">")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Ord: Eq + PartialOrd { + /// This method returns an [`Ordering`] between `self` and `other`. + /// + /// By convention, `self.cmp(&other)` returns the ordering matching the expression + /// `self other` if true. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(5.cmp(&10), Ordering::Less); + /// assert_eq!(10.cmp(&5), Ordering::Greater); + /// assert_eq!(5.cmp(&5), Ordering::Equal); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(2, 1.max(2)); + /// assert_eq!(2, 2.max(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn max(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1, 1.min(2)); + /// assert_eq!(2, 2.min(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn min(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Restrict a value to a certain interval. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// # Panics + /// + /// Panics if `min > max`. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp)] + /// + /// assert!((-3).clamp(-2, 1) == -2); + /// assert!(0.clamp(-2, 1) == 0); + /// assert!(2.clamp(-2, 1) == 1); + /// ``` + #[must_use] + #[unstable(feature = "clamp", issue = "44095")] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: Sized, + { + if self < min { + min + } else if self > max { + max + } else { + self + } + } + } + } + + pub mod intrinsics { + #[lang = "discriminant_kind"] + pub trait DiscriminantKind { + #[lang = "discriminant_type"] + type Discriminant; + } + + extern "rust-intrinsic" { + pub fn discriminant_value(v: &T) -> ::Discriminant; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::marker::Sized; +use core::option::Option; + +// for comparing discriminant_value +impl PartialEq for isize { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +// for comparing discriminant_value +impl PartialOrd for isize { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self > *other { + Ordering::Greater + } else if *self < *other { + Ordering::Less + } else { + Ordering::Equal + } + } +} + +impl Eq for i32 {} + +#[derive(PartialEq, PartialOrd)] +enum Foo { + A, + B(i32, i32, i32), + C { inner: i32, outer: i32 }, +} + +#[derive(Ord, PartialOrd, PartialEq, Eq)] +struct Bar { + a: i32, +} + +#[derive(Ord, PartialOrd, PartialEq, Eq)] +struct BarFull { + a: i32, + b: i32, + c: i32, + d: i32, +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() { + let a = Foo::A; + let b = Foo::B(15, 14, 13); + + match a.partial_cmp(&b) { + Option::Some(Ordering::Less) => print("less"), + Option::Some(Ordering::Greater) => print("greater"), + Option::Some(Ordering::Equal) => print("equal"), + _ => print("uuuuh woops lol"), + } +} From c201a32cf171aaf6eb6163925ec13a55981c5dc6 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 11 Jun 2025 11:12:55 +0200 Subject: [PATCH 079/161] chore: Fix formatting gcc/rust/ChangeLog: * expand/rust-derive.cc: Fix formatting after fork update. --- gcc/rust/expand/rust-derive.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc index 8b4327ac3650..55147df26f24 100644 --- a/gcc/rust/expand/rust-derive.cc +++ b/gcc/rust/expand/rust-derive.cc @@ -81,7 +81,8 @@ DeriveVisitor::setup_impl_generics ( { switch (generic->get_kind ()) { - case GenericParam::Kind::Lifetime: { + case GenericParam::Kind::Lifetime: + { LifetimeParam &lifetime_param = (LifetimeParam &) *generic.get (); Lifetime l = builder.new_lifetime (lifetime_param.get_lifetime ()); @@ -93,7 +94,8 @@ DeriveVisitor::setup_impl_generics ( } break; - case GenericParam::Kind::Type: { + case GenericParam::Kind::Type: + { TypeParam &type_param = (TypeParam &) *generic.get (); std::unique_ptr associated_type = builder.single_type_path ( @@ -116,7 +118,8 @@ DeriveVisitor::setup_impl_generics ( } break; - case GenericParam::Kind::Const: { + case GenericParam::Kind::Const: + { ConstGenericParam &const_param = (ConstGenericParam &) *generic.get (); From f486b307b21069a4eabd7a043f9d5adb1678039d Mon Sep 17 00:00:00 2001 From: Zhi Heng Date: Sun, 15 Jun 2025 15:07:54 +0800 Subject: [PATCH 080/161] gccrs: Improve HIR dumps for patterns gcc/rust/ChangeLog: * hir/rust-hir-dump.cc: Change pattern dumps to use visit_field. Signed-off-by: Yap Zhi Heng --- gcc/rust/hir/rust-hir-dump.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index 38079c76f9a9..098b3c1e2660 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -2196,7 +2196,7 @@ Dump::visit (StructPatternFieldIdentPat &e) auto oa = e.get_outer_attrs (); do_outer_attrs (oa); put_field ("ident", e.get_identifier ().as_string ()); - put_field ("ident_pattern", e.get_pattern ().as_string ()); + visit_field ("ident_pattern", e.get_pattern ()); end ("StructPatternFieldIdentPat"); } @@ -2314,7 +2314,7 @@ Dump::visit (LetStmt &e) auto oa = e.get_outer_attrs (); do_outer_attrs (oa); - put_field ("variable_pattern", e.get_pattern ().as_string ()); + visit_field ("variable_pattern", e.get_pattern ()); if (e.has_type ()) visit_field ("type", e.get_type ()); From bb7cb582ede7829132110afbf6e692d8c5fd8bfc Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 9 May 2025 14:37:55 -0400 Subject: [PATCH 081/161] nr2.0: Adjust lookup of associated items gcc/rust/ChangeLog: * resolve/rust-default-resolver.cc (DefaultResolver::visit): Adjust scoping of trait definitions and their generic parameters. * resolve/rust-forever-stack.hxx (ForeverStack::get): Prevent lookups inside TraitOrImpl ribs. (ForeverStack::resolve_segments): Prevent lookups of the first segment inside TraitOrImpl ribs. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove entries. Signed-off-by: Owen Avery --- gcc/rust/resolve/rust-default-resolver.cc | 26 +++++++++++++++++++---- gcc/rust/resolve/rust-forever-stack.hxx | 12 +++++++++++ gcc/testsuite/rust/compile/nr2/exclude | 2 -- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 01906cf0a32d..5f5dd09ca6f1 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -113,15 +113,33 @@ DefaultResolver::visit (AST::IfLetExpr &expr) void DefaultResolver::visit (AST::Trait &trait) { - auto inner_fn_1 - = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); }; + visit_outer_attrs (trait); + visit (trait.get_visibility ()); + visit_inner_attrs (trait); + + auto inner_fn_1 = [this, &trait] () { + for (auto &item : trait.get_trait_items ()) + visit (item); + }; auto inner_fn_2 = [this, &trait, &inner_fn_1] () { + visit (trait.get_implicit_self ()); + for (auto &generic : trait.get_generic_params ()) + visit (generic); + if (trait.has_where_clause ()) + visit (trait.get_where_clause ()); + for (auto &bound : trait.get_type_param_bounds ()) + visit (bound); + + ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn_1); + }; + + auto inner_fn_3 = [this, &trait, &inner_fn_2] () { ctx.canonical_ctx.scope (trait.get_node_id (), trait.get_identifier (), - std::move (inner_fn_1)); + std::move (inner_fn_2)); }; - ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn_2, + ctx.scoped (Rib::Kind::Generics, trait.get_node_id (), inner_fn_3, trait.get_identifier () /* FIXME: Is that valid?*/); } diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 8721386a2402..582e53b16022 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -297,6 +297,10 @@ ForeverStack::get (Node &start, const Identifier &name) // TODO: Can we improve the API? have `reverse_iter` return an optional? reverse_iter (start, [&resolved_definition, &name] (Node ¤t) { + // we can't reference associated types/functions like this + if (current.rib.kind == Rib::Kind::TraitOrImpl) + return KeepGoing::Yes; + auto candidate = current.rib.get (name.as_string ()); return candidate.map_or ( @@ -549,6 +553,14 @@ ForeverStack::resolve_segments ( bool searched_prelude = false; while (true) { + if (is_start (iterator, segments) + && current_node->rib.kind == Rib::Kind::TraitOrImpl) + { + // we can't reference associated types/functions like this + current_node = ¤t_node->parent.value (); + continue; + } + // may set the value of child for (auto &kv : current_node->children) { diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 31d7a26be4e3..58a20146091f 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,7 +1,5 @@ issue-3315-2.rs torture/alt_patterns1.rs -torture/name_resolve1.rs -issue-3652.rs issue-1487.rs issue-2015.rs issue-3454.rs From 6a7f7d1d641989670a57a2ff2c2f304d1ec46aed Mon Sep 17 00:00:00 2001 From: Zhi Heng Date: Wed, 11 Jun 2025 21:48:32 +0800 Subject: [PATCH 082/161] gccrs: Rename get_pattern_to_bind to get_subpattern gcc/rust/ChangeLog: * ast/rust-ast-collector.cc: Rename get_pattern_to_bind to get_subpattern * ast/rust-ast-visitor.cc: Ditto. * ast/rust-pattern.h: Ditto. * expand/rust-cfg-strip.cc: Ditto. * hir/rust-ast-lower-pattern.cc: Ditto. Signed-off-by: Yap Zhi Heng --- gcc/rust/ast/rust-ast-collector.cc | 2 +- gcc/rust/ast/rust-ast-visitor.cc | 2 +- gcc/rust/ast/rust-pattern.h | 3 +-- gcc/rust/expand/rust-cfg-strip.cc | 2 +- gcc/rust/hir/rust-ast-lower-pattern.cc | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index b0e06ab85dbc..5a8d462dbd7b 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -2485,7 +2485,7 @@ TokenCollector::visit (IdentifierPattern &pattern) if (pattern.has_subpattern ()) { push (Rust::Token::make (PATTERN_BIND, UNDEF_LOCATION)); - visit (pattern.get_pattern_to_bind ()); + visit (pattern.get_subpattern ()); } } diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 02f4f1664d62..f21a5bbfcb75 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -1200,7 +1200,7 @@ void DefaultASTVisitor::visit (AST::IdentifierPattern &pattern) { if (pattern.has_subpattern ()) - visit (pattern.get_pattern_to_bind ()); + visit (pattern.get_subpattern ()); } void diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 195a08f4fcd9..b9c0fd9bb2f1 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -137,8 +137,7 @@ class IdentifierPattern : public Pattern void accept_vis (ASTVisitor &vis) override; - // TODO: is this better? Or is a "vis_pattern" better? - Pattern &get_pattern_to_bind () + Pattern &get_subpattern () { rust_assert (has_subpattern ()); return *subpattern; diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index 0db6122d5c33..774e2b46b947 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -2267,7 +2267,7 @@ CfgStrip::visit (AST::IdentifierPattern &pattern) AST::DefaultASTVisitor::visit (pattern); - auto &sub_pattern = pattern.get_pattern_to_bind (); + auto &sub_pattern = pattern.get_subpattern (); if (sub_pattern.is_marked_for_strip ()) rust_error_at (sub_pattern.get_locus (), "cannot strip pattern in this position"); diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc index 9baf81d6ee91..bb5b93b2c49b 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.cc +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -53,7 +53,7 @@ ASTLoweringPattern::visit (AST::IdentifierPattern &pattern) if (pattern.has_subpattern ()) { subpattern = std::unique_ptr ( - ASTLoweringPattern::translate (pattern.get_pattern_to_bind ())); + ASTLoweringPattern::translate (pattern.get_subpattern ())); } translated = new HIR::IdentifierPattern (mapping, pattern.get_ident (), From 871cd1dcc82ea9e803c4bbe180ca72208c247eb9 Mon Sep 17 00:00:00 2001 From: Zhi Heng Date: Fri, 13 Jun 2025 22:19:33 +0800 Subject: [PATCH 083/161] gccrs: Implement name resolution for IdentifierPattern's subpattern gcc/rust/ChangeLog: * resolve/rust-ast-resolve-pattern.cc: Implement name resolution for IdentifierPattern's subpattern. * resolve/rust-late-name-resolver-2.0.cc: Ditto, but for nr2. Signed-off-by: Yap Zhi Heng --- gcc/rust/resolve/rust-ast-resolve-pattern.cc | 5 +++++ gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc index 2b5e2bf97eb9..fce45bcf1e62 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc @@ -62,6 +62,11 @@ PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type, void PatternDeclaration::visit (AST::IdentifierPattern &pattern) { + if (pattern.has_subpattern ()) + { + pattern.get_subpattern ().accept_vis (*this); + } + Mutability mut = pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm; add_new_binding (pattern.get_ident (), pattern.get_node_id (), BindingTypeInfo (mut, pattern.get_is_ref (), diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index f8f1eb5c1b05..b66e525946eb 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -251,6 +251,11 @@ visit_identifier_as_pattern (NameResolutionContext &ctx, void Late::visit (AST::IdentifierPattern &identifier) { + if (identifier.has_subpattern ()) + { + DefaultResolver::visit (identifier.get_subpattern ()); + } + visit_identifier_as_pattern (ctx, identifier.get_ident (), identifier.get_locus (), identifier.get_node_id ()); From 74a6644174f0a6f7906d131471c076566e077636 Mon Sep 17 00:00:00 2001 From: Zhi Heng Date: Fri, 13 Jun 2025 22:45:23 +0800 Subject: [PATCH 084/161] gccrs: Implement compilation of IdentifierPattern's subpattern bindings gcc/rust/ChangeLog: * backend/rust-compile-pattern.cc: Add support for IdentifierPattern's subpattern under CompilePatternBindings. Signed-off-by: Yap Zhi Heng --- gcc/rust/backend/rust-compile-pattern.cc | 6 ++++++ .../rust/compile/match-identifierpattern-enum.rs | 12 ++++++++++++ .../rust/execute/match-identifierpattern-enum.rs | 15 +++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 gcc/testsuite/rust/compile/match-identifierpattern-enum.rs create mode 100644 gcc/testsuite/rust/execute/match-identifierpattern-enum.rs diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index e19aa678497d..bd3aea01b537 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -666,6 +666,12 @@ CompilePatternBindings::visit (HIR::ReferencePattern &pattern) void CompilePatternBindings::visit (HIR::IdentifierPattern &pattern) { + if (pattern.has_subpattern ()) + { + CompilePatternBindings::Compile (pattern.get_subpattern (), + match_scrutinee_expr, ctx); + } + if (!pattern.get_is_ref ()) { ctx->insert_pattern_binding (pattern.get_mappings ().get_hirid (), diff --git a/gcc/testsuite/rust/compile/match-identifierpattern-enum.rs b/gcc/testsuite/rust/compile/match-identifierpattern-enum.rs new file mode 100644 index 000000000000..c712667e27a4 --- /dev/null +++ b/gcc/testsuite/rust/compile/match-identifierpattern-enum.rs @@ -0,0 +1,12 @@ +enum Foo { + I(i32), +} + +fn main() { + let x = Foo::I(1); + + match x { + a @ Foo::I(b) => {}, + _ => {}, + }; +} diff --git a/gcc/testsuite/rust/execute/match-identifierpattern-enum.rs b/gcc/testsuite/rust/execute/match-identifierpattern-enum.rs new file mode 100644 index 000000000000..c3a0f65fe710 --- /dev/null +++ b/gcc/testsuite/rust/execute/match-identifierpattern-enum.rs @@ -0,0 +1,15 @@ +enum Foo { + I(i32), +} + +fn main() -> i32 { + let x = Foo::I(0); + let ret = 1; + + match x { + _ @ Foo::I(b) => { ret = b }, + _ => {}, + }; + + ret +} From 8e5099c92b52e4e095ef07891e93d51468a1967c Mon Sep 17 00:00:00 2001 From: Zhi Heng Date: Mon, 16 Jun 2025 21:30:44 +0800 Subject: [PATCH 085/161] nr2.0: Update IdentifierPattern's subpattern name resolution gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::visit(IdentifierPattern)): Remove redundant subpattern check. Signed-off-by: Yap Zhi Heng --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index b66e525946eb..6e63d7078c7b 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -251,10 +251,7 @@ visit_identifier_as_pattern (NameResolutionContext &ctx, void Late::visit (AST::IdentifierPattern &identifier) { - if (identifier.has_subpattern ()) - { - DefaultResolver::visit (identifier.get_subpattern ()); - } + DefaultResolver::visit (identifier); visit_identifier_as_pattern (ctx, identifier.get_ident (), identifier.get_locus (), From abeb90e42df775130d0fe40beb9284090fb8d3ae Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 17 Jun 2025 11:32:21 +0100 Subject: [PATCH 086/161] gccrs: Fix issues around PartialEq Eq Ord Partial Ord There is still an issue with derive on PartialOrd but this adds good tests and fixes a bug we had handling the default Rhs = Self generic type param substitutions on the comparison traits. gcc/rust/ChangeLog: * typecheck/rust-tyty.cc (ParamType::handle_substitions): make this consistent gcc/testsuite/ChangeLog: * rust/compile/bug-with-default-generic.rs: New test. * rust/execute/torture/partial-eq-1.rs: New test. * rust/execute/torture/partial-eq-2.rs: New test. * rust/execute/torture/partial-eq-3.rs: New test. * rust/execute/torture/partial-eq-4.rs: New test. * rust/execute/torture/partial-ord-1.rs: New test. * rust/execute/torture/partial-ord-2.rs: New test. * rust/execute/torture/partial-ord-3.rs: New test. * rust/execute/torture/partial-ord-4.rs: New test. * rust/execute/torture/partial-ord-5.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/typecheck/rust-tyty.cc | 10 +- .../rust/compile/bug-with-default-generic.rs | 15 + .../rust/execute/torture/partial-eq-1.rs | 103 ++++ .../rust/execute/torture/partial-eq-2.rs | 60 +++ .../rust/execute/torture/partial-eq-3.rs | 457 ++++++++++++++++ .../rust/execute/torture/partial-eq-4.rs | 457 ++++++++++++++++ .../rust/execute/torture/partial-ord-1.rs | 101 ++++ .../rust/execute/torture/partial-ord-2.rs | 469 +++++++++++++++++ .../rust/execute/torture/partial-ord-3.rs | 489 ++++++++++++++++++ .../rust/execute/torture/partial-ord-4.rs | 115 ++++ .../rust/execute/torture/partial-ord-5.rs | 487 +++++++++++++++++ 11 files changed, 2758 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/rust/compile/bug-with-default-generic.rs create mode 100644 gcc/testsuite/rust/execute/torture/partial-eq-1.rs create mode 100644 gcc/testsuite/rust/execute/torture/partial-eq-2.rs create mode 100644 gcc/testsuite/rust/execute/torture/partial-eq-3.rs create mode 100644 gcc/testsuite/rust/execute/torture/partial-eq-4.rs create mode 100644 gcc/testsuite/rust/execute/torture/partial-ord-1.rs create mode 100644 gcc/testsuite/rust/execute/torture/partial-ord-2.rs create mode 100644 gcc/testsuite/rust/execute/torture/partial-ord-3.rs create mode 100644 gcc/testsuite/rust/execute/torture/partial-ord-4.rs create mode 100644 gcc/testsuite/rust/execute/torture/partial-ord-5.rs diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 91c68efe972d..e2dfa743b9aa 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -3545,12 +3545,12 @@ ParamType::handle_substitions (SubstitutionArgumentMappings &subst_mappings) ParamType *p = static_cast (clone ()); subst_mappings.on_param_subst (*p, arg); - // there are two cases one where we substitute directly to a new PARAM and - // otherwise - if (arg.get_tyty ()->get_kind () == TyTy::TypeKind::PARAM) + const BaseType *resolved = arg.get_tyty (); + if (resolved->get_kind () == TyTy::TypeKind::PARAM) { - p->set_ty_ref (arg.get_tyty ()->get_ref ()); - return p; + const ParamType &pp = *static_cast (resolved); + if (pp.can_resolve ()) + resolved = pp.resolve (); } // this is the new subst that this needs to pass diff --git a/gcc/testsuite/rust/compile/bug-with-default-generic.rs b/gcc/testsuite/rust/compile/bug-with-default-generic.rs new file mode 100644 index 000000000000..25f46a09c7dc --- /dev/null +++ b/gcc/testsuite/rust/compile/bug-with-default-generic.rs @@ -0,0 +1,15 @@ +#[lang = "sized"] +pub trait Sized {} + +pub trait MyBinaryTrait { + fn do_something(&self, rhs: &Rhs); +} + +struct Foo { + // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 } + value: T, +} + +impl MyBinaryTrait for Foo { + fn do_something(&self, _rhs: &Self) {} +} diff --git a/gcc/testsuite/rust/execute/torture/partial-eq-1.rs b/gcc/testsuite/rust/execute/torture/partial-eq-1.rs new file mode 100644 index 000000000000..db123a1b5e7d --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/partial-eq-1.rs @@ -0,0 +1,103 @@ +/* { dg-output "a == b\r*\na != c\r*\n" }*/ +/* { dg-options "-w" } */ + +mod core { + mod marker { + #[lang = "phantom_data"] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct PhantomData; + + #[unstable(feature = "structural_match", issue = "31434")] + #[lang = "structural_peq"] + pub trait StructuralPartialEq { + // Empty. + } + + #[unstable(feature = "structural_match", issue = "31434")] + #[lang = "structural_teq"] + pub trait StructuralEq { + // Empty. + } + + #[lang = "sized"] + pub trait Sized {} + } + + pub mod cmp { + use super::marker::Sized; + + #[lang = "eq"] + pub trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + pub trait Eq: PartialEq { + fn assert_receiver_is_total_eq(&self) {} + } + } +} + +use core::cmp::{Eq, PartialEq}; + +// PartialEq for i32 and u32 so we can compare across types +impl PartialEq for i32 { + fn eq(&self, other: &u32) -> bool { + *self >= 0 && (*self as u32) == *other + } +} +impl PartialEq for u32 { + fn eq(&self, other: &i32) -> bool { + *other >= 0 && *self == *other as u32 + } +} + +// Our generic struct +struct Foo { + value: T, +} + +// Manual impl of PartialEq for different generic params +impl PartialEq> for Foo +where + T: PartialEq, +{ + fn eq(&self, other: &Foo) -> bool { + self.value.eq(&other.value) + } +} + +impl Eq for Foo {} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let a = Foo { value: 42i32 }; + let b = Foo { value: 42u32 }; + let c = Foo { value: 7u32 }; + + if a == b { + print("a == b"); + } else { + print("a != b"); + } + + if a == c { + print("a == c"); + } else { + print("a != c"); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/partial-eq-2.rs b/gcc/testsuite/rust/execute/torture/partial-eq-2.rs new file mode 100644 index 000000000000..debed8c83f32 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/partial-eq-2.rs @@ -0,0 +1,60 @@ +/* { dg-output "a == b\r*\na != c\r*\n" }*/ +/* { dg-options "-w" } */ + +#[lang = "sized"] +pub trait Sized {} + +#[lang = "eq"] +pub trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } +} + +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +struct Foo { + value: T, +} + +impl PartialEq for Foo { + fn eq(&self, other: &Self) -> bool { + self.value.eq(&other.value) + } +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let a = Foo { value: 42i32 }; + let b = Foo { value: 42i32 }; + let c = Foo { value: 99i32 }; + + if a == b { + print("a == b"); + } else { + print("a != b"); + } + + if a == c { + print("a == c"); + } else { + print("a != c"); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/partial-eq-3.rs b/gcc/testsuite/rust/execute/torture/partial-eq-3.rs new file mode 100644 index 000000000000..849910afc832 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/partial-eq-3.rs @@ -0,0 +1,457 @@ +/* { dg-output "a == b\r*\na != c\r*\n" }*/ +/* { dg-options "-w" } */ + +#![feature(intrinsics)] + +mod core { + mod option { + // #[rustc_diagnostic_item = "option_type"] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Option { + /// No value + #[lang = "None"] + #[stable(feature = "rust1", since = "1.0.0")] + None, + /// Some value `T` + #[lang = "Some"] + #[stable(feature = "rust1", since = "1.0.0")] + Some(#[stable(feature = "rust1", since = "1.0.0")] T), + } + } + + mod marker { + #[lang = "phantom_data"] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct PhantomData; + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] + #[lang = "structural_peq"] + pub trait StructuralPartialEq { + // Empty. + } + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] + #[lang = "structural_teq"] + pub trait StructuralEq { + // Empty. + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[lang = "sized"] + // #[rustc_on_unimplemented( + // message = "the size for values of type `{Self}` cannot be known at compilation time", + // label = "doesn't have a size known at compile-time" + // )] + // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable + // #[rustc_specialization_trait] + pub trait Sized { + // Empty. + } + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + // #[derive(Clone, Copy, PartialEq, Debug, Hash)] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Ordering { + /// An ordering where a compared value is less than another. + #[stable(feature = "rust1", since = "1.0.0")] + Less = -1, + /// An ordering where a compared value is equal to another. + #[stable(feature = "rust1", since = "1.0.0")] + Equal = 0, + /// An ordering where a compared value is greater than another. + #[stable(feature = "rust1", since = "1.0.0")] + Greater = 1, + } + + #[lang = "eq"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = "==")] + #[doc(alias = "!=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} == {Rhs}`" + // )] + pub trait PartialEq { + /// This method tests for `self` and `other` values to be equal, and is used + /// by `==`. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + #[doc(alias = "==")] + #[doc(alias = "!=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Eq: PartialEq { + // this method is used solely by #[deriving] to assert + // that every component of a type implements #[deriving] + // itself, the current deriving infrastructure means doing this + // assertion without using a method on this trait is nearly + // impossible. + // + // This should never be implemented by hand. + #[doc(hidden)] + #[stable(feature = "rust1", since = "1.0.0")] + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = ">")] + #[doc(alias = "<")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`" + // )] + pub trait PartialOrd: PartialEq { + /// This method returns an ordering between `self` and `other` values if one exists. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = 1.0.partial_cmp(&2.0); + /// assert_eq!(result, Some(Ordering::Less)); + /// + /// let result = 1.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Equal)); + /// + /// let result = 2.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Greater)); + /// ``` + /// + /// When comparison is impossible: + /// + /// ``` + /// let result = f64::NAN.partial_cmp(&1.0); + /// assert_eq!(result, None); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn partial_cmp(&self, other: &Rhs) -> Option; + + /// This method tests less than (for `self` and `other`) and is used by the `<` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 < 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 < 1.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 <= 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 <= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less | Ordering::Equal) => true, + _ => false, + } + } + + /// This method tests greater than (for `self` and `other`) and is used by the `>` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 > 2.0; + /// assert_eq!(result, false); + /// + /// let result = 2.0 > 2.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 2.0 >= 1.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 >= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater | Ordering::Equal) => true, + _ => false, + } + } + } + + #[doc(alias = "<")] + #[doc(alias = ">")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Ord: Eq + PartialOrd { + /// This method returns an [`Ordering`] between `self` and `other`. + /// + /// By convention, `self.cmp(&other)` returns the ordering matching the expression + /// `self other` if true. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(5.cmp(&10), Ordering::Less); + /// assert_eq!(10.cmp(&5), Ordering::Greater); + /// assert_eq!(5.cmp(&5), Ordering::Equal); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(2, 1.max(2)); + /// assert_eq!(2, 2.max(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn max(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1, 1.min(2)); + /// assert_eq!(2, 2.min(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn min(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Restrict a value to a certain interval. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// # Panics + /// + /// Panics if `min > max`. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp)] + /// + /// assert!((-3).clamp(-2, 1) == -2); + /// assert!(0.clamp(-2, 1) == 0); + /// assert!(2.clamp(-2, 1) == 1); + /// ``` + #[must_use] + #[unstable(feature = "clamp", issue = "44095")] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: Sized, + { + if self < min { + min + } else if self > max { + max + } else { + self + } + } + } + } + + pub mod intrinsics { + #[lang = "discriminant_kind"] + pub trait DiscriminantKind { + #[lang = "discriminant_type"] + type Discriminant; + } + + extern "rust-intrinsic" { + pub fn discriminant_value(v: &T) -> ::Discriminant; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::marker::Sized; +use core::option::Option; + +// for comparing discriminant_value +impl PartialEq for isize { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +// for comparing discriminant_value +impl PartialOrd for isize { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} +impl Eq for i32 {} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self > *other { + Ordering::Greater + } else if *self < *other { + Ordering::Less + } else { + Ordering::Equal + } + } +} + +#[derive(PartialEq)] +struct Foo { + a: i32, +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let a = Foo { a: 42i32 }; + let b = Foo { a: 42i32 }; + let c = Foo { a: 7i32 }; + + if a == b { + print("a == b"); + } else { + print("a != b"); + } + + if a == c { + print("a == c"); + } else { + print("a != c"); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/partial-eq-4.rs b/gcc/testsuite/rust/execute/torture/partial-eq-4.rs new file mode 100644 index 000000000000..b6997d8592fa --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/partial-eq-4.rs @@ -0,0 +1,457 @@ +/* { dg-output "a == b\r*\na != c\r*\n" }*/ +/* { dg-options "-w" } */ + +#![feature(intrinsics)] + +mod core { + mod option { + // #[rustc_diagnostic_item = "option_type"] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Option { + /// No value + #[lang = "None"] + #[stable(feature = "rust1", since = "1.0.0")] + None, + /// Some value `T` + #[lang = "Some"] + #[stable(feature = "rust1", since = "1.0.0")] + Some(#[stable(feature = "rust1", since = "1.0.0")] T), + } + } + + mod marker { + #[lang = "phantom_data"] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct PhantomData; + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] + #[lang = "structural_peq"] + pub trait StructuralPartialEq { + // Empty. + } + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] + #[lang = "structural_teq"] + pub trait StructuralEq { + // Empty. + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[lang = "sized"] + // #[rustc_on_unimplemented( + // message = "the size for values of type `{Self}` cannot be known at compilation time", + // label = "doesn't have a size known at compile-time" + // )] + // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable + // #[rustc_specialization_trait] + pub trait Sized { + // Empty. + } + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + // #[derive(Clone, Copy, PartialEq, Debug, Hash)] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Ordering { + /// An ordering where a compared value is less than another. + #[stable(feature = "rust1", since = "1.0.0")] + Less = -1, + /// An ordering where a compared value is equal to another. + #[stable(feature = "rust1", since = "1.0.0")] + Equal = 0, + /// An ordering where a compared value is greater than another. + #[stable(feature = "rust1", since = "1.0.0")] + Greater = 1, + } + + #[lang = "eq"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = "==")] + #[doc(alias = "!=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} == {Rhs}`" + // )] + pub trait PartialEq { + /// This method tests for `self` and `other` values to be equal, and is used + /// by `==`. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + #[doc(alias = "==")] + #[doc(alias = "!=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Eq: PartialEq { + // this method is used solely by #[deriving] to assert + // that every component of a type implements #[deriving] + // itself, the current deriving infrastructure means doing this + // assertion without using a method on this trait is nearly + // impossible. + // + // This should never be implemented by hand. + #[doc(hidden)] + #[stable(feature = "rust1", since = "1.0.0")] + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = ">")] + #[doc(alias = "<")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`" + // )] + pub trait PartialOrd: PartialEq { + /// This method returns an ordering between `self` and `other` values if one exists. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = 1.0.partial_cmp(&2.0); + /// assert_eq!(result, Some(Ordering::Less)); + /// + /// let result = 1.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Equal)); + /// + /// let result = 2.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Greater)); + /// ``` + /// + /// When comparison is impossible: + /// + /// ``` + /// let result = f64::NAN.partial_cmp(&1.0); + /// assert_eq!(result, None); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn partial_cmp(&self, other: &Rhs) -> Option; + + /// This method tests less than (for `self` and `other`) and is used by the `<` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 < 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 < 1.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 <= 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 <= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less | Ordering::Equal) => true, + _ => false, + } + } + + /// This method tests greater than (for `self` and `other`) and is used by the `>` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 > 2.0; + /// assert_eq!(result, false); + /// + /// let result = 2.0 > 2.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 2.0 >= 1.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 >= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater | Ordering::Equal) => true, + _ => false, + } + } + } + + #[doc(alias = "<")] + #[doc(alias = ">")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Ord: Eq + PartialOrd { + /// This method returns an [`Ordering`] between `self` and `other`. + /// + /// By convention, `self.cmp(&other)` returns the ordering matching the expression + /// `self other` if true. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(5.cmp(&10), Ordering::Less); + /// assert_eq!(10.cmp(&5), Ordering::Greater); + /// assert_eq!(5.cmp(&5), Ordering::Equal); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(2, 1.max(2)); + /// assert_eq!(2, 2.max(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn max(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1, 1.min(2)); + /// assert_eq!(2, 2.min(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn min(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Restrict a value to a certain interval. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// # Panics + /// + /// Panics if `min > max`. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp)] + /// + /// assert!((-3).clamp(-2, 1) == -2); + /// assert!(0.clamp(-2, 1) == 0); + /// assert!(2.clamp(-2, 1) == 1); + /// ``` + #[must_use] + #[unstable(feature = "clamp", issue = "44095")] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: Sized, + { + if self < min { + min + } else if self > max { + max + } else { + self + } + } + } + } + + pub mod intrinsics { + #[lang = "discriminant_kind"] + pub trait DiscriminantKind { + #[lang = "discriminant_type"] + type Discriminant; + } + + extern "rust-intrinsic" { + pub fn discriminant_value(v: &T) -> ::Discriminant; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::marker::Sized; +use core::option::Option; + +// for comparing discriminant_value +impl PartialEq for isize { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +// for comparing discriminant_value +impl PartialOrd for isize { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} +impl Eq for i32 {} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self > *other { + Ordering::Greater + } else if *self < *other { + Ordering::Less + } else { + Ordering::Equal + } + } +} + +#[derive(PartialEq, Eq)] +struct Foo { + a: i32, +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let a = Foo { a: 42i32 }; + let b = Foo { a: 42i32 }; + let c = Foo { a: 7i32 }; + + if a == b { + print("a == b"); + } else { + print("a != b"); + } + + if a == c { + print("a == c"); + } else { + print("a != c"); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-1.rs b/gcc/testsuite/rust/execute/torture/partial-ord-1.rs new file mode 100644 index 000000000000..a3558e7cb7a9 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/partial-ord-1.rs @@ -0,0 +1,101 @@ +/* { dg-output "x == y\r*\nx > z\r*\n" }*/ +#[lang = "sized"] +pub trait Sized {} + +pub enum Option { + #[lang = "None"] + None, + #[lang = "Some"] + Some(T), +} + +use Option::{None, Some}; + +#[lang = "eq"] +pub trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } +} + +pub enum Ordering { + Less = -1, + Equal = 0, + Greater = 1, +} + +#[lang = "partial_ord"] +pub trait PartialOrd: PartialEq { + fn partial_cmp(&self, other: &Rhs) -> Option; +} + +// Implement for i32 +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +// Implement PartialOrd for i32 +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self < *other { + Some(Ordering::Less) + } else if *self > *other { + Some(Ordering::Greater) + } else { + Some(Ordering::Equal) + } + } +} + +// Struct with manual PartialEq +struct Foo { + a: i32, +} + +impl PartialEq for Foo { + fn eq(&self, other: &Self) -> bool { + self.a.eq(&other.a) + } +} + +impl PartialOrd for Foo { + fn partial_cmp(&self, other: &Self) -> Option { + self.a.partial_cmp(&other.a) + } +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let x = Foo { a: 42 }; + let y = Foo { a: 42 }; + let z = Foo { a: 7 }; + + match x.partial_cmp(&y) { + Some(Ordering::Equal) => print("x == y"), + Some(Ordering::Less) => print("x < y"), + Some(Ordering::Greater) => print("x > y"), + None => print("x ? y"), + } + + match x.partial_cmp(&z) { + Some(Ordering::Equal) => print("x == z"), + Some(Ordering::Less) => print("x < z"), + Some(Ordering::Greater) => print("x > z"), + None => print("x ? z"), + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-2.rs b/gcc/testsuite/rust/execute/torture/partial-ord-2.rs new file mode 100644 index 000000000000..d3b713fc5e26 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/partial-ord-2.rs @@ -0,0 +1,469 @@ +/* { dg-output "x == y\r*\nx > z\r*\n" }*/ + +#![feature(intrinsics)] + +mod core { + mod option { + // #[rustc_diagnostic_item = "option_type"] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Option { + /// No value + #[lang = "None"] + #[stable(feature = "rust1", since = "1.0.0")] + None, + /// Some value `T` + #[lang = "Some"] + #[stable(feature = "rust1", since = "1.0.0")] + Some(#[stable(feature = "rust1", since = "1.0.0")] T), + } + } + + mod marker { + #[lang = "phantom_data"] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct PhantomData; + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] + #[lang = "structural_peq"] + pub trait StructuralPartialEq { + // Empty. + } + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] + #[lang = "structural_teq"] + pub trait StructuralEq { + // Empty. + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[lang = "sized"] + // #[rustc_on_unimplemented( + // message = "the size for values of type `{Self}` cannot be known at compilation time", + // label = "doesn't have a size known at compile-time" + // )] + // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable + // #[rustc_specialization_trait] + pub trait Sized { + // Empty. + } + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + // #[derive(Clone, Copy, PartialEq, Debug, Hash)] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Ordering { + /// An ordering where a compared value is less than another. + #[stable(feature = "rust1", since = "1.0.0")] + Less = -1, + /// An ordering where a compared value is equal to another. + #[stable(feature = "rust1", since = "1.0.0")] + Equal = 0, + /// An ordering where a compared value is greater than another. + #[stable(feature = "rust1", since = "1.0.0")] + Greater = 1, + } + + #[lang = "eq"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = "==")] + #[doc(alias = "!=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} == {Rhs}`" + // )] + pub trait PartialEq { + /// This method tests for `self` and `other` values to be equal, and is used + /// by `==`. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + #[doc(alias = "==")] + #[doc(alias = "!=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Eq: PartialEq { + // this method is used solely by #[deriving] to assert + // that every component of a type implements #[deriving] + // itself, the current deriving infrastructure means doing this + // assertion without using a method on this trait is nearly + // impossible. + // + // This should never be implemented by hand. + #[doc(hidden)] + #[stable(feature = "rust1", since = "1.0.0")] + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = ">")] + #[doc(alias = "<")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`" + // )] + pub trait PartialOrd: PartialEq { + /// This method returns an ordering between `self` and `other` values if one exists. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = 1.0.partial_cmp(&2.0); + /// assert_eq!(result, Some(Ordering::Less)); + /// + /// let result = 1.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Equal)); + /// + /// let result = 2.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Greater)); + /// ``` + /// + /// When comparison is impossible: + /// + /// ``` + /// let result = f64::NAN.partial_cmp(&1.0); + /// assert_eq!(result, None); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn partial_cmp(&self, other: &Rhs) -> Option; + + /// This method tests less than (for `self` and `other`) and is used by the `<` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 < 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 < 1.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 <= 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 <= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less | Ordering::Equal) => true, + _ => false, + } + } + + /// This method tests greater than (for `self` and `other`) and is used by the `>` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 > 2.0; + /// assert_eq!(result, false); + /// + /// let result = 2.0 > 2.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 2.0 >= 1.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 >= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater | Ordering::Equal) => true, + _ => false, + } + } + } + + #[doc(alias = "<")] + #[doc(alias = ">")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Ord: Eq + PartialOrd { + /// This method returns an [`Ordering`] between `self` and `other`. + /// + /// By convention, `self.cmp(&other)` returns the ordering matching the expression + /// `self other` if true. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(5.cmp(&10), Ordering::Less); + /// assert_eq!(10.cmp(&5), Ordering::Greater); + /// assert_eq!(5.cmp(&5), Ordering::Equal); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(2, 1.max(2)); + /// assert_eq!(2, 2.max(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn max(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1, 1.min(2)); + /// assert_eq!(2, 2.min(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn min(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Restrict a value to a certain interval. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// # Panics + /// + /// Panics if `min > max`. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp)] + /// + /// assert!((-3).clamp(-2, 1) == -2); + /// assert!(0.clamp(-2, 1) == 0); + /// assert!(2.clamp(-2, 1) == 1); + /// ``` + #[must_use] + #[unstable(feature = "clamp", issue = "44095")] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: Sized, + { + if self < min { + min + } else if self > max { + max + } else { + self + } + } + } + } + + pub mod intrinsics { + #[lang = "discriminant_kind"] + pub trait DiscriminantKind { + #[lang = "discriminant_type"] + type Discriminant; + } + + extern "rust-intrinsic" { + pub fn discriminant_value(v: &T) -> ::Discriminant; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::marker::Sized; +use core::option::Option; + +// for comparing discriminant_value +impl PartialEq for isize { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +// for comparing discriminant_value +impl PartialOrd for isize { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} +impl Eq for i32 {} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self > *other { + Ordering::Greater + } else if *self < *other { + Ordering::Less + } else { + Ordering::Equal + } + } +} + +struct Foo { + a: i32, +} + +impl PartialEq for Foo { + fn eq(&self, other: &'_ Self) -> bool { + self.a == other.a + } +} + +impl PartialOrd for Foo { + fn partial_cmp(&self, other: &'_ Foo) -> Option<::core::cmp::Ordering> { + self.a.partial_cmp(&other.a) + } +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let x = Foo { a: 42 }; + let y = Foo { a: 42 }; + let z = Foo { a: 7 }; + + match x.partial_cmp(&y) { + Option::Some(Ordering::Equal) => print("x == y"), + Option::Some(Ordering::Less) => print("x < y"), + Option::Some(Ordering::Greater) => print("x > y"), + Option::None => print("x ? y"), + } + + match x.partial_cmp(&z) { + Option::Some(Ordering::Equal) => print("x == z"), + Option::Some(Ordering::Less) => print("x < z"), + Option::Some(Ordering::Greater) => print("x > z"), + Option::None => print("x ? z"), + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-3.rs b/gcc/testsuite/rust/execute/torture/partial-ord-3.rs new file mode 100644 index 000000000000..7aec07c5caaa --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/partial-ord-3.rs @@ -0,0 +1,489 @@ +/* { dg-output "x == y\r*\nx > z\r*\nx < z\r*\nx >= y\r*\nx <= y\r*\n" } */ +/* { dg-options "-w" } */ + +#![feature(intrinsics)] + +mod core { + mod option { + // #[rustc_diagnostic_item = "option_type"] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Option { + /// No value + #[lang = "None"] + #[stable(feature = "rust1", since = "1.0.0")] + None, + /// Some value `T` + #[lang = "Some"] + #[stable(feature = "rust1", since = "1.0.0")] + Some(#[stable(feature = "rust1", since = "1.0.0")] T), + } + } + + mod marker { + #[lang = "phantom_data"] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct PhantomData; + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] + #[lang = "structural_peq"] + pub trait StructuralPartialEq { + // Empty. + } + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] + #[lang = "structural_teq"] + pub trait StructuralEq { + // Empty. + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[lang = "sized"] + // #[rustc_on_unimplemented( + // message = "the size for values of type `{Self}` cannot be known at compilation time", + // label = "doesn't have a size known at compile-time" + // )] + // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable + // #[rustc_specialization_trait] + pub trait Sized { + // Empty. + } + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + // #[derive(Clone, Copy, PartialEq, Debug, Hash)] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Ordering { + /// An ordering where a compared value is less than another. + #[stable(feature = "rust1", since = "1.0.0")] + Less = -1, + /// An ordering where a compared value is equal to another. + #[stable(feature = "rust1", since = "1.0.0")] + Equal = 0, + /// An ordering where a compared value is greater than another. + #[stable(feature = "rust1", since = "1.0.0")] + Greater = 1, + } + + #[lang = "eq"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = "==")] + #[doc(alias = "!=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} == {Rhs}`" + // )] + pub trait PartialEq { + /// This method tests for `self` and `other` values to be equal, and is used + /// by `==`. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + #[doc(alias = "==")] + #[doc(alias = "!=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Eq: PartialEq { + // this method is used solely by #[deriving] to assert + // that every component of a type implements #[deriving] + // itself, the current deriving infrastructure means doing this + // assertion without using a method on this trait is nearly + // impossible. + // + // This should never be implemented by hand. + #[doc(hidden)] + #[stable(feature = "rust1", since = "1.0.0")] + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = ">")] + #[doc(alias = "<")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`" + // )] + pub trait PartialOrd: PartialEq { + /// This method returns an ordering between `self` and `other` values if one exists. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = 1.0.partial_cmp(&2.0); + /// assert_eq!(result, Some(Ordering::Less)); + /// + /// let result = 1.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Equal)); + /// + /// let result = 2.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Greater)); + /// ``` + /// + /// When comparison is impossible: + /// + /// ``` + /// let result = f64::NAN.partial_cmp(&1.0); + /// assert_eq!(result, None); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn partial_cmp(&self, other: &Rhs) -> Option; + + /// This method tests less than (for `self` and `other`) and is used by the `<` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 < 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 < 1.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 <= 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 <= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less | Ordering::Equal) => true, + _ => false, + } + } + + /// This method tests greater than (for `self` and `other`) and is used by the `>` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 > 2.0; + /// assert_eq!(result, false); + /// + /// let result = 2.0 > 2.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 2.0 >= 1.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 >= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater | Ordering::Equal) => true, + _ => false, + } + } + } + + #[doc(alias = "<")] + #[doc(alias = ">")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Ord: Eq + PartialOrd { + /// This method returns an [`Ordering`] between `self` and `other`. + /// + /// By convention, `self.cmp(&other)` returns the ordering matching the expression + /// `self other` if true. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(5.cmp(&10), Ordering::Less); + /// assert_eq!(10.cmp(&5), Ordering::Greater); + /// assert_eq!(5.cmp(&5), Ordering::Equal); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(2, 1.max(2)); + /// assert_eq!(2, 2.max(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn max(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1, 1.min(2)); + /// assert_eq!(2, 2.min(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn min(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Restrict a value to a certain interval. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// # Panics + /// + /// Panics if `min > max`. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp)] + /// + /// assert!((-3).clamp(-2, 1) == -2); + /// assert!(0.clamp(-2, 1) == 0); + /// assert!(2.clamp(-2, 1) == 1); + /// ``` + #[must_use] + #[unstable(feature = "clamp", issue = "44095")] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: Sized, + { + if self < min { + min + } else if self > max { + max + } else { + self + } + } + } + } + + pub mod intrinsics { + #[lang = "discriminant_kind"] + pub trait DiscriminantKind { + #[lang = "discriminant_type"] + type Discriminant; + } + + extern "rust-intrinsic" { + pub fn discriminant_value(v: &T) -> ::Discriminant; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::marker::Sized; +use core::option::Option; + +// for comparing discriminant_value +impl PartialEq for isize { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +// for comparing discriminant_value +impl PartialOrd for isize { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} +impl Eq for i32 {} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self > *other { + Ordering::Greater + } else if *self < *other { + Ordering::Less + } else { + Ordering::Equal + } + } +} + +struct Foo { + a: i32, +} + +impl PartialEq for Foo { + fn eq(&self, other: &Self) -> bool { + self.a == other.a + } +} +impl Eq for Foo {} + +impl PartialOrd for Foo { + fn partial_cmp(&self, other: &Self) -> Option { + self.a.partial_cmp(&other.a) + } +} + +impl Ord for Foo { + fn cmp(&self, other: &Self) -> Ordering { + self.a.cmp(&other.a) + } +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let x = Foo { a: 42 }; + let y = Foo { a: 42 }; + let z = Foo { a: 7 }; + + // test direct equality + if x == y { + print("x == y"); + } + + // test PartialOrd via match + match x.partial_cmp(&z) { + Option::Some(Ordering::Greater) => print("x > z"), + _ => print("x ? z"), + } + + // test `<` directly + if z < x { + print("x < z"); + } + + // test `>=` + if x >= y { + print("x >= y"); + } + + // test `<=` + if x <= y { + print("x <= y"); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-4.rs b/gcc/testsuite/rust/execute/torture/partial-ord-4.rs new file mode 100644 index 000000000000..fd52f328c58b --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/partial-ord-4.rs @@ -0,0 +1,115 @@ +/* { dg-output "a == b\r*\na != c\r*\n" }*/ +/* { dg-options "-w" } */ + +#![feature(intrinsics)] + +mod core { + mod option { + pub enum Option { + #[lang = "None"] + None, + #[lang = "Some"] + Some(T), + } + } + + mod marker { + #[lang = "sized"] + pub trait Sized {} + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + pub enum Ordering { + Less = -1, + Equal = 0, + Greater = 1, + } + + #[lang = "eq"] + pub trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + #[lang = "partial_ord"] + pub trait PartialOrd: PartialEq { + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn partial_cmp(&self, other: &Rhs) -> Option; + } + } +} + +use core::cmp::{Ordering, PartialEq, PartialOrd}; +use core::marker::Sized; +use core::option::Option; + +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } +} + +struct Foo { + a: i32, +} + +impl PartialEq for Foo { + fn eq(&self, other: &'_ Self) -> bool { + self.a == other.a + } +} + +impl PartialOrd for Foo { + fn partial_cmp(&self, other: &'_ Foo) -> Option<::core::cmp::Ordering> { + ::core::cmp::PartialOrd::partial_cmp(&self.a, &other.a) + } +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let a = Foo { a: 42i32 }; + let b = Foo { a: 42i32 }; + let c = Foo { a: 7i32 }; + + if a == b { + print("a == b"); + } else { + print("a != b"); + } + + if a == c { + print("a == c"); + } else { + print("a != c"); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-5.rs b/gcc/testsuite/rust/execute/torture/partial-ord-5.rs new file mode 100644 index 000000000000..721d2aa00655 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/partial-ord-5.rs @@ -0,0 +1,487 @@ +/* { dg-output "a == b\r*\na != c\r*\na >= c\r*\na <= b\r*\na > c\r*\nc < b\r*\n" } */ +/* { dg-options "-w" } */ + +#![feature(intrinsics)] + +mod core { + mod option { + // #[rustc_diagnostic_item = "option_type"] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Option { + /// No value + #[lang = "None"] + #[stable(feature = "rust1", since = "1.0.0")] + None, + /// Some value `T` + #[lang = "Some"] + #[stable(feature = "rust1", since = "1.0.0")] + Some(#[stable(feature = "rust1", since = "1.0.0")] T), + } + } + + mod marker { + #[lang = "phantom_data"] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct PhantomData; + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] + #[lang = "structural_peq"] + pub trait StructuralPartialEq { + // Empty. + } + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] + #[lang = "structural_teq"] + pub trait StructuralEq { + // Empty. + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[lang = "sized"] + // #[rustc_on_unimplemented( + // message = "the size for values of type `{Self}` cannot be known at compilation time", + // label = "doesn't have a size known at compile-time" + // )] + // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable + // #[rustc_specialization_trait] + pub trait Sized { + // Empty. + } + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + // #[derive(Clone, Copy, PartialEq, Debug, Hash)] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Ordering { + /// An ordering where a compared value is less than another. + #[stable(feature = "rust1", since = "1.0.0")] + Less = -1, + /// An ordering where a compared value is equal to another. + #[stable(feature = "rust1", since = "1.0.0")] + Equal = 0, + /// An ordering where a compared value is greater than another. + #[stable(feature = "rust1", since = "1.0.0")] + Greater = 1, + } + + #[lang = "eq"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = "==")] + #[doc(alias = "!=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} == {Rhs}`" + // )] + pub trait PartialEq { + /// This method tests for `self` and `other` values to be equal, and is used + /// by `==`. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + #[doc(alias = "==")] + #[doc(alias = "!=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Eq: PartialEq { + // this method is used solely by #[deriving] to assert + // that every component of a type implements #[deriving] + // itself, the current deriving infrastructure means doing this + // assertion without using a method on this trait is nearly + // impossible. + // + // This should never be implemented by hand. + #[doc(hidden)] + #[stable(feature = "rust1", since = "1.0.0")] + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = ">")] + #[doc(alias = "<")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`" + // )] + pub trait PartialOrd: PartialEq { + /// This method returns an ordering between `self` and `other` values if one exists. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = 1.0.partial_cmp(&2.0); + /// assert_eq!(result, Some(Ordering::Less)); + /// + /// let result = 1.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Equal)); + /// + /// let result = 2.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Greater)); + /// ``` + /// + /// When comparison is impossible: + /// + /// ``` + /// let result = f64::NAN.partial_cmp(&1.0); + /// assert_eq!(result, None); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn partial_cmp(&self, other: &Rhs) -> Option; + + /// This method tests less than (for `self` and `other`) and is used by the `<` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 < 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 < 1.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 <= 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 <= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less | Ordering::Equal) => true, + _ => false, + } + } + + /// This method tests greater than (for `self` and `other`) and is used by the `>` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 > 2.0; + /// assert_eq!(result, false); + /// + /// let result = 2.0 > 2.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 2.0 >= 1.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 >= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater | Ordering::Equal) => true, + _ => false, + } + } + } + + #[doc(alias = "<")] + #[doc(alias = ">")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Ord: Eq + PartialOrd { + /// This method returns an [`Ordering`] between `self` and `other`. + /// + /// By convention, `self.cmp(&other)` returns the ordering matching the expression + /// `self other` if true. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(5.cmp(&10), Ordering::Less); + /// assert_eq!(10.cmp(&5), Ordering::Greater); + /// assert_eq!(5.cmp(&5), Ordering::Equal); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(2, 1.max(2)); + /// assert_eq!(2, 2.max(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn max(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1, 1.min(2)); + /// assert_eq!(2, 2.min(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn min(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Restrict a value to a certain interval. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// # Panics + /// + /// Panics if `min > max`. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp)] + /// + /// assert!((-3).clamp(-2, 1) == -2); + /// assert!(0.clamp(-2, 1) == 0); + /// assert!(2.clamp(-2, 1) == 1); + /// ``` + #[must_use] + #[unstable(feature = "clamp", issue = "44095")] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: Sized, + { + if self < min { + min + } else if self > max { + max + } else { + self + } + } + } + } + + pub mod intrinsics { + #[lang = "discriminant_kind"] + pub trait DiscriminantKind { + #[lang = "discriminant_type"] + type Discriminant; + } + + extern "rust-intrinsic" { + pub fn discriminant_value(v: &T) -> ::Discriminant; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::marker::Sized; +use core::option::Option; + +// for comparing discriminant_value +impl PartialEq for isize { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +// for comparing discriminant_value +impl PartialOrd for isize { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} +impl Eq for i32 {} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self > *other { + Ordering::Greater + } else if *self < *other { + Ordering::Less + } else { + Ordering::Equal + } + } +} + +#[derive(PartialEq, Eq, Ord)] +struct Foo { + a: i32, +} + +impl PartialOrd for Foo { + fn partial_cmp(&self, other: &'_ Foo) -> Option<::core::cmp::Ordering> { + self.a.partial_cmp(&other.a) + } +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let a = Foo { a: 42 }; + let b = Foo { a: 42 }; + let c = Foo { a: 7 }; + + if a == b { + print("a == b"); + } else { + print("a != b"); + } + + if a != c { + print("a != c"); + } else { + print("a == c"); + } + + if a < c { + print("a < c"); + } else { + print("a >= c"); + } + + if a <= b { + print("a <= b"); + } else { + print("a > b"); + } + + if a > c { + print("a > c"); + } else { + print("a <= c"); + } + + if c >= b { + print("c >= b"); + } else { + print("c < b"); + } + + 0 +} From c2c3b8f77a382f492814b500f9e781d744ff816d Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Tue, 17 Jun 2025 10:42:05 -0400 Subject: [PATCH 087/161] Fix execute testsuite Our non-torture execute tests haven't actually been running. gcc/testsuite/ChangeLog: * rust/execute/black_box.rs: Return 0 from main. * rust/execute/match-identifierpattern-enum.rs: Move to... * rust/execute/xfail/match-identifierpattern-enum.rs: ...here. * rust/execute/execute.exp: New file. Signed-off-by: Owen Avery --- gcc/testsuite/rust/execute/black_box.rs | 3 +- gcc/testsuite/rust/execute/execute.exp | 33 +++++++++++++++++++ .../match-identifierpattern-enum.rs | 0 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/rust/execute/execute.exp rename gcc/testsuite/rust/execute/{ => xfail}/match-identifierpattern-enum.rs (100%) diff --git a/gcc/testsuite/rust/execute/black_box.rs b/gcc/testsuite/rust/execute/black_box.rs index 7a9920eba947..58d10a3e4209 100644 --- a/gcc/testsuite/rust/execute/black_box.rs +++ b/gcc/testsuite/rust/execute/black_box.rs @@ -21,10 +21,11 @@ pub fn black_box(mut dummy: T) -> T { dummy } -fn main() { +fn main() -> i32 { let dummy: i32 = 42; let result = black_box(dummy); unsafe { printf("Value is: %i\n\0" as *const str as *const i8, result); } + 0 } diff --git a/gcc/testsuite/rust/execute/execute.exp b/gcc/testsuite/rust/execute/execute.exp new file mode 100644 index 000000000000..3754778bd4cd --- /dev/null +++ b/gcc/testsuite/rust/execute/execute.exp @@ -0,0 +1,33 @@ +# Copyright (C) 2021-2025 Free Software Foundation, Inc. + +# This program 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 of the License, or +# (at your option) any later version. +# +# This program 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 +# . + +# Execute tests. + +# Load support procs. +load_lib rust-dg.exp + +# Initialize `dg'. +dg-init + +# Main loop. +set saved-dg-do-what-default ${dg-do-what-default} + +set dg-do-what-default "run" +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.rs]] "" "" +set dg-do-what-default ${saved-dg-do-what-default} + +# All done. +dg-finish diff --git a/gcc/testsuite/rust/execute/match-identifierpattern-enum.rs b/gcc/testsuite/rust/execute/xfail/match-identifierpattern-enum.rs similarity index 100% rename from gcc/testsuite/rust/execute/match-identifierpattern-enum.rs rename to gcc/testsuite/rust/execute/xfail/match-identifierpattern-enum.rs From 5b8b7397c237602a85af683f1dec02e172965c6d Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Mon, 16 Jun 2025 17:04:22 -0400 Subject: [PATCH 088/161] Adjust external crate lowering and type checking The 2.0 name resolver is provided through ImmutableNameResolutionContext after it is done being mutated. The typechecker attempts to use ImmutableNameResolutionContext, so it needs to be run after ImmutableNameResolutionContext has been initialized (after all name resolution has been completed). Additionally, although I haven't seen any issues with lowering AST to HIR before name resolution 2.0 is complete, it makes sense to perform all lowering in lockstep as well. gcc/rust/ChangeLog: * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Add visitor for ExternCrate. * hir/rust-ast-lower-item.h (ASTLoweringItem::visit): Likewise. * rust-session-manager.cc (Session::load_extern_crate): Avoid lowering or type resolving external crates here. * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): Add visitor for ExternCrate. * typecheck/rust-hir-type-check-item.h (TypeCheckItem::visit): Replace empty definition with a declaration. Signed-off-by: Owen Avery --- gcc/rust/hir/rust-ast-lower-item.cc | 19 +++++++++++++++++++ gcc/rust/hir/rust-ast-lower-item.h | 1 + gcc/rust/rust-session-manager.cc | 8 -------- .../typecheck/rust-hir-type-check-item.cc | 19 +++++++++++++++++++ gcc/rust/typecheck/rust-hir-type-check-item.h | 2 +- 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc index acec008c8923..0623065ddd46 100644 --- a/gcc/rust/hir/rust-ast-lower-item.cc +++ b/gcc/rust/hir/rust-ast-lower-item.cc @@ -732,6 +732,25 @@ ASTLoweringItem::visit (AST::MacroRulesDefinition &def) lower_macro_definition (def); } +void +ASTLoweringItem::visit (AST::ExternCrate &extern_crate) +{ + if (extern_crate.references_self ()) + return; + + auto &mappings = Analysis::Mappings::get (); + CrateNum num + = mappings.lookup_crate_name (extern_crate.get_referenced_crate ()) + .value (); + AST::Crate &crate = mappings.get_ast_crate (num); + + auto saved_crate_num = mappings.get_current_crate (); + mappings.set_current_crate (num); + auto lowered = ASTLowering::Resolve (crate); + mappings.insert_hir_crate (std::move (lowered)); + mappings.set_current_crate (saved_crate_num); +} + HIR::SimplePath ASTLoweringSimplePath::translate (const AST::SimplePath &path) { diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 4e142ed5e7c4..dc750571d138 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -45,6 +45,7 @@ class ASTLoweringItem : public ASTLoweringBase void visit (AST::TraitImpl &impl_block) override; void visit (AST::ExternBlock &extern_block) override; void visit (AST::MacroRulesDefinition &rules_def) override; + void visit (AST::ExternCrate &extern_crate) override; private: ASTLoweringItem () : translated (nullptr) {} diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index d42ae6a3fda5..da11a6e57c27 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -1182,14 +1182,6 @@ Session::load_extern_crate (const std::string &crate_name, location_t locus) // name resolve it Resolver::NameResolution::Resolve (parsed_crate); - // perform hir lowering - std::unique_ptr lowered - = HIR::ASTLowering::Resolve (parsed_crate); - HIR::Crate &hir = mappings.insert_hir_crate (std::move (lowered)); - - // perform type resolution - Resolver::TypeResolution::Resolve (hir); - // always restore the crate_num mappings.set_current_crate (saved_crate_num); diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 5595dad22cc5..70622778a1c0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -737,6 +737,25 @@ TypeCheckItem::visit (HIR::ExternBlock &extern_block) } } +void +TypeCheckItem::visit (HIR::ExternCrate &extern_crate) +{ + if (extern_crate.references_self ()) + return; + + auto &mappings = Analysis::Mappings::get (); + CrateNum num + = mappings.lookup_crate_name (extern_crate.get_referenced_crate ()) + .value (); + HIR::Crate &crate = mappings.get_hir_crate (num); + + CrateNum saved_crate_num = mappings.get_current_crate (); + mappings.set_current_crate (num); + for (auto &item : crate.get_items ()) + TypeCheckItem::Resolve (*item); + mappings.set_current_crate (saved_crate_num); +} + std::pair, TyTy::RegionConstraints> TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block, bool &failure_flag) diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 56832e75ccdb..414694be2790 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -51,9 +51,9 @@ class TypeCheckItem : private TypeCheckBase, private HIR::HIRVisItemVisitor void visit (HIR::ImplBlock &impl_block) override; void visit (HIR::ExternBlock &extern_block) override; void visit (HIR::Trait &trait_block) override; + void visit (HIR::ExternCrate &extern_crate) override; // nothing to do - void visit (HIR::ExternCrate &) override {} void visit (HIR::UseDeclaration &) override {} protected: From 166e80232b0562db2e4493ecd44ebb155ebcac13 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 18 Jun 2025 18:25:14 +0100 Subject: [PATCH 089/161] gccrs: Fix ICE when constant is missing and expression This is an invalid test case and doesnt work with rustc, we dont fully pick up the errors. Nr2 does handle this and puts out an extra good diagnostic but the old NR doesnt so for now i added this to the exclude list and then when we remove old name resolver this issue goes away. Fixes Rust-GCC#3642 gcc/rust/ChangeLog: * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): check for has_expr * hir/rust-hir-dump.cc (Dump::visit): likewise * hir/tree/rust-hir-item.h: add has_expr helper * resolve/rust-ast-resolve-item.cc (ResolveItem::visit): check for has_expr * resolve/rust-ast-resolve-stmt.h: likewise * typecheck/rust-hir-type-check-stmt.cc (TypeCheckStmt::visit): likewise gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: nr2 puts out an extra error * rust/compile/issue-3642.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/hir/rust-ast-lower-item.cc | 4 +++- gcc/rust/hir/rust-hir-dump.cc | 3 ++- gcc/rust/hir/tree/rust-hir-item.h | 2 ++ gcc/rust/resolve/rust-ast-resolve-item.cc | 3 ++- gcc/rust/resolve/rust-ast-resolve-stmt.h | 3 ++- gcc/rust/typecheck/rust-hir-type-check-stmt.cc | 6 ++++++ gcc/testsuite/rust/compile/issue-3642.rs | 9 +++++++++ gcc/testsuite/rust/compile/nr2/exclude | 1 + 8 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/rust/compile/issue-3642.rs diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc index 0623065ddd46..4e5a747b2a98 100644 --- a/gcc/rust/hir/rust-ast-lower-item.cc +++ b/gcc/rust/hir/rust-ast-lower-item.cc @@ -367,7 +367,9 @@ ASTLoweringItem::visit (AST::ConstantItem &constant) HIR::Visibility vis = translate_visibility (constant.get_visibility ()); HIR::Type *type = ASTLoweringType::translate (constant.get_type (), true); - HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ()); + HIR::Expr *expr = nullptr; + if (constant.has_expr ()) + expr = ASTLoweringExpr::translate (constant.get_expr ()); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, constant.get_node_id (), diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index 098b3c1e2660..18589316e9f7 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -1926,7 +1926,8 @@ Dump::visit (ConstantItem &e) do_vis_item (e); put_field ("identifier", e.get_identifier ().as_string ()); visit_field ("type", e.get_type ()); - visit_field ("const_expr", e.get_expr ()); + if (e.has_expr ()) + visit_field ("const_expr", e.get_expr ()); end ("ConstantItem"); } diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index d61027732ab9..0f25b379dfa8 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -1797,6 +1797,8 @@ class ConstantItem : public VisItem, public ImplItem return *type; } + bool has_expr () const { return const_expr != nullptr; } + Expr &get_expr () { return *const_expr; } Identifier get_identifier () const { return identifier; } diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index 0937d6577c8b..1d5ebed99696 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -453,7 +453,8 @@ ResolveItem::visit (AST::ConstantItem &constant) resolve_visibility (constant.get_visibility ()); ResolveType::go (constant.get_type ()); - ResolveExpr::go (constant.get_expr (), path, cpath); + if (constant.has_expr ()) + ResolveExpr::go (constant.get_expr (), path, cpath); } void diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index d413a7c17ae6..d7145112c823 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -67,7 +67,8 @@ class ResolveStmt : public ResolverBase }); ResolveType::go (constant.get_type ()); - ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix); + if (constant.has_expr ()) + ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix); } void visit (AST::LetStmt &stmt) override diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc index 4e53856278f1..87141af509fd 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc @@ -60,6 +60,12 @@ void TypeCheckStmt::visit (HIR::ConstantItem &constant) { TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ()); + if (!constant.has_expr ()) + { + infered = type; + return; + } + TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); infered = coercion_site ( diff --git a/gcc/testsuite/rust/compile/issue-3642.rs b/gcc/testsuite/rust/compile/issue-3642.rs new file mode 100644 index 000000000000..6d9decc8616d --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3642.rs @@ -0,0 +1,9 @@ +#[lang = "sized"] +trait Sized {} + +pub trait T { + const D: i32 = { + // { dg-error "mismatched types, expected .i32. but got .()." "" { target *-*-* } .-1 } + const C: X; + }; +} diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 58a20146091f..b67d0e50a8a3 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -4,4 +4,5 @@ issue-1487.rs issue-2015.rs issue-3454.rs impl_trait_generic_arg.rs +issue-3642.rs # please don't delete the trailing newline From 841124380a4cf187bd265c02e9d048147bbc5584 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 19 Jun 2025 19:37:10 +0100 Subject: [PATCH 090/161] gccrs: Add test case showing RPIT working to close issue Fixes Rust-GCC#1486 gcc/testsuite/ChangeLog: * rust/execute/torture/issue-1481.rs: New test. Signed-off-by: Philip Herron --- .../rust/execute/torture/issue-1481.rs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 gcc/testsuite/rust/execute/torture/issue-1481.rs diff --git a/gcc/testsuite/rust/execute/torture/issue-1481.rs b/gcc/testsuite/rust/execute/torture/issue-1481.rs new file mode 100644 index 000000000000..2ff78d9b6055 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-1481.rs @@ -0,0 +1,35 @@ +/* { dg-output "called Foo::print\\(\\)\r*" } */ +/* { dg-options "-w" } */ + +#[lang = "sized"] +trait Sized {} + +trait Printable { + fn print(&self); +} + +struct Foo; + +impl Printable for Foo { + fn print(&self) { + // Simulate output + unsafe { + puts("called Foo::print()\0" as *const _ as *const i8); + } + } +} + +fn get_printable() -> impl Printable { + Foo +} + +extern "C" { + fn puts(s: *const i8); +} + +fn main() -> i32 { + let p = get_printable(); + p.print(); + + 0 +} From 7da95ee3af595dcc61ac699135df734ecacfe52b Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Sat, 24 May 2025 14:32:10 -0400 Subject: [PATCH 091/161] Move AST desugaring into expansion phase This fixes some issues with name resolution 2.0. gcc/rust/ChangeLog: * rust-session-manager.cc (Session::compile_crate): Move AST desugaring to... (Session::expansion): ...here and add a final TopLevel pass afterwards. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove entries. Signed-off-by: Owen Avery --- gcc/rust/rust-session-manager.cc | 18 ++++++++++++++---- gcc/testsuite/rust/compile/nr2/exclude | 4 ---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index da11a6e57c27..dbb3b47b8627 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -619,10 +619,6 @@ Session::compile_crate (const char *filename) expansion (parsed_crate, name_resolution_ctx); - AST::DesugarForLoops ().go (parsed_crate); - AST::DesugarQuestionMark ().go (parsed_crate); - AST::DesugarApit ().go (parsed_crate); - rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m"); if (options.dump_option_enabled (CompileOptions::EXPANSION_DUMP)) { @@ -986,6 +982,20 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx) rust_error_at (range, "reached recursion limit"); } + // handle AST desugaring + if (!saw_errors ()) + { + AST::DesugarForLoops ().go (crate); + AST::DesugarQuestionMark ().go (crate); + AST::DesugarApit ().go (crate); + + // HACK: we may need a final TopLevel pass + // however, this should not count towards the recursion limit + // and we don't need a full Early pass + if (flag_name_resolution_2_0) + Resolver2_0::TopLevel (ctx).go (crate); + } + // error reporting - check unused macros, get missing fragment specifiers // build test harness diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index b67d0e50a8a3..82faf1ae0ce4 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,8 +1,4 @@ issue-3315-2.rs torture/alt_patterns1.rs -issue-1487.rs -issue-2015.rs -issue-3454.rs -impl_trait_generic_arg.rs issue-3642.rs # please don't delete the trailing newline From 1a889f9fb7dbfe8601e75af1da9cea2fb79da1aa Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 20 Jun 2025 17:49:32 +0100 Subject: [PATCH 092/161] gccrs: Ensure we look at the bounds behind a reference When type checking expressions that involve references, we need to examine the bounds of the referenced type to properly resolve traits and methods. gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-expr.cc: Look at bounds behind references. * typecheck/rust-hir-type-check-expr.h: Add helper method. --- .../typecheck/rust-hir-type-check-expr.cc | 37 ++++++++++++++++--- gcc/rust/typecheck/rust-hir-type-check-expr.h | 3 +- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 81d95c83239f..753d3915f69f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -2086,16 +2086,13 @@ TypeCheckExpr::resolve_operator_overload ( HIR::PathIdentSegment TypeCheckExpr::resolve_possible_fn_trait_call_method_name ( - TyTy::BaseType &receiver, TyTy::TypeBoundPredicate *associated_predicate) + const TyTy::BaseType &receiver, + TyTy::TypeBoundPredicate *associated_predicate) { - // Question - // do we need to probe possible bounds here? I think not, i think when we - // support Fn traits they are explicitly specified - // FIXME // the logic to map the FnTrait to their respective call trait-item is // duplicated over in the backend/rust-compile-expr.cc - for (auto &bound : receiver.get_specified_bounds ()) + for (const auto &bound : receiver.get_specified_bounds ()) { bool found_fn = bound.get_name ().compare ("Fn") == 0; bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0; @@ -2118,6 +2115,34 @@ TypeCheckExpr::resolve_possible_fn_trait_call_method_name ( } } + if (receiver.is ()) + { + const auto &ref = static_cast (receiver); + const auto &underlying = *ref.get_base (); + for (const auto &bound : underlying.get_specified_bounds ()) + { + bool found_fn = bound.get_name ().compare ("Fn") == 0; + bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0; + bool found_fn_once = bound.get_name ().compare ("FnOnce") == 0; + + if (found_fn) + { + *associated_predicate = bound; + return HIR::PathIdentSegment ("call"); + } + else if (found_fn_mut) + { + *associated_predicate = bound; + return HIR::PathIdentSegment ("call_mut"); + } + else if (found_fn_once) + { + *associated_predicate = bound; + return HIR::PathIdentSegment ("call_once"); + } + } + } + // nothing *associated_predicate = TyTy::TypeBoundPredicate::error (); return HIR::PathIdentSegment (""); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index e0a3278fb82d..531197436853 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -109,7 +109,8 @@ class TypeCheckExpr : private TypeCheckBase, private HIR::HIRExpressionVisitor TyTy::BaseType **result); HIR::PathIdentSegment resolve_possible_fn_trait_call_method_name ( - TyTy::BaseType &receiver, TyTy::TypeBoundPredicate *associated_predicate); + const TyTy::BaseType &receiver, + TyTy::TypeBoundPredicate *associated_predicate); private: TypeCheckExpr (); From 8aea945e969f2c8029b4eb45fecd1e266bd61907 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 21 Jun 2025 14:22:04 +0100 Subject: [PATCH 093/161] gccrs: Fix cyclical projection to placeholder Prevent infinite loops when projecting associated types by properly handling cyclical references with placeholder types. gcc/rust/ChangeLog: * typecheck/rust-hir-trait-resolve.cc: Add cyclical projection protection. --- gcc/rust/typecheck/rust-hir-trait-resolve.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index 35c9b0a6a2d3..fccc53ed6c2d 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -444,11 +444,27 @@ TraitItemReference::associated_type_set (TyTy::BaseType *ty) const { rust_assert (get_trait_item_type () == TraitItemType::TYPE); + // this isnt super safe there are cases like the FnTraits where the type is + // set to the impls placeholder associated type. For example + // + // type Output = F::Output; -- see the fn trait impls in libcore + // + // then this projection ends up resolving back to this placeholder so it just + // ends up being cyclical + TyTy::BaseType *item_ty = get_tyty (); rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER); TyTy::PlaceholderType *placeholder = static_cast (item_ty); + if (ty->is ()) + { + const auto &projection = *static_cast (ty); + const auto resolved = projection.get (); + if (resolved == item_ty) + return; + } + placeholder->set_associated_type (ty->get_ty_ref ()); } From 367245854ff2f72bb5012f99463bfa7449b9fbca Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 17 Jun 2025 20:22:34 +0100 Subject: [PATCH 094/161] gccrs: Cleanup and refactor method resolution Refactor the dot operator implementation to improve code organization and maintainability while preserving existing functionality. gcc/rust/ChangeLog: * typecheck/rust-hir-dot-operator.cc: Major refactoring and cleanup. * typecheck/rust-hir-dot-operator.h: Add new helper methods. --- gcc/rust/typecheck/rust-hir-dot-operator.cc | 183 ++++++++++---------- gcc/rust/typecheck/rust-hir-dot-operator.h | 35 ++++ 2 files changed, 127 insertions(+), 91 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc index c1165e9e5b17..7b7944c508dd 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.cc +++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc @@ -102,26 +102,16 @@ MethodResolver::try_hook (const TyTy::BaseType &r) } } -bool -MethodResolver::select (TyTy::BaseType &receiver) +std::vector +MethodResolver::assemble_inherent_impl_candidates ( + const TyTy::BaseType &receiver) { - rust_debug ("MethodResolver::select reciever=[%s] path=[%s]", - receiver.debug_str ().c_str (), - segment_name.as_string ().c_str ()); - - struct impl_item_candidate - { - HIR::Function *item; - HIR::ImplBlock *impl_block; - TyTy::FnType *ty; - }; - + std::vector inherent_impl_fns; const TyTy::BaseType *raw = receiver.destructure (); bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER; bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF; - // assemble inherent impl items - std::vector inherent_impl_fns; + // Assemble inherent impl items (non-trait impl blocks) mappings.iterate_impl_items ( [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool { bool is_trait_impl = impl->has_trait_ref (); @@ -190,16 +180,19 @@ MethodResolver::select (TyTy::BaseType &receiver) return true; }); - struct trait_item_candidate - { - const HIR::TraitItemFunc *item; - const HIR::Trait *trait; - TyTy::FnType *ty; - const TraitReference *reference; - const TraitItemReference *item_ref; - }; + return inherent_impl_fns; +} + +void +MethodResolver::assemble_trait_impl_candidates ( + const TyTy::BaseType &receiver, + std::vector &impl_candidates, + std::vector &trait_candidates) +{ + const TyTy::BaseType *raw = receiver.destructure (); + bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER; + bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF; - std::vector trait_fns; mappings.iterate_impl_blocks ([&] (HirId id, HIR::ImplBlock *impl) mutable -> bool { bool is_trait_impl = impl->has_trait_ref (); @@ -266,7 +259,7 @@ MethodResolver::select (TyTy::BaseType &receiver) continue; } - inherent_impl_fns.push_back ({func, impl, fnty}); + impl_candidates.push_back ({func, impl, fnty}); return true; } @@ -293,26 +286,15 @@ MethodResolver::select (TyTy::BaseType &receiver) TyTy::FnType *fnty = static_cast (ty); trait_item_candidate candidate{func, trait, fnty, trait_ref, item_ref}; - trait_fns.push_back (candidate); + trait_candidates.push_back (candidate); return true; }); +} - // lookup specified bounds for an associated item - struct precdicate_candidate - { - TyTy::TypeBoundPredicateItem lookup; - TyTy::FnType *fntype; - }; - - // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L580-L694 - - rust_debug ("inherent_impl_fns found {%lu}, trait_fns found {%lu}, " - "predicate_items found {%lu}", - (unsigned long) inherent_impl_fns.size (), - (unsigned long) trait_fns.size (), - (unsigned long) predicate_items.size ()); - +bool +MethodResolver::try_select_predicate_candidates (TyTy::BaseType &receiver) +{ bool found_possible_candidate = false; for (const auto &predicate : predicate_items) { @@ -346,60 +328,33 @@ MethodResolver::select (TyTy::BaseType &receiver) found_possible_candidate = true; } } - if (found_possible_candidate) - { - return true; - } + return found_possible_candidate; +} - for (auto &impl_item : inherent_impl_fns) +bool +MethodResolver::try_select_inherent_impl_candidates ( + TyTy::BaseType &receiver, const std::vector &candidates, + bool trait_impl_blocks_only) +{ + bool found_possible_candidate = false; + for (auto &impl_item : candidates) { bool is_trait_impl_block = impl_item.impl_block->has_trait_ref (); - if (is_trait_impl_block) + if (trait_impl_blocks_only && !is_trait_impl_block) continue; - - TyTy::FnType *fn = impl_item.ty; - rust_assert (fn->is_method ()); - - TyTy::BaseType *fn_self = fn->get_self_type (); - rust_debug ("dot-operator impl_item fn_self={%s} can_eq receiver={%s}", - fn_self->debug_str ().c_str (), - receiver.debug_str ().c_str ()); - - auto res - = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION, - false /*allow-autoderef*/); - bool ok = !res.is_error (); - if (ok) - { - std::vector adjs = append_adjustments (res.adjustments); - PathProbeCandidate::ImplItemCandidate c{impl_item.item, - impl_item.impl_block}; - auto try_result = MethodCandidate{ - PathProbeCandidate (PathProbeCandidate::CandidateType::IMPL_FUNC, - fn, impl_item.item->get_locus (), c), - adjs}; - result.insert (std::move (try_result)); - found_possible_candidate = true; - } - } - if (found_possible_candidate) - { - return true; - } - - for (auto &impl_item : inherent_impl_fns) - { - bool is_trait_impl_block = impl_item.impl_block->has_trait_ref (); - if (!is_trait_impl_block) + if (!trait_impl_blocks_only && is_trait_impl_block) continue; TyTy::FnType *fn = impl_item.ty; rust_assert (fn->is_method ()); TyTy::BaseType *fn_self = fn->get_self_type (); - rust_debug ( - "dot-operator trait_impl_item fn_self={%s} can_eq receiver={%s}", - fn_self->debug_str ().c_str (), receiver.debug_str ().c_str ()); + + const char *debug_prefix + = trait_impl_blocks_only ? "trait_impl_item" : "impl_item"; + rust_debug ("dot-operator %s fn_self={%s} can_eq receiver={%s}", + debug_prefix, fn_self->debug_str ().c_str (), + receiver.debug_str ().c_str ()); auto res = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION, @@ -418,12 +373,15 @@ MethodResolver::select (TyTy::BaseType &receiver) found_possible_candidate = true; } } - if (found_possible_candidate) - { - return true; - } + return found_possible_candidate; +} - for (auto trait_item : trait_fns) +bool +MethodResolver::try_select_trait_impl_candidates ( + TyTy::BaseType &receiver, const std::vector &candidates) +{ + bool found_possible_candidate = false; + for (auto trait_item : candidates) { TyTy::FnType *fn = trait_item.ty; rust_assert (fn->is_method ()); @@ -451,10 +409,53 @@ MethodResolver::select (TyTy::BaseType &receiver) found_possible_candidate = true; } } - return found_possible_candidate; } +bool +MethodResolver::select (TyTy::BaseType &receiver) +{ + rust_debug ("MethodResolver::select reciever=[%s] path=[%s]", + receiver.debug_str ().c_str (), + segment_name.as_string ().c_str ()); + + // Assemble candidates + std::vector inherent_impl_fns + = assemble_inherent_impl_candidates (receiver); + std::vector trait_impl_fns; + std::vector trait_fns; + assemble_trait_impl_candidates (receiver, trait_impl_fns, trait_fns); + + // Combine inherent and trait impl functions + inherent_impl_fns.insert (inherent_impl_fns.end (), trait_impl_fns.begin (), + trait_impl_fns.end ()); + + // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L580-L694 + + rust_debug ("inherent_impl_fns found {%lu}, trait_fns found {%lu}, " + "predicate_items found {%lu}", + (unsigned long) inherent_impl_fns.size (), + (unsigned long) trait_fns.size (), + (unsigned long) predicate_items.size ()); + + // Try selection in the priority order defined by Rust's method resolution: + + // 1. Try predicate candidates first (highest priority) + if (try_select_predicate_candidates (receiver)) + return true; + + // 2. Try inherent impl functions (non-trait impl blocks) + if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns, false)) + return true; + + // 3. Try inherent impl functions from trait impl blocks + if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns, true)) + return true; + + // 4. Try trait functions (lowest priority) + return try_select_trait_impl_candidates (receiver, trait_fns); +} + std::vector MethodResolver::get_predicate_items ( const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver, diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h index ab95a5a40c45..cc40472e0faf 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.h +++ b/gcc/rust/typecheck/rust-hir-dot-operator.h @@ -65,6 +65,22 @@ class MethodResolver : private TypeCheckBase, protected AutoderefCycle const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver, const std::vector &specified_bounds); + struct impl_item_candidate + { + HIR::Function *item; + HIR::ImplBlock *impl_block; + TyTy::FnType *ty; + }; + + struct trait_item_candidate + { + const HIR::TraitItemFunc *item; + const HIR::Trait *trait; + TyTy::FnType *ty; + const TraitReference *reference; + const TraitItemReference *item_ref; + }; + protected: MethodResolver (bool autoderef_flag, const HIR::PathIdentSegment &segment_name); @@ -77,6 +93,25 @@ class MethodResolver : private TypeCheckBase, protected AutoderefCycle std::vector append_adjustments (const std::vector &adjustments) const; + std::vector + assemble_inherent_impl_candidates (const TyTy::BaseType &receiver); + + void assemble_trait_impl_candidates ( + const TyTy::BaseType &receiver, + std::vector &impl_candidates, + std::vector &trait_candidates); + + bool try_select_predicate_candidates (TyTy::BaseType &receiver); + + bool try_select_inherent_impl_candidates ( + TyTy::BaseType &receiver, + const std::vector &candidates, + bool trait_impl_blocks_only); + + bool try_select_trait_impl_candidates ( + TyTy::BaseType &receiver, + const std::vector &candidates); + private: // search const HIR::PathIdentSegment &segment_name; From 4ec1073e62f65511adee7b90795e37fc3c4c68d1 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 21 Jun 2025 15:40:50 +0100 Subject: [PATCH 095/161] gccrs: Refactor marker builtin trait assembly Rename assemble_sized_builtin to assemble_marker_builtins and reorganize the type matching to properly handle function pointers and closures with their associated traits (Fn, FnMut, FnOnce). gcc/rust/ChangeLog: * typecheck/rust-hir-type-bounds.h: Rename method. * typecheck/rust-tyty-bounds.cc: Refactor marker trait assembly and add proper Fn trait handling for function types. --- gcc/rust/typecheck/rust-hir-type-bounds.h | 2 +- gcc/rust/typecheck/rust-tyty-bounds.cc | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h index 82333f18685e..3cf77733e45a 100644 --- a/gcc/rust/typecheck/rust-hir-type-bounds.h +++ b/gcc/rust/typecheck/rust-hir-type-bounds.h @@ -37,7 +37,7 @@ class TypeBoundsProbe : public TypeCheckBase private: void scan (); - void assemble_sized_builtin (); + void assemble_marker_builtins (); void add_trait_bound (HIR::Trait *trait); void assemble_builtin_candidate (LangItem::Kind item); diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index 5d42f80221ee..a36f7712dac4 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -105,7 +105,7 @@ TypeBoundsProbe::scan () } // marker traits... - assemble_sized_builtin (); + assemble_marker_builtins (); // add auto trait bounds for (auto *auto_trait : mappings.get_auto_traits ()) @@ -113,7 +113,7 @@ TypeBoundsProbe::scan () } void -TypeBoundsProbe::assemble_sized_builtin () +TypeBoundsProbe::assemble_marker_builtins () { const TyTy::BaseType *raw = receiver->destructure (); @@ -132,7 +132,6 @@ TypeBoundsProbe::assemble_sized_builtin () case TyTy::POINTER: case TyTy::PARAM: case TyTy::FNDEF: - case TyTy::FNPTR: case TyTy::BOOL: case TyTy::CHAR: case TyTy::INT: @@ -140,7 +139,6 @@ TypeBoundsProbe::assemble_sized_builtin () case TyTy::FLOAT: case TyTy::USIZE: case TyTy::ISIZE: - case TyTy::CLOSURE: case TyTy::INFER: case TyTy::NEVER: case TyTy::PLACEHOLDER: @@ -149,6 +147,14 @@ TypeBoundsProbe::assemble_sized_builtin () assemble_builtin_candidate (LangItem::Kind::SIZED); break; + case TyTy::FNPTR: + case TyTy::CLOSURE: + assemble_builtin_candidate (LangItem::Kind::SIZED); + assemble_builtin_candidate (LangItem::Kind::FN_ONCE); + assemble_builtin_candidate (LangItem::Kind::FN); + assemble_builtin_candidate (LangItem::Kind::FN_MUT); + break; + // FIXME str and slice need to be moved and test cases updated case TyTy::SLICE: case TyTy::STR: From f1914edd4fcd86802ea6f7a031001e7cc4807690 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 21 Jun 2025 14:58:49 +0100 Subject: [PATCH 096/161] gccrs: Fix bug with bad type bindings not looking at super traits When resolving type bounds, we need to examine super traits to properly determine if type bindings are valid in the current context. gcc/rust/ChangeLog: * typecheck/rust-tyty-bounds.cc: Check super traits for type bindings. * typecheck/rust-tyty.h: Add helper methods for bound checking. --- gcc/rust/typecheck/rust-tyty-bounds.cc | 32 ++++++++++++++++++++------ gcc/rust/typecheck/rust-tyty.h | 3 +++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index a36f7712dac4..f5b18004c187 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -754,16 +754,34 @@ size_t TypeBoundPredicate::get_num_associated_bindings () const { size_t count = 0; + + get_trait_hierachy ([&count] (const Resolver::TraitReference &ref) { + for (const auto &trait_item : ref.get_trait_items ()) + { + bool is_associated_type + = trait_item.get_trait_item_type () + == Resolver::TraitItemReference::TraitItemType::TYPE; + if (is_associated_type) + count++; + } + }); + + return count; +} + +void +TypeBoundPredicate::get_trait_hierachy ( + std::function callback) const +{ auto trait_ref = get (); - for (const auto &trait_item : trait_ref->get_trait_items ()) + callback (*trait_ref); + + for (auto &super : super_traits) { - bool is_associated_type - = trait_item.get_trait_item_type () - == Resolver::TraitItemReference::TraitItemType::TYPE; - if (is_associated_type) - count++; + const auto &super_trait_ref = *super.get (); + callback (super_trait_ref); + super.get_trait_hierachy (callback); } - return count; } TypeBoundPredicateItem diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index c759521090da..e8ddd3e1d91d 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -593,6 +593,9 @@ class TypeBoundPredicate : public SubstitutionRef TypeBoundPredicate (mark_is_error); + void get_trait_hierachy ( + std::function callback) const; + DefId reference; location_t locus; bool error_flag; From 83c2110eb26c8aedaaa4190c1a14c0c906d2902f Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 20 Jun 2025 18:21:30 +0100 Subject: [PATCH 097/161] gccrs: Fix silly ordering bug in trait reference resolution Ensure proper ordering when resolving trait references to prevent incorrect type resolution in certain contexts. gcc/rust/ChangeLog: * typecheck/rust-hir-trait-reference.cc (TraitReference::on_resolved): ensure associated types are done first * typecheck/rust-hir-type-check-type.cc: Update call site. gcc/testsuite/ChangeLog: * rust/compile/silly-order-bug.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/typecheck/rust-hir-trait-reference.cc | 10 +++++++++- gcc/rust/typecheck/rust-hir-type-check-type.cc | 3 +-- gcc/testsuite/rust/compile/silly-order-bug.rs | 8 ++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/rust/compile/silly-order-bug.rs diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.cc b/gcc/rust/typecheck/rust-hir-trait-reference.cc index 83985f009893..88e270d510d2 100644 --- a/gcc/rust/typecheck/rust-hir-trait-reference.cc +++ b/gcc/rust/typecheck/rust-hir-trait-reference.cc @@ -342,7 +342,15 @@ TraitReference::on_resolved () { for (auto &item : item_refs) { - item.on_resolved (); + if (item.get_trait_item_type () + == TraitItemReference::TraitItemType::TYPE) + item.on_resolved (); + } + for (auto &item : item_refs) + { + if (item.get_trait_item_type () + != TraitItemReference::TraitItemType::TYPE) + item.on_resolved (); } } diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 18e04581ab83..f23352baacda 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -549,8 +549,7 @@ TypeCheckType::resolve_segments ( bool selfResolveOk = false; if (first_segment && tySegIsBigSelf - && context->block_context ().is_in_context () - && context->block_context ().peek ().is_impl_block ()) + && context->block_context ().is_in_context ()) { TypeCheckBlockContextItem ctx = context->block_context ().peek (); TyTy::BaseType *lookup = nullptr; diff --git a/gcc/testsuite/rust/compile/silly-order-bug.rs b/gcc/testsuite/rust/compile/silly-order-bug.rs new file mode 100644 index 000000000000..0d9cf1d8a884 --- /dev/null +++ b/gcc/testsuite/rust/compile/silly-order-bug.rs @@ -0,0 +1,8 @@ +#[lang = "sized"] +trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce { + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; + type Output; +} From 8701f5a9bcc2350ca95496da5c1e3e1e1a72e372 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 21 Jun 2025 16:08:28 +0100 Subject: [PATCH 098/161] gccrs: Add unify rules for fnptr and closures Its valid to unify a closure to an fnptr as we are working on the fn traits. There are still other issues but this is part of the patch set. gcc/rust/ChangeLog: * typecheck/rust-unify.cc (UnifyRules::expect_fnptr): add unify rules Signed-off-by: Philip Herron --- gcc/rust/typecheck/rust-unify.cc | 38 +++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 9144f2eafba4..2a981acaf3a7 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -1098,6 +1098,43 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) } break; + case TyTy::CLOSURE: + { + TyTy::ClosureType &type = *static_cast (rtype); + auto this_ret_type = ltype->get_return_type (); + auto other_ret_type = type.get_return_type (); + + auto unified_result + = resolve_subtype (TyTy::TyWithLocation (this_ret_type), + TyTy::TyWithLocation (other_ret_type)); + if (unified_result->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + + if (ltype->num_params () != type.get_num_params ()) + { + return new TyTy::ErrorType (0); + } + + for (size_t i = 0; i < ltype->num_params (); i++) + { + auto this_param = ltype->get_param_type_at (i); + auto other_param = type.get_param_type_at (i); + + auto unified_param + = resolve_subtype (TyTy::TyWithLocation (this_param), + TyTy::TyWithLocation (other_param)); + if (unified_param->get_kind () == TyTy::TypeKind::ERROR) + { + return new TyTy::ErrorType (0); + } + } + + return ltype->clone (); + } + break; + case TyTy::TUPLE: case TyTy::BOOL: case TyTy::CHAR: @@ -1117,7 +1154,6 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) case TyTy::PLACEHOLDER: case TyTy::PROJECTION: case TyTy::DYNAMIC: - case TyTy::CLOSURE: case TyTy::OPAQUE: case TyTy::ERROR: return new TyTy::ErrorType (0); From 0db8eb18c67d5d4cfa9d2f7864a54a981e01d080 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 20 Jun 2025 12:04:29 -0400 Subject: [PATCH 099/161] nr2.0: Fix resolution of constant items gcc/rust/ChangeLog: * resolve/rust-default-resolver.cc (DefaultResolver::visit): Call DefaultASTVisitor::visit even on ConstantItem instances without expressions. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove issue-3642.rs. Signed-off-by: Owen Avery --- gcc/rust/resolve/rust-default-resolver.cc | 22 +++++++++------------- gcc/testsuite/rust/compile/nr2/exclude | 1 - 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 5f5dd09ca6f1..cdd41e37b782 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -361,19 +361,15 @@ DefaultResolver::visit (AST::MatchExpr &expr) void DefaultResolver::visit (AST::ConstantItem &item) { - if (item.has_expr ()) - { - auto expr_vis_1 - = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; - - auto expr_vis_2 = [this, &item, &expr_vis_1] () { - ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), - std::move (expr_vis_1)); - }; - - // FIXME: Why do we need a Rib here? - ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2); - } + auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + auto expr_vis_2 = [this, &item, &expr_vis_1] () { + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + std::move (expr_vis_1)); + }; + + // FIXME: Why do we need a Rib here? + ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2); } void diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 82faf1ae0ce4..dfaba888dc51 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,4 +1,3 @@ issue-3315-2.rs torture/alt_patterns1.rs -issue-3642.rs # please don't delete the trailing newline From 8064f137b7dd52149a54732158ca07e962d7a4ce Mon Sep 17 00:00:00 2001 From: Zhi Heng Date: Sun, 22 Jun 2025 17:38:06 +0800 Subject: [PATCH 100/161] gccrs: Fix TupleStructPattern compilation throwing error Code for TupleStructPattern compilation previously only assumes that it is derived from an enum. This commit adds a check for that, and compiles non-enum TupleStructPatterns similarly to TuplePatterns if it is not an enum. gcc/rust/ChangeLog: * backend/rust-compile-pattern.cc(CompilePatternCheckExpr::visit(TupleStructPattern)): Fix error thrown when compiling non-enum TupleStructPattern. Signed-off-by: Yap Zhi Heng --- gcc/rust/backend/rust-compile-pattern.cc | 62 +++++++++++++------ .../rust/compile/match-tuplestructpattern.rs | 9 +++ .../torture/match-tuplestructpattern.rs | 12 ++++ 3 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/rust/compile/match-tuplestructpattern.rs create mode 100644 gcc/testsuite/rust/execute/torture/match-tuplestructpattern.rs diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index bd3aea01b537..cd1c77be5eb7 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -369,31 +369,55 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern) rust_assert (items_no_range.get_patterns ().size () == variant->num_fields ()); - size_t tuple_field_index = 0; - for (auto &pattern : items_no_range.get_patterns ()) + if (adt->is_enum ()) { - // find payload union field of scrutinee - tree payload_ref - = Backend::struct_field_expression (match_scrutinee_expr, 1, - pattern->get_locus ()); + size_t tuple_field_index = 0; + for (auto &pattern : items_no_range.get_patterns ()) + { + // find payload union field of scrutinee + tree payload_ref + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern->get_locus ()); - tree variant_ref - = Backend::struct_field_expression (payload_ref, variant_index, - pattern->get_locus ()); + tree variant_ref + = Backend::struct_field_expression (payload_ref, + variant_index, + pattern->get_locus ()); - tree field_expr - = Backend::struct_field_expression (variant_ref, - tuple_field_index++, - pattern->get_locus ()); + tree field_expr + = Backend::struct_field_expression (variant_ref, + tuple_field_index++, + pattern->get_locus ()); - tree check_expr_sub - = CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx); - check_expr = Backend::arithmetic_or_logical_expression ( - ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, - check_expr_sub, pattern->get_locus ()); + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern, field_expr, + ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern->get_locus ()); + } + } + else + { + // For non-enum TupleStructPatterns + size_t tuple_field_index = 0; + for (auto &pattern : items_no_range.get_patterns ()) + { + tree field_expr + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, + pattern->get_locus ()); + + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern, field_expr, + ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern->get_locus ()); + } } + break; } - break; } } diff --git a/gcc/testsuite/rust/compile/match-tuplestructpattern.rs b/gcc/testsuite/rust/compile/match-tuplestructpattern.rs new file mode 100644 index 000000000000..0dae71ea0051 --- /dev/null +++ b/gcc/testsuite/rust/compile/match-tuplestructpattern.rs @@ -0,0 +1,9 @@ +fn main() { + struct A (i32, i32); + let a = A (0, 1); + + match a { + A (0, 1) => {}, + _ => {} + } +} diff --git a/gcc/testsuite/rust/execute/torture/match-tuplestructpattern.rs b/gcc/testsuite/rust/execute/torture/match-tuplestructpattern.rs new file mode 100644 index 000000000000..323109cd4963 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/match-tuplestructpattern.rs @@ -0,0 +1,12 @@ +fn main() -> i32 { + struct A (i32, i32); + let a = A (0, 1); + let mut ret = 1; + + match a { + A (0, b) => { ret -= b }, + _ => {} + } + + ret +} From e807ca79474f59ebf3a21aecfca4fef8cfb6fc56 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 23 Jun 2025 11:21:02 +0100 Subject: [PATCH 101/161] gccrs: check for invalid const calls during code-gen Closure calls are not const so this is invalid. This patch fixes two bugs 1. Make the look at the parent context optional for generics 2. Ensure we look for non const calls during call expr code-gen Fixes Rust-GCC#3551 gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (CompileExpr::visit): add const call check * backend/rust-compile-item.cc (CompileItem::visit): ensure we upfront compile types where possible * backend/rust-compile-item.h: update header * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): make parent ctx optional gcc/testsuite/ChangeLog: * rust/compile/issue-3551.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/backend/rust-compile-expr.cc | 22 +++++++ gcc/rust/backend/rust-compile-item.cc | 60 +++++++++++++++++++ gcc/rust/backend/rust-compile-item.h | 8 +-- .../typecheck/rust-hir-type-check-expr.cc | 20 ++++--- gcc/testsuite/rust/compile/issue-3551.rs | 15 +++++ 5 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/rust/compile/issue-3551.rs diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index d8ddab5bd9aa..7a1e5a70ab69 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -1338,6 +1338,28 @@ CompileExpr::visit (HIR::CallExpr &expr) }; auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx); + if (ctx->const_context_p ()) + { + if (!FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn_address))) + { + rust_error_at (expr.get_locus (), + "calls in constants are limited to constant " + "functions, tuple structs and tuple variants"); + return; + } + + if (TREE_CODE (fn_address) == ADDR_EXPR) + { + tree fndecl = TREE_OPERAND (fn_address, 0); + if (!DECL_DECLARED_CONSTEXPR_P (fndecl)) + { + rust_error_at (expr.get_locus (), + "calls in constants are limited to constant " + "functions, tuple structs and tuple variants"); + return; + } + } + } // is this a closure call? bool possible_trait_call diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc index 3e7ea9a25e93..78f6f571e9ce 100644 --- a/gcc/rust/backend/rust-compile-item.cc +++ b/gcc/rust/backend/rust-compile-item.cc @@ -297,5 +297,65 @@ CompileItem::visit (HIR::Module &module) CompileItem::compile (item.get (), ctx); } +void +CompileItem::visit (HIR::TupleStruct &tuple_struct_decl) +{ + TyTy::BaseType *lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + tuple_struct_decl.get_mappings ().get_hirid (), &lookup)) + { + rust_error_at (tuple_struct_decl.get_locus (), "failed to resolve type"); + return; + } + + if (lookup->is_concrete ()) + TyTyResolveCompile::compile (ctx, lookup); +} + +void +CompileItem::visit (HIR::Enum &enum_decl) +{ + TyTy::BaseType *lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type (enum_decl.get_mappings ().get_hirid (), + &lookup)) + { + rust_error_at (enum_decl.get_locus (), "failed to resolve type"); + return; + } + + if (lookup->is_concrete ()) + TyTyResolveCompile::compile (ctx, lookup); +} + +void +CompileItem::visit (HIR::Union &union_decl) +{ + TyTy::BaseType *lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type (union_decl.get_mappings ().get_hirid (), + &lookup)) + { + rust_error_at (union_decl.get_locus (), "failed to resolve type"); + return; + } + + if (lookup->is_concrete ()) + TyTyResolveCompile::compile (ctx, lookup); +} + +void +CompileItem::visit (HIR::StructStruct &struct_decl) +{ + TyTy::BaseType *lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type (struct_decl.get_mappings ().get_hirid (), + &lookup)) + { + rust_error_at (struct_decl.get_locus (), "failed to resolve type"); + return; + } + + if (lookup->is_concrete ()) + TyTyResolveCompile::compile (ctx, lookup); +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index d9d946d25140..56baaabce877 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -44,9 +44,12 @@ class CompileItem : private HIRCompileBase, protected HIR::HIRStmtVisitor void visit (HIR::ImplBlock &impl_block) override; void visit (HIR::ExternBlock &extern_block) override; void visit (HIR::Module &module) override; + void visit (HIR::TupleStruct &tuple_struct) override; + void visit (HIR::Enum &enum_decl) override; + void visit (HIR::Union &union_decl) override; + void visit (HIR::StructStruct &struct_decl) override; // Empty visit for unused Stmt HIR nodes. - void visit (HIR::TupleStruct &) override {} void visit (HIR::EnumItem &) override {} void visit (HIR::EnumItemTuple &) override {} void visit (HIR::EnumItemStruct &) override {} @@ -57,9 +60,6 @@ class CompileItem : private HIRCompileBase, protected HIR::HIRStmtVisitor void visit (HIR::ExternCrate &) override {} void visit (HIR::UseDeclaration &) override {} void visit (HIR::TypeAlias &) override {} - void visit (HIR::StructStruct &) override {} - void visit (HIR::Enum &) override {} - void visit (HIR::Union &) override {} void visit (HIR::Trait &) override {} void visit (HIR::EmptyStmt &) override {} void visit (HIR::LetStmt &) override {} diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 753d3915f69f..eb50803814f4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -1726,16 +1726,22 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr) void TypeCheckExpr::visit (HIR::ClosureExpr &expr) { - TypeCheckContextItem current_context = context->peek_context (); - TyTy::FnType *current_context_fndecl = current_context.get_context_type (); - + std::vector subst_refs; HirId ref = expr.get_mappings ().get_hirid (); DefId id = expr.get_mappings ().get_defid (); - RustIdent ident{current_context_fndecl->get_ident ().path, expr.get_locus ()}; + RustIdent ident{CanonicalPath::create_empty (), expr.get_locus ()}; + + if (context->have_function_context ()) + { + TypeCheckContextItem current_context = context->peek_context (); + TyTy::FnType *current_context_fndecl + = current_context.get_context_type (); + + ident = RustIdent{current_context_fndecl->get_ident ().path, + expr.get_locus ()}; - // get from parent context - std::vector subst_refs - = current_context_fndecl->clone_substs (); + subst_refs = current_context_fndecl->clone_substs (); + } std::vector parameter_types; for (auto &p : expr.get_params ()) diff --git a/gcc/testsuite/rust/compile/issue-3551.rs b/gcc/testsuite/rust/compile/issue-3551.rs new file mode 100644 index 000000000000..6d6a8129885d --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3551.rs @@ -0,0 +1,15 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +struct Bug { + a: [(); (|| 0)()], + // { dg-error "calls in constants are limited to constant functions, tuple structs and tuple variants" "" { target *-*-* } .-1 } +} From 47f42f78ecdb7ae24659d4ed30c6106b7b6fbb98 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 23 Jun 2025 12:59:33 +0100 Subject: [PATCH 102/161] gccrs: Fix bug with non compiled const decl There was a sily bug where if you reorder this test case to declare A before B this test would work but its meant to work in any order. So this fixes the bug during code gen to fall back to our query compile system if this is needed. Fixes Rust-GCC#3525 gcc/rust/ChangeLog: * backend/rust-compile-resolve-path.cc: if this fails fall back to query compile gcc/testsuite/ChangeLog: * rust/compile/issue-3525.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/backend/rust-compile-resolve-path.cc | 13 +++++++++---- gcc/testsuite/rust/compile/issue-3525.rs | 6 ++++++ 2 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/rust/compile/issue-3525.rs diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 81d2dbb033f1..1ce9676913d3 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -187,13 +187,18 @@ ResolvePathRef::resolve_with_node_id ( } // Handle unit struct + tree resolved_item = error_mark_node; if (lookup->get_kind () == TyTy::TypeKind::ADT) - return attempt_constructor_expression_lookup (lookup, ctx, mappings, - expr_locus); + resolved_item + = attempt_constructor_expression_lookup (lookup, ctx, mappings, + expr_locus); + + if (!error_operand_p (resolved_item)) + return resolved_item; // let the query system figure it out - tree resolved_item = query_compile (ref, lookup, final_segment, mappings, - expr_locus, is_qualified_path); + resolved_item = query_compile (ref, lookup, final_segment, mappings, + expr_locus, is_qualified_path); if (resolved_item != error_mark_node) { TREE_USED (resolved_item) = 1; diff --git a/gcc/testsuite/rust/compile/issue-3525.rs b/gcc/testsuite/rust/compile/issue-3525.rs new file mode 100644 index 000000000000..84a7ebeee116 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3525.rs @@ -0,0 +1,6 @@ +// { dg-options "-w" } + +struct Foo(usize); + +const B: usize = A.0; +const A: Foo = Foo(123); From 0f6955fc8a1ee45ef18390a757b2964a66b9f58b Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Mon, 23 Jun 2025 12:33:54 -0400 Subject: [PATCH 103/161] Fix scan-assembler regexp in recurse2.rs gcc/testsuite/ChangeLog: * rust/compile/macros/builtin/recurse2.rs: Match "abheyho\0" as well as "abheyho", to handle slight differences in assembly output for null-terminated strings. Signed-off-by: Owen Avery --- gcc/testsuite/rust/compile/macros/builtin/recurse2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/testsuite/rust/compile/macros/builtin/recurse2.rs b/gcc/testsuite/rust/compile/macros/builtin/recurse2.rs index 73e6ab4aa6cd..fbb4b10e6545 100644 --- a/gcc/testsuite/rust/compile/macros/builtin/recurse2.rs +++ b/gcc/testsuite/rust/compile/macros/builtin/recurse2.rs @@ -34,7 +34,7 @@ fn print_str(s: &str) { } } -// { dg-final { scan-assembler {"abheyho"} } } +// { dg-final { scan-assembler {"abheyho(\\0)?"} } } static S: &str = concat!("a", 'b', a!(), a!(b c d e f a!()), '\0'); fn main() { From 29ce42724068d079b28e74e176144d0e15e5c9ba Mon Sep 17 00:00:00 2001 From: Ryutaro Okada <1015ryu88@gmail.com> Date: Mon, 23 Jun 2025 22:25:57 -0700 Subject: [PATCH 104/161] gccrs: Add getter for outer attributions gcc/rust/ChangeLog: * hir/tree/rust-hir-expr.h (MatchArm::get_outer_attrs): Add getter for outer attributions Signed-off-by: Ryutaro Okada <1015ryu88@gmail.com> --- gcc/rust/hir/tree/rust-hir-expr.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index bf278d68b31e..fcb4744fef4c 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2698,6 +2698,8 @@ struct MatchArm Expr &get_guard_expr () { return *guard_expr; } location_t get_locus () const { return locus; } + + AST::AttrVec &get_outer_attrs () { return outer_attrs; } }; /* A "match case" - a correlated match arm and resulting expression. Not From 058abfcfa64c5a92c8396c0c29560b8b9b5d3a55 Mon Sep 17 00:00:00 2001 From: Ryutaro Okada <1015ryu88@gmail.com> Date: Mon, 23 Jun 2025 22:28:59 -0700 Subject: [PATCH 105/161] gccrs: Add getter for non const lifetime object gcc/rust/ChangeLog: * hir/tree/rust-hir-item.h (SelfParam::get_lifetime): Add getter for non const lifetime object Signed-off-by: Ryutaro Okada <1015ryu88@gmail.com> --- gcc/rust/hir/tree/rust-hir-item.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 0f25b379dfa8..8cedfe8647dc 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -402,6 +402,8 @@ struct SelfParam const Lifetime &get_lifetime () const { return lifetime.value (); } + Lifetime &get_lifetime () { return lifetime.value (); } + std::string as_string () const; location_t get_locus () const { return locus; } From 02f65e91b31caae6e5872a4e1ff6a3bb44586738 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Mon, 23 Jun 2025 20:27:36 -0400 Subject: [PATCH 106/161] Create Rust::GGC::Ident This should make it easier for us to hand identifiers off to the back end. gcc/rust/ChangeLog: * Make-lang.in (GRS_OBJS): Add rust-ggc.o. * backend/rust-compile-base.cc (HIRCompileBase::compile_function): Adjust call to Backend::function. (HIRCompileBase::compile_constant_item): Likewise and adjust initialization of Backend::typed_identifier. * backend/rust-compile-expr.cc (CompileExpr::visit): Adjust call to Backend::label. * backend/rust-compile-type.cc (TyTyResolveCompile::visit): Adjust initialization of Backend::typed_identifier. * rust-backend.h: Add includes. (Backend::GGC::Ident): Use Rust::GGC::Ident. (struct typed_identifier): Store name as a GGC::Ident rather than a std::string and adjust constructors. (named_type): Take GGC::Ident/tl::optional rather than std::string. (global_variable): Likewise. (local_variable): Likewise. (parameter_variable): Likewise. (static_chain_variable): Likewise. (label): Likewise. (function): Likewise. * rust-gcc.cc (named_type): Likewise. (global_variable): Likewise. (local_variable): Likewise. (parameter_variable): Likewise. (static_chain_variable): Likewise. (label): Likewise. (function): Likewise. (function_defer_statement): Adjust call to Backend::label. (get_identifier_from_string): Remove function. (fill_in_fields): Handle adjustments to typed_identifier. * util/rust-ggc.cc: New file. * util/rust-ggc.h: New file. Signed-off-by: Owen Avery --- gcc/rust/Make-lang.in | 1 + gcc/rust/backend/rust-compile-base.cc | 7 +-- gcc/rust/backend/rust-compile-expr.cc | 11 ++--- gcc/rust/backend/rust-compile-type.cc | 2 +- gcc/rust/rust-backend.h | 43 +++++++++--------- gcc/rust/rust-gcc.cc | 61 +++++++++++--------------- gcc/rust/util/rust-ggc.cc | 41 +++++++++++++++++ gcc/rust/util/rust-ggc.h | 63 +++++++++++++++++++++++++++ 8 files changed, 164 insertions(+), 65 deletions(-) create mode 100644 gcc/rust/util/rust-ggc.cc create mode 100644 gcc/rust/util/rust-ggc.h diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 85614b3e2246..39013d86cfc8 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -238,6 +238,7 @@ GRS_OBJS = \ rust/rust-punycode.o \ rust/rust-unwrap-segment.o \ rust/rust-edition.o \ + rust/rust-ggc.o \ rust/rust-expand-format-args.o \ rust/rust-lang-item.o \ rust/rust-collect-lang-items.o \ diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index 84c4bcd3fe43..c9f9fbe76bfd 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -689,7 +689,7 @@ HIRCompileBase::compile_function ( unsigned int flags = 0; tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, - "" /* asm_name */, flags, locus); + tl::nullopt /* asm_name */, flags, locus); setup_fndecl (fndecl, is_main_fn, fntype->has_substitutions_defined (), visibility, qualifiers, outer_attrs); @@ -807,11 +807,12 @@ HIRCompileBase::compile_constant_item ( // machineary that we already have. This means the best approach is to // make a _fake_ function with a block so it can hold onto temps then // use our constexpr code to fold it completely or error_mark_node - Backend::typed_identifier receiver; + Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION); tree compiled_fn_type = Backend::function_type ( receiver, {}, {Backend::typed_identifier ("_", const_type, locus)}, NULL, locus); - tree fndecl = Backend::function (compiled_fn_type, ident, "", 0, locus); + tree fndecl + = Backend::function (compiled_fn_type, ident, tl::nullopt, 0, locus); TREE_READONLY (fndecl) = 1; tree enclosing_scope = NULL_TREE; diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 7a1e5a70ab69..3ce5961f10e1 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -714,7 +714,8 @@ CompileExpr::visit (HIR::LoopExpr &expr) loop_label.get_lifetime ().get_mappings ().get_hirid (), label); } - tree loop_begin_label = Backend::label (fnctx.fndecl, "", expr.get_locus ()); + tree loop_begin_label + = Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ()); tree loop_begin_label_decl = Backend::label_definition_statement (loop_begin_label); ctx->add_statement (loop_begin_label_decl); @@ -756,7 +757,8 @@ CompileExpr::visit (HIR::WhileLoopExpr &expr) start_location, end_location); ctx->push_block (loop_block); - tree loop_begin_label = Backend::label (fnctx.fndecl, "", expr.get_locus ()); + tree loop_begin_label + = Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ()); tree loop_begin_label_decl = Backend::label_definition_statement (loop_begin_label); ctx->add_statement (loop_begin_label_decl); @@ -1143,9 +1145,8 @@ CompileExpr::visit (HIR::MatchExpr &expr) // setup the end label so the cases can exit properly tree fndecl = fnctx.fndecl; location_t end_label_locus = expr.get_locus (); // FIXME - tree end_label - = Backend::label (fndecl, "" /* empty creates an artificial label */, - end_label_locus); + // tl::nullopt creates an artificial label + tree end_label = Backend::label (fndecl, tl::nullopt, end_label_locus); tree end_label_decl_statement = Backend::label_definition_statement (end_label); diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index 7e56a0f4e1be..c397b4beb4ca 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -189,7 +189,7 @@ TyTyResolveCompile::visit (const TyTy::ClosureType &type) void TyTyResolveCompile::visit (const TyTy::FnType &type) { - Backend::typed_identifier receiver; + Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION); std::vector parameters; std::vector results; diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index a0df21798808..2d813d91efd6 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -27,6 +27,8 @@ #include "rust-linemap.h" #include "rust-diagnostics.h" #include "util/rust-operators.h" +#include "util/rust-ggc.h" +#include "util/optional.h" #include "tree.h" #include "rust-gcc.h" @@ -42,21 +44,23 @@ class Bvariable; namespace Backend { +namespace GGC { + +using Rust::GGC::Ident; + +} // namespace GGC + void init (); // Name/type/location. Used for function parameters, struct fields, // interface methods. struct typed_identifier { - std::string name; + GGC::Ident name; tree type; location_t location; - typed_identifier () : name (), type (NULL_TREE), location (UNKNOWN_LOCATION) - {} - - typed_identifier (const std::string &a_name, tree a_type, - location_t a_location) + typed_identifier (GGC::Ident a_name, tree a_type, location_t a_location) : name (a_name), type (a_type), location (a_location) {} }; @@ -133,7 +137,7 @@ tree array_type (tree element_type, tree length); // created via placeholder_pointer_type, placeholder_struct_type, or // placeholder_array_type.. (It may be called for a pointer, // struct, or array type in a case like "type P *byte; type Q P".) -tree named_type (const std::string &name, tree, location_t); +tree named_type (GGC::Ident name, tree, location_t); // Return the size of a type. int64_t type_size (tree); @@ -314,8 +318,7 @@ void block_add_statements (tree, const std::vector &); // be put into a unique section if possible; this is intended to // permit the linker to garbage collect the variable if it is not // referenced. LOCATION is where the variable was defined. -Bvariable *global_variable (const std::string &name, - const std::string &asm_name, tree btype, +Bvariable *global_variable (GGC::Ident name, GGC::Ident asm_name, tree btype, bool is_external, bool is_hidden, bool in_unique_section, location_t location); @@ -339,18 +342,18 @@ void global_variable_set_init (Bvariable *, tree); // the function, as otherwise the variable would be on the heap). // LOCATION is where the variable is defined. For each local variable // the frontend will call init_statement to set the initial value. -Bvariable *local_variable (tree function, const std::string &name, tree type, +Bvariable *local_variable (tree function, GGC::Ident name, tree type, Bvariable *decl_var, location_t location); // Create a function parameter. This is an incoming parameter, not // a result parameter (result parameters are treated as local // variables). The arguments are as for local_variable. -Bvariable *parameter_variable (tree function, const std::string &name, - tree type, location_t location); +Bvariable *parameter_variable (tree function, GGC::Ident name, tree type, + location_t location); // Create a static chain parameter. This is the closure parameter. -Bvariable *static_chain_variable (tree function, const std::string &name, - tree type, location_t location); +Bvariable *static_chain_variable (tree function, GGC::Ident name, tree type, + location_t location); // Create a temporary variable. A temporary variable has no name, // just a type. We pass in FUNCTION and BLOCK in case they are @@ -369,10 +372,10 @@ Bvariable *temporary_variable (tree fndecl, tree bind_tree, tree type, // Labels. -// Create a new label. NAME will be empty if this is a label +// Create a new label. NAME will be tl::nullopt if this is a label // created by the frontend for a loop construct. The location is // where the label is defined. -tree label (tree, const std::string &name, location_t); +tree label (tree, tl::optional name, location_t); // Create a statement which defines a label. This statement will be // put into the codestream at the point where the label should be @@ -408,12 +411,12 @@ static const unsigned int function_does_not_return = 1 << 2; static const unsigned int function_in_unique_section = 1 << 3; // Declare or define a function of FNTYPE. -// NAME is the Go name of the function. ASM_NAME, if not the empty -// string, is the name that should be used in the symbol table; this +// NAME is the Go name of the function. ASM_NAME, if not tl::nullopt, +// is the name that should be used in the symbol table; this // will be non-empty if a magic extern comment is used. FLAGS is // bit flags described above. -tree function (tree fntype, const std::string &name, - const std::string &asm_name, unsigned int flags, location_t); +tree function (tree fntype, GGC::Ident name, tl::optional asm_name, + unsigned int flags, location_t); // Create a statement that runs all deferred calls for FUNCTION. This should // be a statement that looks like this in C++: diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index f440f79801b3..42cdc6ca7f1c 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -91,12 +91,6 @@ Bvariable::error_variable () // A helper function to create a GCC identifier from a C++ string. -static inline tree -get_identifier_from_string (const std::string &str) -{ - return get_identifier_with_length (str.data (), str.length ()); -} - namespace Backend { // Define the built-in functions that are exposed to GCCRust. @@ -609,7 +603,7 @@ fill_in_fields (tree fill, const std::vector &fields, tree *pp = &field_trees; for (const auto &p : fields) { - tree name_tree = get_identifier_from_string (p.name); + tree name_tree = p.name.as_tree (); tree type_tree = p.type; if (error_operand_p (type_tree)) return error_mark_node; @@ -675,7 +669,7 @@ fill_in_array (tree fill, tree element_type, tree length_tree) // Return a named version of a type. tree -named_type (const std::string &name, tree type, location_t location) +named_type (GGC::Ident name, tree type, location_t location) { if (error_operand_p (type)) return error_mark_node; @@ -688,15 +682,14 @@ named_type (const std::string &name, tree type, location_t location) || TREE_CODE (type) == COMPLEX_TYPE || TREE_CODE (type) == BOOLEAN_TYPE)) { - tree decl = build_decl (BUILTINS_LOCATION, TYPE_DECL, - get_identifier_from_string (name), type); + tree decl + = build_decl (BUILTINS_LOCATION, TYPE_DECL, name.as_tree (), type); TYPE_NAME (type) = decl; return type; } tree copy = build_variant_type_copy (type); - tree decl - = build_decl (location, TYPE_DECL, get_identifier_from_string (name), copy); + tree decl = build_decl (location, TYPE_DECL, name.as_tree (), copy); DECL_ORIGINAL_TYPE (decl) = type; TYPE_NAME (copy) = decl; return copy; @@ -1924,9 +1917,9 @@ convert_tree (tree type_tree, tree expr_tree, location_t location) // Make a global variable. Bvariable * -global_variable (const std::string &var_name, const std::string &asm_name, - tree type_tree, bool is_external, bool is_hidden, - bool in_unique_section, location_t location) +global_variable (GGC::Ident var_name, GGC::Ident asm_name, tree type_tree, + bool is_external, bool is_hidden, bool in_unique_section, + location_t location) { if (error_operand_p (type_tree)) return Bvariable::error_variable (); @@ -1936,8 +1929,7 @@ global_variable (const std::string &var_name, const std::string &asm_name, if ((is_external || !is_hidden) && int_size_in_bytes (type_tree) == 0) type_tree = non_zero_size_type (type_tree); - tree decl = build_decl (location, VAR_DECL, - get_identifier_from_string (var_name), type_tree); + tree decl = build_decl (location, VAR_DECL, var_name.as_tree (), type_tree); if (is_external) DECL_EXTERNAL (decl) = 1; else @@ -1945,11 +1937,11 @@ global_variable (const std::string &var_name, const std::string &asm_name, if (!is_hidden) { TREE_PUBLIC (decl) = 1; - SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); + SET_DECL_ASSEMBLER_NAME (decl, asm_name.as_tree ()); } else { - SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); + SET_DECL_ASSEMBLER_NAME (decl, asm_name.as_tree ()); } TREE_USED (decl) = 1; @@ -1989,13 +1981,12 @@ global_variable_set_init (Bvariable *var, tree expr_tree) // Make a local variable. Bvariable * -local_variable (tree function, const std::string &name, tree type_tree, +local_variable (tree function, GGC::Ident name, tree type_tree, Bvariable *decl_var, location_t location) { if (error_operand_p (type_tree)) return Bvariable::error_variable (); - tree decl = build_decl (location, VAR_DECL, get_identifier_from_string (name), - type_tree); + tree decl = build_decl (location, VAR_DECL, name.as_tree (), type_tree); DECL_CONTEXT (decl) = function; if (decl_var != NULL) @@ -2010,13 +2001,12 @@ local_variable (tree function, const std::string &name, tree type_tree, // Make a function parameter variable. Bvariable * -parameter_variable (tree function, const std::string &name, tree type_tree, +parameter_variable (tree function, GGC::Ident name, tree type_tree, location_t location) { if (error_operand_p (type_tree)) return Bvariable::error_variable (); - tree decl = build_decl (location, PARM_DECL, - get_identifier_from_string (name), type_tree); + tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree); DECL_CONTEXT (decl) = function; DECL_ARG_TYPE (decl) = type_tree; @@ -2027,13 +2017,12 @@ parameter_variable (tree function, const std::string &name, tree type_tree, // Make a static chain variable. Bvariable * -static_chain_variable (tree fndecl, const std::string &name, tree type_tree, +static_chain_variable (tree fndecl, GGC::Ident name, tree type_tree, location_t location) { if (error_operand_p (type_tree)) return Bvariable::error_variable (); - tree decl = build_decl (location, PARM_DECL, - get_identifier_from_string (name), type_tree); + tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree); DECL_CONTEXT (decl) = fndecl; DECL_ARG_TYPE (decl) = type_tree; TREE_USED (decl) = 1; @@ -2124,10 +2113,10 @@ temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree init_tree, // Make a label. tree -label (tree func_tree, const std::string &name, location_t location) +label (tree func_tree, tl::optional name, location_t location) { tree decl; - if (name.empty ()) + if (!name.has_value ()) { if (DECL_STRUCT_FUNCTION (func_tree) == NULL) push_struct_function (func_tree); @@ -2140,7 +2129,7 @@ label (tree func_tree, const std::string &name, location_t location) } else { - tree id = get_identifier_from_string (name); + tree id = name->as_tree (); decl = build_decl (location, LABEL_DECL, id, void_type_node); DECL_CONTEXT (decl) = func_tree; } @@ -2179,7 +2168,7 @@ label_address (tree label, location_t location) // Declare or define a new function. tree -function (tree functype, const std::string &name, const std::string &asm_name, +function (tree functype, GGC::Ident name, tl::optional asm_name, unsigned int flags, location_t location) { if (error_operand_p (functype)) @@ -2187,13 +2176,13 @@ function (tree functype, const std::string &name, const std::string &asm_name, gcc_assert (FUNCTION_POINTER_TYPE_P (functype)); functype = TREE_TYPE (functype); - tree id = get_identifier_from_string (name); + tree id = name.as_tree (); if (error_operand_p (id)) return error_mark_node; tree decl = build_decl (location, FUNCTION_DECL, id, functype); - if (!asm_name.empty ()) - SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); + if (asm_name.has_value ()) + SET_DECL_ASSEMBLER_NAME (decl, asm_name->as_tree ()); if ((flags & function_is_declaration) != 0) DECL_EXTERNAL (decl) = 1; @@ -2236,7 +2225,7 @@ function_defer_statement (tree function, tree undefer_tree, tree defer_tree, push_cfun (DECL_STRUCT_FUNCTION (function)); tree stmt_list = NULL; - tree label = Backend::label (function, "", location); + tree label = Backend::label (function, tl::nullopt, location); tree label_def = label_definition_statement (label); append_to_statement_list (label_def, &stmt_list); diff --git a/gcc/rust/util/rust-ggc.cc b/gcc/rust/util/rust-ggc.cc new file mode 100644 index 000000000000..0722af2b7188 --- /dev/null +++ b/gcc/rust/util/rust-ggc.cc @@ -0,0 +1,41 @@ +// Copyright (C) 2025 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 +// . + +#include "rust-ggc.h" +#include "stringpool.h" + +namespace Rust { + +namespace GGC { + +Ident::Ident (const char *str) : inner (get_identifier (str)) {} + +Ident::Ident (const std::string &str) + : inner (get_identifier_with_length (str.c_str (), str.length ())) +{} + +bool +Ident::operator== (const std::string &other) const +{ + // maybe_get_identifier_with_length doesn't seem to exist + return maybe_get_identifier (other.c_str ()) == inner; +} + +} // namespace GGC + +} // namespace Rust diff --git a/gcc/rust/util/rust-ggc.h b/gcc/rust/util/rust-ggc.h new file mode 100644 index 000000000000..da28edeffe0b --- /dev/null +++ b/gcc/rust/util/rust-ggc.h @@ -0,0 +1,63 @@ +// Copyright (C) 2025 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 +// . + +#ifndef RUST_GGC_H +#define RUST_GGC_H + +#include "rust-system.h" +#include "tree.h" + +namespace Rust { + +namespace GGC { + +class Ident +{ + tree inner; + +public: + Ident (const char *str); + Ident (const std::string &str); + + bool operator== (const Ident &other) const { return inner == other.inner; } + bool operator== (const std::string &other) const; + + const char *c_str () const { return IDENTIFIER_POINTER (inner); } + size_t size () const { return IDENTIFIER_LENGTH (inner); } + + bool empty () const { return !size (); } + + std::string as_string () const + { + return std::string (c_str (), c_str () + size ()); + } + + tree as_tree () const { return inner; } +}; + +static inline bool +operator== (const std::string &a, const Ident &b) +{ + return b == a; +} + +} // namespace GGC + +} // namespace Rust + +#endif // RUST_GGC_H From 9efe335b7e7d6fa7d242a486972dc29efff33495 Mon Sep 17 00:00:00 2001 From: Ryutaro Okada <1015ryu88@gmail.com> Date: Mon, 23 Jun 2025 22:03:09 -0700 Subject: [PATCH 107/161] gccrs: Implement default HIR visitor class gcc/rust/ChangeLog: * Make-lang.in: Scaffolding new rust-hir-visitor files * hir/tree/rust-hir-visitor.h (DefaultHIRVisitor): Declare default HIR visitor * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor): Define default HIR visitor Signed-off-by: Ryutaro Okada <1015ryu88@gmail.com> --- gcc/rust/Make-lang.in | 1 + gcc/rust/hir/tree/rust-hir-visitor.cc | 1179 +++++++++++++++++++++++++ gcc/rust/hir/tree/rust-hir-visitor.h | 305 +++++++ 3 files changed, 1485 insertions(+) create mode 100644 gcc/rust/hir/tree/rust-hir-visitor.cc diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 39013d86cfc8..2a2e79d29f5f 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -81,6 +81,7 @@ GRS_OBJS = \ rust/rust-ast-dump.o \ rust/rust-ast-collector.o \ rust/rust-ast-visitor.o \ + rust/rust-hir-visitor.o \ rust/rust-hir-dump.o \ rust/rust-session-manager.o \ rust/rust-compile.o \ diff --git a/gcc/rust/hir/tree/rust-hir-visitor.cc b/gcc/rust/hir/tree/rust-hir-visitor.cc new file mode 100644 index 000000000000..447606ebc8c4 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-visitor.cc @@ -0,0 +1,1179 @@ +// Copyright (C) 2021-2025 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 +// . + +#include "rust-expr.h" +#include "rust-hir-full-decls.h" +#include "rust-hir-visitor.h" +#include "rust-hir-full.h" +#include "rust-system.h" + +namespace Rust { +namespace HIR { + +void +DefaultHIRVisitor::walk (Lifetime &) +{} + +void +DefaultHIRVisitor::walk (LifetimeParam &lifetime_param) +{ + visit_outer_attrs (lifetime_param); + lifetime_param.get_lifetime ().accept_vis (*this); + for (Lifetime &lifetime_bound : lifetime_param.get_lifetime_bounds ()) + lifetime_bound.accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_generic_args (GenericArgs &generic_args) +{ + for (auto &lifetime : generic_args.get_lifetime_args ()) + lifetime.accept_vis (*this); + for (auto &type : generic_args.get_type_args ()) + type->accept_vis (*this); + for (auto &binding : generic_args.get_binding_args ()) + binding.get_type ().accept_vis (*this); + for (auto &const_arg : generic_args.get_const_args ()) + const_arg.get_expression ()->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (PathInExpression &path_in_expr) +{ + visit_outer_attrs (path_in_expr); + if (!path_in_expr.is_lang_item ()) + for (auto &segment : path_in_expr.get_segments ()) + visit_path_expr_segment (segment); +} + +void +DefaultHIRVisitor::walk (TypePathSegment &) +{} + +void +DefaultHIRVisitor::walk (TypePathSegmentFunction &segment_function) +{ + TypePathFunction &function_path = segment_function.get_function_path (); + if (function_path.has_inputs ()) + for (auto ¶m : function_path.get_params ()) + param->accept_vis (*this); + if (function_path.has_return_type ()) + function_path.get_return_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TypePathSegmentGeneric &segment_generic) +{ + if (segment_generic.has_generic_args ()) + visit_generic_args (segment_generic.get_generic_args ()); +} + +void +DefaultHIRVisitor::walk (TypePath &type_path) +{ + for (auto &segment : type_path.get_segments ()) + segment->accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_qualified_path_type (QualifiedPathType &path) +{ + path.get_type ().accept_vis (*this); + if (path.has_as_clause ()) + path.get_trait ().accept_vis (*this); +} + +// TODO: Implement visit_path_expr_segment +void +DefaultHIRVisitor::visit_path_expr_segment (PathExprSegment &segment) +{ + if (segment.has_generic_args ()) + visit_generic_args (segment.get_generic_args ()); +} + +void +DefaultHIRVisitor::walk (QualifiedPathInExpression &path_in_expr) +{ + visit_outer_attrs (path_in_expr); + visit_qualified_path_type (path_in_expr.get_path_type ()); + for (auto &segment : path_in_expr.get_segments ()) + visit_path_expr_segment (segment); +} + +void +DefaultHIRVisitor::walk (QualifiedPathInType &path_in_type) +{ + visit_qualified_path_type (path_in_type.get_path_type ()); + path_in_type.get_associated_segment ().accept_vis (*this); + for (auto &segment : path_in_type.get_segments ()) + segment->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (LiteralExpr &expr) +{ + visit_outer_attrs (expr); +} + +void +DefaultHIRVisitor::walk (BorrowExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (DereferenceExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ErrorPropagationExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (NegationExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ArithmeticOrLogicalExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_lhs ().accept_vis (*this); + expr.get_rhs ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ComparisonExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_lhs ().accept_vis (*this); + expr.get_rhs ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (LazyBooleanExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_lhs ().accept_vis (*this); + expr.get_rhs ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TypeCastExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_expr ().accept_vis (*this); + expr.get_type_to_convert_to ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (AssignmentExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_lhs ().accept_vis (*this); + expr.get_rhs ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (CompoundAssignmentExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_lhs ().accept_vis (*this); + expr.get_rhs ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (GroupedExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + expr.get_expr_in_parens ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ArrayElemsValues &elems) +{ + for (auto &elem : elems.get_values ()) + elem->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ArrayElemsCopied &elems) +{ + elems.get_elem_to_copy ().accept_vis (*this); + elems.get_num_copies_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ArrayExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + expr.get_internal_elements ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ArrayIndexExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_array_expr ().accept_vis (*this); + expr.get_index_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TupleExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + for (auto &elem : expr.get_tuple_elems ()) + elem->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TupleIndexExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_tuple_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructExprStruct &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + expr.get_struct_name ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructExprFieldIdentifier &) +{} + +void +DefaultHIRVisitor::walk (StructExprFieldIdentifierValue &field) +{ + field.get_value ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructExprFieldIndexValue &field) +{ + field.get_value ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructExprStructFields &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + expr.get_struct_name ().accept_vis (*this); + if (expr.has_struct_base ()) + { + StructBase &base = expr.get_struct_base (); + base.get_base ().accept_vis (*this); + } + for (auto &field : expr.get_fields ()) + field->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructExprStructBase &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + expr.get_struct_name ().accept_vis (*this); + StructBase &base = expr.get_struct_base (); + base.get_base ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (CallExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_fnexpr ().accept_vis (*this); + for (auto &arg : expr.get_arguments ()) + arg->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (MethodCallExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_receiver ().accept_vis (*this); + visit_path_expr_segment (expr.get_method_name ()); + for (auto &arg : expr.get_arguments ()) + arg->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (FieldAccessExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_receiver_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_closure_param (ClosureParam ¶m) +{ + visit_outer_attrs (param); + param.get_pattern ().accept_vis (*this); + if (param.has_type_given ()) + { + param.get_type ().accept_vis (*this); + } +} + +void +DefaultHIRVisitor::walk (ClosureExpr &expr) +{ + visit_outer_attrs (expr); + for (auto ¶m : expr.get_params ()) + visit_closure_param (param); + if (expr.has_return_type ()) + expr.get_return_type ().accept_vis (*this); + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (BlockExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + for (auto &stmt : expr.get_statements ()) + stmt->accept_vis (*this); + if (expr.has_expr ()) + expr.get_final_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ContinueExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_label ()) + expr.get_label ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (BreakExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_label ()) + expr.get_label ().accept_vis (*this); + + if (expr.has_break_expr ()) + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangeFromToExpr &expr) +{ + expr.get_from_expr ().accept_vis (*this); + expr.get_to_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangeFromExpr &expr) +{ + expr.get_from_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangeToExpr &expr) +{ + expr.get_to_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangeFullExpr &) +{} + +void +DefaultHIRVisitor::walk (RangeFromToInclExpr &expr) +{ + expr.get_from_expr ().accept_vis (*this); + expr.get_to_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangeToInclExpr &expr) +{ + expr.get_to_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ReturnExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_return_expr ()) + expr.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (UnsafeBlockExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_block_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_loop_label (LoopLabel &label) +{ + label.get_lifetime ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (LoopExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_loop_label ()) + visit_loop_label (expr.get_loop_label ()); + expr.get_loop_block ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (WhileLoopExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_loop_label ()) + visit_loop_label (expr.get_loop_label ()); + expr.get_predicate_expr ().accept_vis (*this); + expr.get_loop_block ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (WhileLetLoopExpr &expr) +{ + visit_outer_attrs (expr); + for (auto &pattern : expr.get_patterns ()) + pattern->accept_vis (*this); + if (expr.has_loop_label ()) + visit_loop_label (expr.get_loop_label ()); + expr.get_cond ().accept_vis (*this); + expr.get_loop_block ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (IfExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_if_condition ().accept_vis (*this); + expr.get_if_block ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (IfExprConseqElse &expr) +{ + reinterpret_cast (expr).accept_vis (*this); + expr.get_else_block ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_match_arm (MatchArm &arm) +{ + // visit_outer_attrs (arm); + for (auto &pattern : arm.get_patterns ()) + pattern->accept_vis (*this); + if (arm.has_match_arm_guard ()) + arm.get_guard_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_match_case (MatchCase &arm) +{ + visit_match_arm (arm.get_arm ()); + arm.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (MatchExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + expr.get_scrutinee_expr ().accept_vis (*this); + for (auto &arm : expr.get_match_cases ()) + visit_match_case (arm); +} + +void +DefaultHIRVisitor::walk (AwaitExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_awaited_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (AsyncBlockExpr &expr) +{ + visit_outer_attrs (expr); + expr.get_block_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (InlineAsm &expr) +{ + visit_outer_attrs (expr); + const auto &operands = expr.get_operands (); + using RegisterType = AST::InlineAsmOperand::RegisterType; + for (auto &operand : operands) + { + switch (operand.get_register_type ()) + { + case RegisterType::In: + { + operand.get_in ().expr->accept_vis (*this); + break; + } + case RegisterType::Out: + { + operand.get_out ().expr->accept_vis (*this); + break; + } + case RegisterType::InOut: + { + operand.get_in_out ().expr->accept_vis (*this); + break; + } + case RegisterType::SplitInOut: + { + operand.get_split_in_out ().in_expr->accept_vis (*this); + operand.get_split_in_out ().out_expr->accept_vis (*this); + break; + } + case RegisterType::Const: + { + operand.get_const ().anon_const.get_inner_expr ().accept_vis ( + *this); + break; + } + case RegisterType::Sym: + { + operand.get_sym ().expr->accept_vis (*this); + break; + } + case RegisterType::Label: + { + operand.get_label ().expr->accept_vis (*this); + break; + } + } + } +} + +void +DefaultHIRVisitor::walk (LlvmInlineAsm &expr) +{ + for (auto &output : expr.outputs) + output.expr->accept_vis (*this); + for (auto &input : expr.inputs) + input.expr->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TypeParam ¶m) +{ + visit_outer_attrs (param); + for (auto &bounds : param.get_type_param_bounds ()) + bounds->accept_vis (*this); + if (param.has_type ()) + param.get_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ConstGenericParam &const_param) +{ + visit_outer_attrs (const_param); + const_param.get_type ().accept_vis (*this); + if (const_param.has_default_expression ()) + const_param.get_default_expression ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (LifetimeWhereClauseItem &item) +{ + item.get_lifetime ().accept_vis (*this); + for (auto &bound : item.get_lifetime_bounds ()) + bound.accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TypeBoundWhereClauseItem &item) +{ + for (auto &lifetime : item.get_for_lifetimes ()) + lifetime.accept_vis (*this); + item.get_bound_type ().accept_vis (*this); + for (auto ¶m : item.get_type_param_bounds ()) + param->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (Module &module) +{ + visit_outer_attrs (module); + visit_inner_attrs (module); + for (auto &item : module.get_items ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ExternCrate &crate) +{ + visit_outer_attrs (crate); +} + +void +DefaultHIRVisitor::walk (UseTreeGlob &) +{} + +void +DefaultHIRVisitor::walk (UseTreeList &) +{} + +void +DefaultHIRVisitor::walk (UseTreeRebind &) +{} + +void +DefaultHIRVisitor::walk (UseDeclaration &) +{} + +void +DefaultHIRVisitor::visit_function_param (FunctionParam ¶m) +{ + param.get_param_name ().accept_vis (*this); + param.get_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (Function &function) +{ + visit_outer_attrs (function); + for (auto &generic : function.get_generic_params ()) + generic->accept_vis (*this); + for (auto ¶m : function.get_function_params ()) + visit_function_param (param); + if (function.has_return_type ()) + function.get_return_type ().accept_vis (*this); + if (function.has_where_clause ()) + visit_where_clause (function.get_where_clause ()); + function.get_definition ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TypeAlias &type_alias) +{ + visit_outer_attrs (type_alias); + for (auto &generic : type_alias.get_generic_params ()) + generic->accept_vis (*this); + if (type_alias.has_where_clause ()) + visit_where_clause (type_alias.get_where_clause ()); + type_alias.get_type_aliased ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_struct_field (StructField &field) +{ + field.get_field_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructStruct &struct_item) +{ + visit_outer_attrs (struct_item); + for (auto &generic : struct_item.get_generic_params ()) + generic->accept_vis (*this); + if (struct_item.has_where_clause ()) + visit_where_clause (struct_item.get_where_clause ()); + for (auto &field : struct_item.get_fields ()) + visit_struct_field (field); +} + +void +DefaultHIRVisitor::walk (TupleStruct &tuple_struct) +{ + visit_outer_attrs (tuple_struct); + for (auto &generic : tuple_struct.get_generic_params ()) + generic->accept_vis (*this); + if (tuple_struct.has_where_clause ()) + visit_where_clause (tuple_struct.get_where_clause ()); + for (auto &field : tuple_struct.get_fields ()) + field.get_field_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (EnumItem &item) +{ + visit_outer_attrs (item); +} + +void +DefaultHIRVisitor::walk (EnumItemTuple &item_tuple) +{ + reinterpret_cast (item_tuple).accept_vis (*this); + for (auto &field : item_tuple.get_tuple_fields ()) + field.get_field_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (EnumItemStruct &item_struct) +{ + reinterpret_cast (item_struct).accept_vis (*this); + for (auto &field : item_struct.get_struct_fields ()) + field.get_field_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (EnumItemDiscriminant &item) +{ + reinterpret_cast (item).accept_vis (*this); + item.get_discriminant_expression ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (Enum &enum_item) +{ + visit_outer_attrs (enum_item); + for (auto &generic : enum_item.get_generic_params ()) + generic->accept_vis (*this); + if (enum_item.has_where_clause ()) + visit_where_clause (enum_item.get_where_clause ()); + for (auto &item : enum_item.get_variants ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (Union &union_item) +{ + visit_outer_attrs (union_item); + for (auto &generic : union_item.get_generic_params ()) + generic->accept_vis (*this); + if (union_item.has_where_clause ()) + visit_where_clause (union_item.get_where_clause ()); + for (auto &variant : union_item.get_variants ()) + visit_struct_field (variant); +} + +void +DefaultHIRVisitor::walk (ConstantItem &const_item) +{ + visit_outer_attrs (const_item); + const_item.get_type ().accept_vis (*this); + const_item.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StaticItem &static_item) +{ + visit_outer_attrs (static_item); + static_item.get_type ().accept_vis (*this); + static_item.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_self_param (SelfParam &self_param) +{ + if (self_param.has_lifetime ()) + { + Lifetime lifetime = self_param.get_lifetime (); + lifetime.accept_vis (*this); + } + if (self_param.has_type ()) + self_param.get_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TraitItemFunc &item) +{ + visit_outer_attrs (item); + TraitFunctionDecl &decl = item.get_decl (); + for (auto &generic : decl.get_generic_params ()) + generic->accept_vis (*this); + if (decl.get_self ().has_value ()) + visit_self_param (decl.get_self ().value ()); + for (auto ¶m : decl.get_function_params ()) + visit_function_param (param); + if (decl.has_return_type ()) + decl.get_return_type ().accept_vis (*this); + if (decl.has_where_clause ()) + visit_where_clause (decl.get_where_clause ()); + if (item.has_definition ()) + item.get_block_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TraitItemConst &item) +{ + visit_outer_attrs (item); + item.get_type ().accept_vis (*this); + if (item.has_expr ()) + item.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TraitItemType &item) +{ + visit_outer_attrs (item); + for (auto &bound : item.get_type_param_bounds ()) + bound->accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_where_clause (const WhereClause &where_clause) +{ + for (auto &item : where_clause.get_items ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_where_clause (WhereClause &where_clause) +{ + for (auto &item : where_clause.get_items ()) + { + item->accept_vis (*this); + } +} + +void +DefaultHIRVisitor::walk (WhereClauseItem &node) +{} + +void +DefaultHIRVisitor::walk (Trait &trait) +{ + visit_outer_attrs (trait); + for (auto &generic : trait.get_generic_params ()) + generic->accept_vis (*this); + if (trait.has_where_clause ()) + visit_where_clause (trait.get_where_clause ()); + for (auto &bound : trait.get_type_param_bounds ()) + bound->accept_vis (*this); + for (auto &item : trait.get_trait_items ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ImplBlock &impl) +{ + visit_outer_attrs (impl); + for (auto &generic : impl.get_generic_params ()) + generic->accept_vis (*this); + impl.get_trait_ref ().accept_vis (*this); + impl.get_type ().accept_vis (*this); + if (impl.has_where_clause ()) + visit_where_clause (impl.get_where_clause ()); + visit_inner_attrs (impl); + for (auto &item : impl.get_impl_items ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ExternalStaticItem &item) +{ + visit_outer_attrs (item); + item.get_item_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::visit_named_function_param (NamedFunctionParam ¶m) +{ + param.get_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ExternalFunctionItem &item) +{ + visit_outer_attrs (item); + for (auto &generic : item.get_generic_params ()) + generic->accept_vis (*this); + for (auto ¶m : item.get_function_params ()) + visit_named_function_param (param); + if (item.has_return_type ()) + item.get_return_type ().accept_vis (*this); + if (item.has_where_clause ()) + visit_where_clause (item.get_where_clause ()); +} + +void +DefaultHIRVisitor::walk (ExternalTypeItem &item) +{ + visit_outer_attrs (item); +} + +void +DefaultHIRVisitor::walk (ExternBlock &block) +{ + visit_outer_attrs (block); + visit_inner_attrs (block); + for (auto &item : block.get_extern_items ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (LiteralPattern &) +{} + +void +DefaultHIRVisitor::walk (IdentifierPattern &pattern) +{ + if (pattern.has_subpattern ()) + pattern.get_subpattern ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (WildcardPattern &) +{} + +void +DefaultHIRVisitor::walk (RangePatternBoundLiteral &) +{} + +void +DefaultHIRVisitor::walk (RangePatternBoundPath &bound) +{ + bound.get_path ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangePatternBoundQualPath &bound) +{ + bound.get_qualified_path ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (RangePattern &pattern) +{ + pattern.get_lower_bound ().accept_vis (*this); + pattern.get_upper_bound ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ReferencePattern &pattern) +{ + pattern.get_referenced_pattern ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructPatternFieldTuplePat &field) +{ + visit_outer_attrs (field); + field.get_tuple_pattern ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructPatternFieldIdentPat &field) +{ + visit_outer_attrs (field); + field.get_pattern ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (StructPatternFieldIdent &field) +{ + visit_outer_attrs (field); +} + +void +DefaultHIRVisitor::walk (StructPattern &pattern) +{ + pattern.get_path ().accept_vis (*this); + StructPatternElements &elements = pattern.get_struct_pattern_elems (); + for (auto &field : elements.get_struct_pattern_fields ()) + field->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TupleStructItemsNoRange &tuple_items) +{ + for (auto &item : tuple_items.get_patterns ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TupleStructItemsRange &tuple_items) +{ + for (auto &lower : tuple_items.get_lower_patterns ()) + lower->accept_vis (*this); + for (auto &upper : tuple_items.get_upper_patterns ()) + upper->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TupleStructPattern &pattern) +{ + pattern.get_path ().accept_vis (*this); + pattern.get_items ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TuplePatternItemsMultiple &tuple_items) +{ + for (auto &pattern : tuple_items.get_patterns ()) + pattern->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TuplePatternItemsRanged &tuple_items) +{ + for (auto &lower : tuple_items.get_lower_patterns ()) + lower->accept_vis (*this); + for (auto &upper : tuple_items.get_upper_patterns ()) + upper->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TuplePattern &pattern) +{ + pattern.get_items ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (SlicePattern &pattern) +{ + for (auto &item : pattern.get_items ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (AltPattern &pattern) +{ + for (auto &item : pattern.get_alts ()) + item->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (EmptyStmt &stmt) +{} + +void +DefaultHIRVisitor::walk (LetStmt &stmt) +{ + visit_outer_attrs (stmt); + stmt.get_pattern ().accept_vis (*this); + if (stmt.has_type ()) + stmt.get_type ().accept_vis (*this); + if (stmt.has_init_expr ()) + stmt.get_init_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ExprStmt &stmt) +{ + stmt.get_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TraitBound &bound) +{ + for (auto &lifetime : bound.get_for_lifetimes ()) + lifetime.accept_vis (*this); + bound.get_path ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ImplTraitType &type) +{ + for (auto &bound : type.get_type_param_bounds ()) + bound->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TraitObjectType &type) +{ + for (auto &bound : type.get_type_param_bounds ()) + bound->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ParenthesisedType &type) +{ + type.get_type_in_parens ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (TupleType &type) +{ + for (auto &elem : type.get_elems ()) + elem->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (NeverType &type) +{} + +void +DefaultHIRVisitor::walk (RawPointerType &type) +{ + type.get_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ReferenceType &type) +{ + if (type.has_lifetime ()) + type.get_lifetime ().accept_vis (*this); + type.get_base_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (ArrayType &type) +{ + type.get_element_type ().accept_vis (*this); + type.get_size_expr ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (SliceType &type) +{ + type.get_element_type ().accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (InferredType &type) +{} + +void +DefaultHIRVisitor::walk (BareFunctionType &type) +{ + for (auto &lifetime : type.get_for_lifetimes ()) + lifetime.accept_vis (*this); + for (auto ¶m : type.get_function_params ()) + param.get_type ().accept_vis (*this); + if (type.has_return_type ()) + type.get_return_type ().accept_vis (*this); +} + +} // namespace HIR +} // namespace Rust \ No newline at end of file diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h index 43f00dd73b3f..544cf5128a5e 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.h +++ b/gcc/rust/hir/tree/rust-hir-visitor.h @@ -20,6 +20,7 @@ #define RUST_HIR_VISITOR_H #include "rust-hir-full-decls.h" +#include "rust-ast.h" namespace Rust { namespace HIR { @@ -155,6 +156,310 @@ class HIRFullVisitor virtual void visit (BareFunctionType &type) = 0; }; +class DefaultHIRVisitor : public HIRFullVisitor +{ +public: + virtual void visit_where_clause (WhereClause &); + virtual void visit_where_clause (const WhereClause &); + virtual void visit_named_function_param (NamedFunctionParam ¶m); + virtual void visit_function_param (FunctionParam ¶m); + virtual void visit_self_param (SelfParam ¶m); + virtual void visit_match_arm (MatchArm &arm); + virtual void visit_match_case (MatchCase &); + virtual void visit_struct_field (StructField &field); + virtual void visit_generic_args (GenericArgs &args); + virtual void visit_qualified_path_type (QualifiedPathType &); + virtual void visit_path_expr_segment (PathExprSegment &segment); + virtual void visit_closure_param (ClosureParam ¶m); + virtual void visit_loop_label (LoopLabel &); + + virtual void visit_attribute (AST::Attribute &attr) + { + visit_attribute (static_cast (attr)); + } + virtual void visit_attribute (const AST::Attribute &attr) {} + template void visit_outer_attrs (T &node) + { + for (auto &attr : node.get_outer_attrs ()) + visit_attribute (attr); + } + template void visit_inner_attrs (T &node) + { + for (auto &attr : node.get_inner_attrs ()) + visit_attribute (attr); + } + + virtual void visit (WhereClauseItem &node) { walk (node); } + + virtual void visit (Lifetime &node) override { walk (node); } + virtual void visit (LifetimeParam &node) override { walk (node); } + virtual void visit (PathInExpression &node) override { walk (node); } + virtual void visit (TypePathSegment &node) override { walk (node); } + virtual void visit (TypePathSegmentGeneric &node) override { walk (node); } + virtual void visit (TypePathSegmentFunction &node) override { walk (node); } + virtual void visit (TypePath &node) override { walk (node); } + virtual void visit (QualifiedPathInExpression &node) override { walk (node); } + virtual void visit (QualifiedPathInType &node) override { walk (node); } + virtual void visit (LiteralExpr &node) override { walk (node); } + virtual void visit (BorrowExpr &node) override { walk (node); } + virtual void visit (DereferenceExpr &node) override { walk (node); } + virtual void visit (ErrorPropagationExpr &node) override { walk (node); } + virtual void visit (NegationExpr &node) override { walk (node); } + virtual void visit (ArithmeticOrLogicalExpr &node) override { walk (node); } + virtual void visit (ComparisonExpr &node) override { walk (node); } + virtual void visit (LazyBooleanExpr &node) override { walk (node); } + virtual void visit (TypeCastExpr &node) override { walk (node); } + virtual void visit (AssignmentExpr &node) override { walk (node); } + virtual void visit (CompoundAssignmentExpr &node) override { walk (node); } + virtual void visit (GroupedExpr &node) override { walk (node); } + virtual void visit (ArrayElemsValues &node) override { walk (node); } + virtual void visit (ArrayElemsCopied &node) override { walk (node); } + virtual void visit (ArrayExpr &node) override { walk (node); } + virtual void visit (ArrayIndexExpr &node) override { walk (node); } + virtual void visit (TupleExpr &node) override { walk (node); } + virtual void visit (TupleIndexExpr &node) override { walk (node); } + virtual void visit (StructExprStruct &node) override { walk (node); } + virtual void visit (StructExprFieldIdentifier &node) override { walk (node); } + virtual void visit (StructExprFieldIdentifierValue &node) override + { + walk (node); + } + virtual void visit (StructExprFieldIndexValue &node) override { walk (node); } + virtual void visit (StructExprStructFields &node) override { walk (node); } + virtual void visit (StructExprStructBase &node) override { walk (node); } + virtual void visit (CallExpr &node) override { walk (node); } + virtual void visit (MethodCallExpr &node) override { walk (node); } + virtual void visit (FieldAccessExpr &node) override { walk (node); } + virtual void visit (ClosureExpr &node) override { walk (node); } + virtual void visit (BlockExpr &node) override { walk (node); } + virtual void visit (AnonConst &node) override { walk (node); } + virtual void visit (ConstBlock &node) override { walk (node); } + virtual void visit (ContinueExpr &node) override { walk (node); } + virtual void visit (BreakExpr &node) override { walk (node); } + virtual void visit (RangeFromToExpr &node) override { walk (node); } + virtual void visit (RangeFromExpr &node) override { walk (node); } + virtual void visit (RangeToExpr &node) override { walk (node); } + virtual void visit (RangeFullExpr &node) override { walk (node); } + virtual void visit (RangeFromToInclExpr &node) override { walk (node); } + virtual void visit (RangeToInclExpr &node) override { walk (node); } + virtual void visit (ReturnExpr &node) override { walk (node); } + virtual void visit (UnsafeBlockExpr &node) override { walk (node); } + virtual void visit (LoopExpr &node) override { walk (node); } + virtual void visit (WhileLoopExpr &node) override { walk (node); } + virtual void visit (WhileLetLoopExpr &node) override { walk (node); } + virtual void visit (IfExpr &node) override { walk (node); } + virtual void visit (IfExprConseqElse &node) override { walk (node); } + virtual void visit (MatchExpr &node) override { walk (node); } + virtual void visit (AwaitExpr &node) override { walk (node); } + virtual void visit (AsyncBlockExpr &node) override { walk (node); } + virtual void visit (InlineAsm &node) override { walk (node); } + virtual void visit (LlvmInlineAsm &node) override { walk (node); } + virtual void visit (TypeParam &node) override { walk (node); } + virtual void visit (ConstGenericParam &node) override { walk (node); } + virtual void visit (LifetimeWhereClauseItem &node) override { walk (node); } + virtual void visit (TypeBoundWhereClauseItem &node) override { walk (node); } + virtual void visit (Module &node) override { walk (node); } + virtual void visit (ExternCrate &node) override { walk (node); } + virtual void visit (UseTreeGlob &node) override { walk (node); } + virtual void visit (UseTreeList &node) override { walk (node); } + virtual void visit (UseTreeRebind &node) override { walk (node); } + virtual void visit (UseDeclaration &node) override { walk (node); } + virtual void visit (Function &node) override { walk (node); } + virtual void visit (TypeAlias &node) override { walk (node); } + virtual void visit (StructStruct &node) override { walk (node); } + virtual void visit (TupleStruct &node) override { walk (node); } + virtual void visit (EnumItem &node) override { walk (node); } + virtual void visit (EnumItemTuple &node) override { walk (node); } + virtual void visit (EnumItemStruct &node) override { walk (node); } + virtual void visit (EnumItemDiscriminant &node) override { walk (node); } + virtual void visit (Enum &node) override { walk (node); } + virtual void visit (Union &node) override { walk (node); } + virtual void visit (ConstantItem &node) override { walk (node); } + virtual void visit (StaticItem &node) override { walk (node); } + virtual void visit (TraitItemFunc &node) override { walk (node); } + virtual void visit (TraitItemConst &node) override { walk (node); } + virtual void visit (TraitItemType &node) override { walk (node); } + virtual void visit (Trait &node) override { walk (node); } + virtual void visit (ImplBlock &node) override { walk (node); } + virtual void visit (ExternalStaticItem &node) override { walk (node); } + virtual void visit (ExternalFunctionItem &node) override { walk (node); } + virtual void visit (ExternalTypeItem &node) override { walk (node); } + virtual void visit (ExternBlock &node) override { walk (node); } + virtual void visit (LiteralPattern &node) override { walk (node); } + virtual void visit (IdentifierPattern &node) override { walk (node); } + virtual void visit (WildcardPattern &node) override { walk (node); } + virtual void visit (RangePatternBoundLiteral &node) override { walk (node); } + virtual void visit (RangePatternBoundPath &node) override { walk (node); } + virtual void visit (RangePatternBoundQualPath &node) override { walk (node); } + virtual void visit (RangePattern &node) override { walk (node); } + virtual void visit (ReferencePattern &node) override { walk (node); } + virtual void visit (StructPatternFieldTuplePat &node) override + { + walk (node); + } + virtual void visit (StructPatternFieldIdentPat &node) override + { + walk (node); + } + virtual void visit (StructPatternFieldIdent &node) override { walk (node); } + virtual void visit (StructPattern &node) override { walk (node); } + virtual void visit (TupleStructItemsNoRange &node) override { walk (node); } + virtual void visit (TupleStructItemsRange &node) override { walk (node); } + virtual void visit (TupleStructPattern &node) override { walk (node); } + virtual void visit (TuplePatternItemsMultiple &node) override { walk (node); } + virtual void visit (TuplePatternItemsRanged &node) override { walk (node); } + virtual void visit (TuplePattern &node) override { walk (node); } + virtual void visit (SlicePattern &node) override { walk (node); } + virtual void visit (AltPattern &node) override { walk (node); } + virtual void visit (EmptyStmt &node) override { walk (node); } + virtual void visit (LetStmt &node) override { walk (node); } + virtual void visit (ExprStmt &node) override { walk (node); } + virtual void visit (TraitBound &node) override { walk (node); } + virtual void visit (ImplTraitType &node) override { walk (node); } + virtual void visit (TraitObjectType &node) override { walk (node); } + virtual void visit (ParenthesisedType &node) override { walk (node); } + virtual void visit (TupleType &node) override { walk (node); } + virtual void visit (NeverType &node) override { walk (node); } + virtual void visit (RawPointerType &node) override { walk (node); } + virtual void visit (ReferenceType &node) override { walk (node); } + virtual void visit (ArrayType &node) override { walk (node); } + virtual void visit (SliceType &node) override { walk (node); } + virtual void visit (InferredType &node) override { walk (node); } + virtual void visit (BareFunctionType &node) override { walk (node); } + +protected: + virtual void walk (WhereClauseItem &) final; + + virtual void walk (Lifetime &) final; + virtual void walk (LifetimeParam &) final; + virtual void walk (PathInExpression &) final; + virtual void walk (TypePathSegment &) final; + virtual void walk (TypePathSegmentGeneric &) final; + virtual void walk (TypePathSegmentFunction &) final; + virtual void walk (TypePath &) final; + virtual void walk (QualifiedPathInExpression &) final; + virtual void walk (QualifiedPathInType &) final; + + virtual void walk (LiteralExpr &) final; + virtual void walk (BorrowExpr &) final; + virtual void walk (DereferenceExpr &) final; + virtual void walk (ErrorPropagationExpr &) final; + virtual void walk (NegationExpr &) final; + virtual void walk (ArithmeticOrLogicalExpr &) final; + virtual void walk (ComparisonExpr &) final; + virtual void walk (LazyBooleanExpr &) final; + virtual void walk (TypeCastExpr &) final; + virtual void walk (AssignmentExpr &) final; + virtual void walk (CompoundAssignmentExpr &) final; + virtual void walk (GroupedExpr &) final; + + virtual void walk (ArrayElemsValues &) final; + virtual void walk (ArrayElemsCopied &) final; + virtual void walk (ArrayExpr &) final; + virtual void walk (ArrayIndexExpr &) final; + virtual void walk (TupleExpr &) final; + virtual void walk (TupleIndexExpr &) final; + virtual void walk (StructExprStruct &) final; + virtual void walk (StructExprFieldIdentifier &) final; + virtual void walk (StructExprFieldIdentifierValue &) final; + virtual void walk (StructExprFieldIndexValue &) final; + virtual void walk (StructExprStructFields &) final; + virtual void walk (StructExprStructBase &) final; + virtual void walk (CallExpr &) final; + virtual void walk (MethodCallExpr &) final; + virtual void walk (FieldAccessExpr &) final; + virtual void walk (ClosureExpr &) final; + virtual void walk (BlockExpr &) final; + virtual void walk (AnonConst &) final; + virtual void walk (ConstBlock &) final; + virtual void walk (ContinueExpr &) final; + virtual void walk (BreakExpr &) final; + virtual void walk (RangeFromToExpr &) final; + virtual void walk (RangeFromExpr &) final; + virtual void walk (RangeToExpr &) final; + virtual void walk (RangeFullExpr &) final; + virtual void walk (RangeFromToInclExpr &) final; + virtual void walk (RangeToInclExpr &) final; + virtual void walk (ReturnExpr &) final; + virtual void walk (UnsafeBlockExpr &) final; + virtual void walk (LoopExpr &) final; + virtual void walk (WhileLoopExpr &) final; + virtual void walk (WhileLetLoopExpr &) final; + virtual void walk (IfExpr &) final; + virtual void walk (IfExprConseqElse &) final; + virtual void walk (MatchExpr &) final; + virtual void walk (AwaitExpr &) final; + virtual void walk (AsyncBlockExpr &) final; + virtual void walk (InlineAsm &) final; + virtual void walk (LlvmInlineAsm &) final; + virtual void walk (TypeParam &) final; + virtual void walk (ConstGenericParam &) final; + virtual void walk (LifetimeWhereClauseItem &) final; + virtual void walk (TypeBoundWhereClauseItem &) final; + virtual void walk (Module &) final; + virtual void walk (ExternCrate &) final; + virtual void walk (UseTreeGlob &) final; + virtual void walk (UseTreeList &) final; + virtual void walk (UseTreeRebind &) final; + virtual void walk (UseDeclaration &) final; + virtual void walk (Function &) final; + virtual void walk (TypeAlias &) final; + virtual void walk (StructStruct &) final; + virtual void walk (TupleStruct &) final; + virtual void walk (EnumItem &) final; + virtual void walk (EnumItemTuple &) final; + virtual void walk (EnumItemStruct &) final; + virtual void walk (EnumItemDiscriminant &) final; + virtual void walk (Enum &) final; + virtual void walk (Union &) final; + virtual void walk (ConstantItem &) final; + virtual void walk (StaticItem &) final; + virtual void walk (TraitItemFunc &) final; + virtual void walk (TraitItemConst &) final; + virtual void walk (TraitItemType &) final; + virtual void walk (Trait &) final; + virtual void walk (ImplBlock &) final; + virtual void walk (ExternalStaticItem &) final; + virtual void walk (ExternalFunctionItem &) final; + virtual void walk (ExternalTypeItem &) final; + virtual void walk (ExternBlock &) final; + virtual void walk (LiteralPattern &) final; + virtual void walk (IdentifierPattern &) final; + virtual void walk (WildcardPattern &) final; + virtual void walk (RangePatternBoundLiteral &) final; + virtual void walk (RangePatternBoundPath &) final; + virtual void walk (RangePatternBoundQualPath &) final; + virtual void walk (RangePattern &) final; + virtual void walk (ReferencePattern &) final; + virtual void walk (StructPatternFieldTuplePat &) final; + virtual void walk (StructPatternFieldIdentPat &) final; + virtual void walk (StructPatternFieldIdent &) final; + virtual void walk (StructPattern &) final; + virtual void walk (TupleStructItemsNoRange &) final; + virtual void walk (TupleStructItemsRange &) final; + virtual void walk (TupleStructPattern &) final; + virtual void walk (TuplePatternItemsMultiple &) final; + virtual void walk (TuplePatternItemsRanged &) final; + virtual void walk (TuplePattern &) final; + virtual void walk (SlicePattern &) final; + virtual void walk (AltPattern &) final; + virtual void walk (EmptyStmt &) final; + virtual void walk (LetStmt &) final; + virtual void walk (ExprStmt &) final; + virtual void walk (TraitBound &) final; + virtual void walk (ImplTraitType &) final; + virtual void walk (TraitObjectType &) final; + virtual void walk (ParenthesisedType &) final; + virtual void walk (TupleType &) final; + virtual void walk (NeverType &) final; + virtual void walk (RawPointerType &) final; + virtual void walk (ReferenceType &) final; + virtual void walk (ArrayType &) final; + virtual void walk (SliceType &) final; + virtual void walk (InferredType &) final; + virtual void walk (BareFunctionType &) final; +}; + class HIRFullVisitorBase : public HIRFullVisitor { public: From c1d572b2671555e732881199a33e70de9da2c110 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Mon, 23 Jun 2025 23:10:34 -0400 Subject: [PATCH 108/161] Update C++ version check in rust-lang.cc gcc/rust/ChangeLog: * rust-lang.cc: Move version check from C++11 to C++14. Signed-off-by: Owen Avery --- gcc/rust/rust-lang.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc index 35003ab327b7..93ce041c2529 100644 --- a/gcc/rust/rust-lang.cc +++ b/gcc/rust/rust-lang.cc @@ -51,10 +51,10 @@ // FIXME: test saving intellisense #include "options.h" -// version check to stop compiling if c++ isn't c++11 or higher -#if __cplusplus < 201103 +// version check to stop compiling if c++ isn't c++14 or higher +#if __cplusplus < 201402 #error \ - "GCC Rust frontend requires C++11 or higher. You can compile the g++ frontend first and then compile the Rust frontend using that." + "GCC Rust frontend requires C++14 or higher. You can compile the g++ frontend first and then compile the Rust frontend using that." #endif // TODO: is this best way to do it? Is it allowed? (should be) From 61c5bf06ad880c229c2c8e0daa517ac1d587c02a Mon Sep 17 00:00:00 2001 From: Zhi Heng Date: Thu, 26 Jun 2025 22:33:15 +0800 Subject: [PATCH 109/161] gccrs: Implement type checking for ItemType::RANGED in TuplePattern This patch implements the previously unimplemented type checking for RANGED item type for TuplePattern, which serves as the start for implementing compilation of RestPattern. gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(TuplePattern)): Implement type checking for ItemType::RANGED. Signed-off-by: Yap Zhi Heng --- .../typecheck/rust-hir-type-check-pattern.cc | 73 +++++++++++++++---- 1 file changed, 58 insertions(+), 15 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index 15d8620dc2ad..d87916ec7985 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -463,6 +463,17 @@ void TypeCheckPattern::visit (HIR::TuplePattern &pattern) { std::unique_ptr items; + + // Check whether parent is tuple + auto resolved_parent = parent->destructure (); + if (resolved_parent->get_kind () != TyTy::TUPLE) + { + rust_error_at (pattern.get_locus (), "expected %s, found tuple", + parent->as_string ().c_str ()); + return; + } + TyTy::TupleType &par = *static_cast (resolved_parent); + switch (pattern.get_items ().get_item_type ()) { case HIR::TuplePatternItems::ItemType::MULTIPLE: @@ -470,19 +481,9 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) auto &ref = static_cast ( pattern.get_items ()); - auto resolved_parent = parent->destructure (); - if (resolved_parent->get_kind () != TyTy::TUPLE) - { - rust_error_at (pattern.get_locus (), "expected %s, found tuple", - parent->as_string ().c_str ()); - break; - } - const auto &patterns = ref.get_patterns (); size_t nitems_to_resolve = patterns.size (); - TyTy::TupleType &par - = *static_cast (resolved_parent); if (patterns.size () != par.get_fields ().size ()) { emit_pattern_size_error (pattern, par.get_fields ().size (), @@ -507,11 +508,53 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) case HIR::TuplePatternItems::ItemType::RANGED: { - // HIR::TuplePatternItemsRanged &ref - // = *static_cast ( - // pattern.get_items ().get ()); - // TODO - rust_unreachable (); + HIR::TuplePatternItemsRanged &ref + = static_cast (pattern.get_items ()); + + // Check whether size of lower and upper patterns <= parent size + const auto &lower = ref.get_lower_patterns (); + const auto &upper = ref.get_upper_patterns (); + size_t min_size_required = lower.size () + upper.size (); + + if (par.get_fields ().size () > min_size_required) + { + emit_pattern_size_error (pattern, par.get_fields ().size (), + min_size_required); + // TODO attempt to continue to do typechecking even after wrong size + break; + } + + // Resolve lower patterns + std::vector pattern_elems; + for (size_t i = 0; i < lower.size (); i++) + { + auto &p = lower[i]; + TyTy::BaseType *par_type = par.get_field (i); + + TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type); + pattern_elems.push_back (TyTy::TyVar (elem->get_ref ())); + } + + // Pad pattern_elems until needing to resolve upper patterns + size_t rest_end = par.get_fields ().size () - upper.size (); + for (size_t i = lower.size (); i < rest_end; i++) + { + TyTy::BaseType *par_type = par.get_field (i); + pattern_elems.push_back (TyTy::TyVar (par_type->get_ref ())); + } + + // Resolve upper patterns + for (size_t i = 0; i < upper.size (); i++) + { + auto &p = upper[i]; + TyTy::BaseType *par_type = par.get_field (rest_end + i); + + TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type); + pattern_elems.push_back (TyTy::TyVar (elem->get_ref ())); + } + + infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (), + pattern.get_locus (), pattern_elems); } break; } From de92e92951ad3bd41bf6f493da425c02ec0ae6a1 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Mon, 16 Jun 2025 17:05:09 -0400 Subject: [PATCH 110/161] nr2.0: Adjust resolution of external crates This ensures Session::load_extern_crate doesn't try to use the old name resolver when nr2.0 is enabled, while also ensuring that nr2.0 handles external crates. gcc/rust/ChangeLog: * resolve/rust-default-resolver.cc (DefaultResolver::visit_extern_crate): New function. (DefaultResolver::visit): New visitor function for ExternCrate. * resolve/rust-default-resolver.h (DefaultResolver::visit_extern_crate): New function. (DefaultResolver::visit): New visitor function for ExternCrate. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Adjust ExternCrate visitor and rename to... (TopLevel::visit_extern_crate): ...here. * resolve/rust-toplevel-name-resolver-2.0.h (TopLevel::visit): Remove ExternCrate visitor override. (TopLevel::visit_extern_crate): New function. * rust-session-manager.cc (Session::load_extern_crate): Only run name resolution 1.0 if name resolution 2.0 is disabled. Signed-off-by: Owen Avery --- gcc/rust/resolve/rust-default-resolver.cc | 41 ++++++++++++ gcc/rust/resolve/rust-default-resolver.h | 3 + .../rust-toplevel-name-resolver-2.0.cc | 66 +++++++------------ .../resolve/rust-toplevel-name-resolver-2.0.h | 2 +- gcc/rust/rust-session-manager.cc | 9 ++- 5 files changed, 74 insertions(+), 47 deletions(-) diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index cdd41e37b782..588caa4e6f0c 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -394,5 +394,46 @@ DefaultResolver::visit (AST::TypeParam ¶m) ctx.scoped (Rib::Kind::ForwardTypeParamBan, param.get_node_id (), expr_vis); } +void +DefaultResolver::visit_extern_crate (AST::ExternCrate &extern_crate, + AST::Crate &crate, CrateNum num) +{ + visit (crate); +} + +void +DefaultResolver::visit (AST::ExternCrate &crate) +{ + auto &mappings = Analysis::Mappings::get (); + auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ()); + + if (!num_opt) + { + rust_error_at (crate.get_locus (), "unknown crate %qs", + crate.get_referenced_crate ().c_str ()); + return; + } + + CrateNum num = *num_opt; + + AST::Crate &referenced_crate = mappings.get_ast_crate (num); + + auto sub_visitor_1 + = [&, this] () { visit_extern_crate (crate, referenced_crate, num); }; + + auto sub_visitor_2 = [&] () { + ctx.canonical_ctx.scope_crate (referenced_crate.get_node_id (), + crate.get_referenced_crate (), + std::move (sub_visitor_1)); + }; + + if (crate.has_as_clause ()) + ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (), + sub_visitor_2, crate.get_as_clause ()); + else + ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (), + sub_visitor_2, crate.get_referenced_crate ()); +} + } // namespace Resolver2_0 } // namespace Rust diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 99fd8e77a48d..3fa037911075 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -58,6 +58,9 @@ class DefaultResolver : public AST::DefaultASTVisitor void visit (AST::TypeParam &) override; + virtual void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum); + void visit (AST::ExternCrate &) override; + // type dec nodes, which visit their fields or variants by default void visit (AST::StructStruct &) override; void visit (AST::TupleStruct &) override; diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index 3e5ed534e4e6..8ec31c0351ff 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -173,19 +173,10 @@ insert_macros (std::vector ¯os, NameResolutionContext &ctx) } void -TopLevel::visit (AST::ExternCrate &crate) +TopLevel::visit_extern_crate (AST::ExternCrate &extern_crate, AST::Crate &crate, + CrateNum num) { auto &mappings = Analysis::Mappings::get (); - auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ()); - - if (!num_opt) - { - rust_error_at (crate.get_locus (), "unknown crate %qs", - crate.get_referenced_crate ().c_str ()); - return; - } - - CrateNum num = *num_opt; auto attribute_macros = mappings.lookup_attribute_proc_macros (num); @@ -193,40 +184,27 @@ TopLevel::visit (AST::ExternCrate &crate) auto derive_macros = mappings.lookup_derive_proc_macros (num); - auto sub_visitor_1 = [&] () { - // TODO: Find a way to keep this part clean without the double dispatch. - if (derive_macros.has_value ()) - { - insert_macros (derive_macros.value (), ctx); - for (auto ¯o : derive_macros.value ()) - mappings.insert_derive_proc_macro_def (macro); - } - if (attribute_macros.has_value ()) - { - insert_macros (attribute_macros.value (), ctx); - for (auto ¯o : attribute_macros.value ()) - mappings.insert_attribute_proc_macro_def (macro); - } - if (bang_macros.has_value ()) - { - insert_macros (bang_macros.value (), ctx); - for (auto ¯o : bang_macros.value ()) - mappings.insert_bang_proc_macro_def (macro); - } - }; - - auto sub_visitor_2 = [&] () { - ctx.canonical_ctx.scope_crate (crate.get_node_id (), - crate.get_referenced_crate (), - std::move (sub_visitor_1)); - }; + // TODO: Find a way to keep this part clean without the double dispatch. + if (derive_macros.has_value ()) + { + insert_macros (derive_macros.value (), ctx); + for (auto ¯o : derive_macros.value ()) + mappings.insert_derive_proc_macro_def (macro); + } + if (attribute_macros.has_value ()) + { + insert_macros (attribute_macros.value (), ctx); + for (auto ¯o : attribute_macros.value ()) + mappings.insert_attribute_proc_macro_def (macro); + } + if (bang_macros.has_value ()) + { + insert_macros (bang_macros.value (), ctx); + for (auto ¯o : bang_macros.value ()) + mappings.insert_bang_proc_macro_def (macro); + } - if (crate.has_as_clause ()) - ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor_2, - crate.get_as_clause ()); - else - ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor_2, - crate.get_referenced_crate ()); + visit (crate); } static bool diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h index 0dfd654861b3..8d3da92961ad 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -176,7 +176,7 @@ class TopLevel : public DefaultResolver void visit (AST::Union &union_item) override; void visit (AST::ConstantItem &const_item) override; void visit (AST::TypeAlias &type_item) override; - void visit (AST::ExternCrate &crate) override; + void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum) override; void visit (AST::TypeParam &type_param) override; void visit (AST::ConstGenericParam &const_param) override; diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index dbb3b47b8627..3252fcdcc6c0 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -1189,8 +1189,13 @@ Session::load_extern_crate (const std::string &crate_name, location_t locus) mappings.insert_bang_proc_macros (crate_num, bang_macros); mappings.insert_derive_proc_macros (crate_num, derive_macros); - // name resolve it - Resolver::NameResolution::Resolve (parsed_crate); + // if flag_name_resolution_2_0 is enabled + // then we perform resolution later + if (!flag_name_resolution_2_0) + { + // name resolve it + Resolver::NameResolution::Resolve (parsed_crate); + } // always restore the crate_num mappings.set_current_crate (saved_crate_num); From 7349d239bd3f8d3d2d11de88418dcedc64fcd8b9 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Fri, 27 Jun 2025 13:31:17 +0200 Subject: [PATCH 111/161] Add locus getters gcc/rust/ChangeLog: * ast/rust-expr.h: Add getter to locus field. * ast/rust-pattern.h (tokenid_to_rangekind): Likewise. * hir/tree/rust-hir-item.h: Likewise. * hir/tree/rust-hir-visibility.h: Likewise. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-expr.h | 6 ++++++ gcc/rust/ast/rust-pattern.h | 2 +- gcc/rust/hir/tree/rust-hir-item.h | 2 ++ gcc/rust/hir/tree/rust-hir-visibility.h | 2 ++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 8f44d5878bbf..21e856bb1d0e 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1192,6 +1192,8 @@ class ArrayElemsValues : public ArrayElems std::string as_string () const override; + location_t get_locus () const { return locus; } + void accept_vis (ASTVisitor &vis) override; // TODO: this mutable getter seems really dodgy. Think up better way. @@ -1248,6 +1250,8 @@ class ArrayElemsCopied : public ArrayElems std::string as_string () const override; + location_t get_locus () const { return locus; } + void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? @@ -1777,6 +1781,8 @@ struct StructBase std::string as_string () const; + location_t get_locus () const { return locus; } + // TODO: is this better? Or is a "vis_block" better? Expr &get_base_struct () { diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index b9c0fd9bb2f1..57c065ff6955 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -948,7 +948,7 @@ class StructPattern : public Pattern * is empty). */ bool has_struct_pattern_elems () const { return !elems.is_empty (); } - location_t get_locus () const override { return path.get_locus (); } + location_t get_locus () const override { return locus; } void accept_vis (ASTVisitor &vis) override; diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 8cedfe8647dc..d9df6029c5ac 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -209,6 +209,8 @@ class LifetimeWhereClauseItem : public WhereClauseItem std::string as_string () const override; + location_t get_locus () const { return locus; } + void accept_vis (HIRFullVisitor &vis) override; Lifetime &get_lifetime () { return lifetime; } diff --git a/gcc/rust/hir/tree/rust-hir-visibility.h b/gcc/rust/hir/tree/rust-hir-visibility.h index a750d88f284d..9dd6ff292674 100644 --- a/gcc/rust/hir/tree/rust-hir-visibility.h +++ b/gcc/rust/hir/tree/rust-hir-visibility.h @@ -73,6 +73,8 @@ struct Visibility } std::string as_string () const; + + location_t get_locus () const { return locus; } }; } // namespace HIR } // namespace Rust From 083d350e48eb1e3db9c7c9c3696c431054f2399d Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Sat, 24 May 2025 11:51:29 -0400 Subject: [PATCH 112/161] nr2.0: Add more checks for alternate patterns gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (visit_identifier_as_pattern): Handle is_ref and is_mut. (Late::visit): Likewise. * resolve/rust-name-resolution-context.cc (BindingLayer::insert_ident): Likewise. (BindingLayer::bind_test): Handle changes to BindingLayer fields. (BindingLayer::merge): Likewise and emit more error messages. * resolve/rust-name-resolution-context.h (struct IdentifierMode): New. (Binding::has_expected_bindings): New field. (Binding::set): Rename field to... (Binding::idents): ...here and convert from a set to a map. (Binding::Binding): Initialize has_expected_bindings. (BindingLayer::insert_ident): Adjust parameters. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove torture/alt_patterns1.rs. Signed-off-by: Owen Avery --- .../resolve/rust-late-name-resolver-2.0.cc | 11 ++-- .../resolve/rust-name-resolution-context.cc | 59 +++++++++++++++++-- .../resolve/rust-name-resolution-context.h | 26 +++++++- gcc/testsuite/rust/compile/nr2/exclude | 1 - 4 files changed, 83 insertions(+), 14 deletions(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 6e63d7078c7b..bd15894268c1 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -211,7 +211,7 @@ Late::visit (AST::LetStmt &let) static void visit_identifier_as_pattern (NameResolutionContext &ctx, const Identifier &ident, location_t locus, - NodeId node_id) + NodeId node_id, bool is_ref, bool is_mut) { // do we insert in labels or in values // but values does not allow shadowing... since functions cannot shadow @@ -232,7 +232,7 @@ visit_identifier_as_pattern (NameResolutionContext &ctx, return; } - ctx.bindings.peek ().insert_ident (ident); + ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut); if (ctx.bindings.peek ().is_or_bound (ident)) { @@ -255,7 +255,9 @@ Late::visit (AST::IdentifierPattern &identifier) visit_identifier_as_pattern (ctx, identifier.get_ident (), identifier.get_locus (), - identifier.get_node_id ()); + identifier.get_node_id (), + identifier.get_is_ref (), + identifier.get_is_mut ()); } void @@ -286,7 +288,8 @@ void Late::visit (AST::StructPatternFieldIdent &field) { visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (), - field.get_node_id ()); + field.get_node_id (), field.is_ref (), + field.is_mut ()); } void diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc index 34615ed97c32..1b84f1d7cfa3 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -33,7 +33,8 @@ BindingLayer::bind_test (Identifier ident, Binding::Kind kind) { for (auto &bind : bindings) { - if (bind.set.find (ident) != bind.set.cend () && bind.kind == kind) + if (bind.idents.find (ident.as_string ()) != bind.idents.cend () + && bind.kind == kind) { return true; } @@ -60,20 +61,66 @@ BindingLayer::is_or_bound (Identifier ident) } void -BindingLayer::insert_ident (Identifier ident) +BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref, + bool is_mut) { - bindings.back ().set.insert (ident); + bindings.back ().idents.emplace ( + std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut))); } void BindingLayer::merge () { - auto last_binding = bindings.back (); + auto last_binding = std::move (bindings.back ()); bindings.pop_back (); - for (auto &value : last_binding.set) + + if (bindings.back ().has_expected_bindings) { - bindings.back ().set.insert (value); + for (auto &value : bindings.back ().idents) + { + auto ident = value.first; + if (last_binding.idents.find (ident) == last_binding.idents.end ()) + { + location_t locus = value.second.first; + rust_error_at (locus, ErrorCode::E0408, + "variable %qs is not bound in all patterns", + ident.c_str ()); + } + } } + + for (auto &value : last_binding.idents) + { + auto res = bindings.back ().idents.emplace (value); + if (res.second) + { + if (bindings.back ().has_expected_bindings) + { + auto &ident = value.first; + location_t locus = value.second.first; + rust_error_at (locus, ErrorCode::E0408, + "variable %qs is not bound in all patterns", + ident.c_str ()); + } + } + else + { + auto this_mode = value.second.second; + auto other_mode = res.first->second.second; + if (this_mode != other_mode) + { + auto &ident = value.first; + location_t locus = value.second.first; + rust_error_at (locus, ErrorCode::E0409, + "variable %qs is bound inconsistently across " + "pattern alternatives", + ident.c_str ()); + } + } + } + + if (bindings.back ().kind == Binding::Kind::Or) + bindings.back ().has_expected_bindings = true; } BindingSource diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index bb8519a04933..0180919db7e7 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -158,6 +158,22 @@ class Definition NodeId id; }; +struct IdentifierMode +{ + bool is_ref; + bool is_mut; + + IdentifierMode (bool is_ref, bool is_mut) : is_ref (is_ref), is_mut (is_mut) + {} + + bool operator== (const IdentifierMode &other) + { + return other.is_ref == is_ref && other.is_mut == is_mut; + } + + bool operator!= (const IdentifierMode &other) { return !(*this == other); } +}; + struct Binding { enum class Kind @@ -166,9 +182,12 @@ struct Binding Or, } kind; - std::unordered_set set; + // used to check the correctness of or-bindings + bool has_expected_bindings; + + std::unordered_map> idents; - Binding (Binding::Kind kind) : kind (kind) {} + Binding (Binding::Kind kind) : kind (kind), has_expected_bindings (false) {} }; /** @@ -208,7 +227,8 @@ class BindingLayer */ bool is_or_bound (Identifier ident); - void insert_ident (Identifier ident); + void insert_ident (std::string ident, location_t locus, bool is_ref, + bool is_mut); void merge (); diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index dfaba888dc51..43d7a0dc9116 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,3 +1,2 @@ issue-3315-2.rs -torture/alt_patterns1.rs # please don't delete the trailing newline From 7736b49833cecb0954274757004c19517f2e2cd4 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Thu, 29 May 2025 17:04:46 -0400 Subject: [PATCH 113/161] nr2.0: Adjust resolution of modules This prioritizes resolution in the language prelude over resolution as a module. gcc/rust/ChangeLog: * resolve/rust-forever-stack.hxx (ForeverStack::resolve_path): Resolve final segments which point to modules. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Avoid inserting module names into ribs in the type namespace. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove issue-3315-2.rs. Signed-off-by: Owen Avery --- gcc/rust/resolve/rust-forever-stack.hxx | 42 ++++++++++++++++++- .../rust-toplevel-name-resolver-2.0.cc | 2 - gcc/testsuite/rust/compile/nr2/exclude | 1 - 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 582e53b16022..1ed87b3d55b4 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -687,7 +687,7 @@ ForeverStack::resolve_path ( if (!res) res = get_lang_prelude (seg.as_string ()); - if (!res && N == Namespace::Types) + if (N == Namespace::Types && !res) { if (seg.is_crate_path_seg ()) { @@ -719,6 +719,26 @@ ForeverStack::resolve_path ( // TODO: does NonShadowable matter? return Rib::Definition::NonShadowable (id); } + else + { + // HACK: check for a module after we check the language prelude + for (auto &kv : + find_closest_module (starting_point.get ()).children) + { + auto &link = kv.first; + + if (link.path.map_or ( + [&seg] (Identifier path) { + auto &path_str = path.as_string (); + return path_str == seg.as_string (); + }, + false)) + { + insert_segment_resolution (outer_seg, kv.second.id); + return Rib::Definition::NonShadowable (kv.second.id); + } + } + } } if (res && !res->is_ambiguous ()) @@ -751,6 +771,26 @@ ForeverStack::resolve_path ( if (!res) res = get_lang_prelude (seg_name); + if (N == Namespace::Types && !res) + { + // HACK: check for a module after we check the language prelude + for (auto &kv : final_node.children) + { + auto &link = kv.first; + + if (link.path.map_or ( + [&seg_name] (Identifier path) { + auto &path_str = path.as_string (); + return path_str == seg_name; + }, + false)) + { + insert_segment_resolution (segments.back (), kv.second.id); + return Rib::Definition::NonShadowable (kv.second.id); + } + } + } + if (res && !res->is_ambiguous ()) insert_segment_resolution (segments.back (), res->get_node_id ()); diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index 8ec31c0351ff..a7b442d5b440 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -101,8 +101,6 @@ TopLevel::go (AST::Crate &crate) void TopLevel::visit (AST::Module &module) { - insert_or_error_out (module.get_name (), module, Namespace::Types); - // Parse the module's items if they haven't been expanded and the file // should be parsed (i.e isn't hidden behind an untrue or impossible cfg // directive diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 43d7a0dc9116..b8eaa81dbf73 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,2 +1 @@ -issue-3315-2.rs # please don't delete the trailing newline From a82b9289b6f8c60ba3c9765f36e04c198c8b544a Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 20 May 2025 14:25:07 +0200 Subject: [PATCH 114/161] ast: reconstruct: Add base for reconstructing and asserting different IDs gcc/rust/ChangeLog: * ast/rust-ast.h (reconstruct): New function for calling the `reconstruct_*_impl` method and asserting that the new NodeId is different, and then wrap it in a unique_ptr. (reconstruct_vec): Likewise, but for vectors of unique_ptr --- gcc/rust/ast/rust-ast.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index cd586c6aa7d3..1cc10c90ee85 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -83,6 +83,42 @@ class Visitable virtual void accept_vis (ASTVisitor &vis) = 0; }; +/** + * Base function for reconstructing and asserting that the new NodeId is + * different from the old NodeId. It then wraps the given pointer into a unique + * pointer and returns it. + */ +template +std::unique_ptr +reconstruct (const T *instance, F method) +{ + auto *reconstructed = (instance->*method) (); + + rust_assert (reconstructed->get_node_id () != instance->get_node_id ()); + + return std::unique_ptr (reconstructed); +} + +/** + * Reconstruct multiple items in a vector + */ +template +std::vector> +reconstruct_vec (const std::vector> &to_reconstruct, + F method) +{ + std::vector> reconstructed; + + for (const auto &elt : to_reconstruct) + { + auto new_elt = (elt.get ()->*method) (); + + reconstructed.emplace_back (std::move (new_elt)); + } + + return reconstructed; +} + // Delimiter types - used in macros and whatever. enum DelimType { From 63ff993974004b1b92d7f320649b6370dd404ebd Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 20 May 2025 14:59:28 +0200 Subject: [PATCH 115/161] ast: Add reconstruct() method for Type nodes gcc/rust/ChangeLog: * ast/rust-ast.h: Add reconstruct() and reconstruct_impl() for Type nodes. * ast/rust-type.h: Implement them. * ast/rust-macro.h: Likewise. * ast/rust-path.h: Likewise. --- gcc/rust/ast/rust-ast.h | 45 ++++++++++++----- gcc/rust/ast/rust-macro.h | 20 +++++--- gcc/rust/ast/rust-path.h | 30 +++++++++++ gcc/rust/ast/rust-type.h | 103 +++++++++++++++++++++++++++++++++----- 4 files changed, 167 insertions(+), 31 deletions(-) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 1cc10c90ee85..ecbc29181300 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -88,11 +88,11 @@ class Visitable * different from the old NodeId. It then wraps the given pointer into a unique * pointer and returns it. */ -template +template std::unique_ptr -reconstruct (const T *instance, F method) +reconstruct_base (const T *instance) { - auto *reconstructed = (instance->*method) (); + auto *reconstructed = instance->reconstruct_impl (); rust_assert (reconstructed->get_node_id () != instance->get_node_id ()); @@ -102,19 +102,14 @@ reconstruct (const T *instance, F method) /** * Reconstruct multiple items in a vector */ -template +template std::vector> -reconstruct_vec (const std::vector> &to_reconstruct, - F method) +reconstruct_vec (const std::vector> &to_reconstruct) { std::vector> reconstructed; for (const auto &elt : to_reconstruct) - { - auto new_elt = (elt.get ()->*method) (); - - reconstructed.emplace_back (std::move (new_elt)); - } + reconstructed.emplace_back (std::unique_ptr (elt->reconstruct_impl ())); return reconstructed; } @@ -1516,6 +1511,10 @@ class Type : public Visitable return std::unique_ptr (clone_type_impl ()); } + // Similar to `clone_type`, but generates a new instance of the node with a + // different NodeId + std::unique_ptr reconstruct () const { return reconstruct_base (this); } + // virtual destructor virtual ~Type () {} @@ -1534,11 +1533,13 @@ class Type : public Visitable virtual location_t get_locus () const = 0; NodeId get_node_id () const { return node_id; } + virtual Type *reconstruct_impl () const = 0; protected: Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {} + Type (NodeId node_id) : node_id (node_id) {} - // Clone function implementation as pure virtual method + // Clone and reconstruct function implementations as pure virtual methods virtual Type *clone_type_impl () const = 0; NodeId node_id; @@ -1554,6 +1555,13 @@ class TypeNoBounds : public Type return std::unique_ptr (clone_type_no_bounds_impl ()); } + std::unique_ptr reconstruct () const + { + return reconstruct_base (this); + } + + virtual TypeNoBounds *reconstruct_impl () const override = 0; + protected: // Clone function implementation as pure virtual method virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0; @@ -1588,6 +1596,11 @@ class TypeParamBound : public Visitable return std::unique_ptr (clone_type_param_bound_impl ()); } + std::unique_ptr reconstruct () const + { + return reconstruct_base (this); + } + virtual std::string as_string () const = 0; NodeId get_node_id () const { return node_id; } @@ -1596,10 +1609,14 @@ class TypeParamBound : public Visitable virtual TypeParamBoundType get_bound_type () const = 0; + virtual TypeParamBound *reconstruct_impl () const = 0; + protected: // Clone function implementation as pure virtual method virtual TypeParamBound *clone_type_param_bound_impl () const = 0; + TypeParamBound () : node_id (Analysis::Mappings::get ().get_next_node_id ()) + {} TypeParamBound (NodeId node_id) : node_id (node_id) {} NodeId node_id; @@ -1661,6 +1678,10 @@ class Lifetime : public TypeParamBound { return new Lifetime (node_id, lifetime_type, lifetime_name, locus); } + Lifetime *reconstruct_impl () const override + { + return new Lifetime (lifetime_type, lifetime_name, locus); + } }; /* Base generic parameter in AST. Abstract - can be represented by a Lifetime diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index fc01e571b916..e8f377c001ec 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -756,22 +756,16 @@ class MacroInvocation : public TypeNoBounds, std::vector> pending_eager_invocs; protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ MacroInvocation *clone_pattern_impl () const final override { return clone_macro_invocation_impl (); } - /* Use covariance to implement clone function as returning this object rather - * than base */ MacroInvocation *clone_expr_without_block_impl () const final override { return clone_macro_invocation_impl (); } - /* Use covariance to implement clone function as returning this object rather - * than base */ MacroInvocation *clone_type_no_bounds_impl () const final override { return clone_macro_invocation_impl (); @@ -788,6 +782,20 @@ class MacroInvocation : public TypeNoBounds, return new MacroInvocation (*this); } + std::unique_ptr reconstruct_macro_invocation () const + { + return nullptr; + // return reconstruct (this, + // &MacroInvocation::reconstruct_macro_invocation_impl); + } + + MacroInvocation *reconstruct_impl () const override + { + return new MacroInvocation (kind, builtin_kind, invoc_data, outer_attrs, + locus, is_semi_coloned, + reconstruct_vec (pending_eager_invocs)); + } + void add_semicolon () override { is_semi_coloned = true; } Pattern::Kind get_pattern_kind () override diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index de895a2f8384..a1b19d559c33 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -786,6 +786,11 @@ class TypePathSegment { return new TypePathSegment (*this); } + virtual TypePathSegment *reconstruct_impl () const + { + return new TypePathSegment (lang_item, ident_segment, + has_separating_scope_resolution, locus); + } public: virtual ~TypePathSegment () {} @@ -797,6 +802,11 @@ class TypePathSegment { return std::unique_ptr (clone_type_path_segment_impl ()); } + // Unique pointer custom reconstruct function + std::unique_ptr reconstruct () const + { + return reconstruct_base (this); + } TypePathSegment (PathIdentSegment ident_segment, bool has_separating_scope_resolution, location_t locus) @@ -821,6 +831,15 @@ class TypePathSegment node_id (Analysis::Mappings::get ().get_next_node_id ()) {} + // General constructor + TypePathSegment (tl::optional lang_item, + tl::optional ident_segment, + bool has_separating_scope_resolution, location_t locus) + : lang_item (lang_item), ident_segment (ident_segment), locus (locus), + has_separating_scope_resolution (has_separating_scope_resolution), + node_id (Analysis::Mappings::get ().get_next_node_id ()) + {} + TypePathSegment (TypePathSegment const &other) : lang_item (other.lang_item), ident_segment (other.ident_segment), locus (other.locus), @@ -1152,6 +1171,11 @@ class TypePath : public TypeNoBounds { return new TypePath (*this); } + TypePath *reconstruct_impl () const override + { + return new TypePath (reconstruct_vec (segments), locus, + has_opening_scope_resolution); + } public: /* Returns whether the TypePath has an opening scope resolution operator @@ -1443,6 +1467,12 @@ class QualifiedPathInType : public TypeNoBounds { return new QualifiedPathInType (*this); } + QualifiedPathInType *reconstruct_impl () const override + { + return new QualifiedPathInType (path_type, + associated_segment->reconstruct (), + reconstruct_vec (segments), locus); + } public: QualifiedPathInType ( diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 6c0652a013f9..abbfd36a6f57 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -19,6 +19,7 @@ #ifndef RUST_AST_TYPE_H #define RUST_AST_TYPE_H +#include "optional.h" #include "rust-ast.h" #include "rust-path.h" @@ -106,6 +107,11 @@ class TraitBound : public TypeParamBound return new TraitBound (node_id, type_path, locus, in_parens, opening_question_mark, for_lifetimes); } + TraitBound *reconstruct_impl () const override + { + return new TraitBound (type_path, locus, in_parens, opening_question_mark, + for_lifetimes); + } }; // definition moved to rust-ast.h @@ -127,6 +133,10 @@ class ImplTraitType : public Type { return new ImplTraitType (*this); } + ImplTraitType *reconstruct_impl () const override + { + return new ImplTraitType (reconstruct_vec (type_param_bounds), locus); + } public: ImplTraitType ( @@ -136,7 +146,8 @@ class ImplTraitType : public Type {} // copy constructor with vector clone - ImplTraitType (ImplTraitType const &other) : locus (other.locus) + ImplTraitType (ImplTraitType const &other) + : Type (other.node_id), locus (other.locus) { type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) @@ -191,6 +202,11 @@ class TraitObjectType : public Type { return new TraitObjectType (*this); } + TraitObjectType *reconstruct_impl () const override + { + return new TraitObjectType (reconstruct_vec (type_param_bounds), locus, + has_dyn); + } public: TraitObjectType ( @@ -202,7 +218,7 @@ class TraitObjectType : public Type // copy constructor with vector clone TraitObjectType (TraitObjectType const &other) - : has_dyn (other.has_dyn), locus (other.locus) + : Type (other.node_id), has_dyn (other.has_dyn), locus (other.locus) { type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) @@ -258,6 +274,10 @@ class ParenthesisedType : public TypeNoBounds { return new ParenthesisedType (*this); } + ParenthesisedType *reconstruct_impl () const override + { + return new ParenthesisedType (type_in_parens->reconstruct (), locus); + } public: // Constructor uses Type pointer for polymorphism @@ -338,6 +358,10 @@ class ImplTraitTypeOneBound : public TypeNoBounds { return new ImplTraitTypeOneBound (*this); } + TypeNoBounds *reconstruct_impl () const override + { + return new ImplTraitTypeOneBound (trait_bound->reconstruct (), locus); + } }; /* A trait object with a single trait bound. The "trait bound" is really just @@ -355,6 +379,10 @@ class TraitObjectTypeOneBound : public TypeNoBounds { return new TraitObjectTypeOneBound (*this); } + TraitObjectTypeOneBound *reconstruct_impl () const override + { + return new TraitObjectTypeOneBound (trait_bound, locus, has_dyn); + } public: TraitObjectTypeOneBound (TraitBound trait_bound, location_t locus, @@ -448,6 +476,10 @@ class TupleType : public TypeNoBounds { return new TupleType (*this); } + TupleType *reconstruct_impl () const override + { + return new TupleType (reconstruct_vec (elems), locus); + } }; /* A type with no values, representing the result of computations that never @@ -464,6 +496,10 @@ class NeverType : public TypeNoBounds { return new NeverType (*this); } + NeverType *reconstruct_impl () const override + { + return new NeverType (locus); + } public: NeverType (location_t locus) : locus (locus) {} @@ -544,6 +580,10 @@ class RawPointerType : public TypeNoBounds { return new RawPointerType (*this); } + RawPointerType *reconstruct_impl () const override + { + return new RawPointerType (pointer_type, type->reconstruct (), locus); + } }; // A type pointing to memory owned by another value @@ -622,6 +662,16 @@ class ReferenceType : public TypeNoBounds { return new ReferenceType (*this); } + ReferenceType *reconstruct_impl () const override + { + return new ReferenceType (has_mut, type->reconstruct (), locus, + // TODO: Improve this - it's ugly! + has_lifetime () ? tl::make_optional ( + lifetime->get_lifetime_type (), + lifetime->get_lifetime_name (), + lifetime->get_locus ()) + : tl::nullopt); + } }; // A fixed-size sequence of elements of a specified type @@ -689,6 +739,13 @@ class ArrayType : public TypeNoBounds { return new ArrayType (*this); } + ArrayType *reconstruct_impl () const override + { + return new ArrayType ( + elem_type->reconstruct (), + size->clone_expr () /* FIXME: This should be `reconstruct_expr()` */, + locus); + } }; /* A dynamically-sized type representing a "view" into a sequence of elements of @@ -739,12 +796,16 @@ class SliceType : public TypeNoBounds std::unique_ptr &get_elem_type_ptr () { return elem_type; } protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ + /* Use covariance to implement clone function as returning this object + * rather than base */ SliceType *clone_type_no_bounds_impl () const override { return new SliceType (*this); } + SliceType *reconstruct_impl () const override + { + return new SliceType (elem_type->reconstruct (), locus); + } }; /* Type used in generic arguments to explicitly request type inference (wildcard @@ -755,13 +816,21 @@ class InferredType : public TypeNoBounds // e.g. Vec<_> = whatever protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ + /* Use covariance to implement clone function as returning this object + * rather than base */ InferredType *clone_type_no_bounds_impl () const override { + // This goes through the copy constructor return new InferredType (*this); } + InferredType *reconstruct_impl () const override + { + // This goes through the base constructor which calls the base + // TypeNoBounds constructor, which allocates a new NodeId + return new InferredType (locus); + } + public: InferredType (location_t locus) : locus (locus) {} @@ -980,9 +1049,17 @@ class BareFunctionType : public TypeNoBounds FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; } + BareFunctionType *reconstruct_impl () const override + { + return new BareFunctionType ( + for_lifetimes, function_qualifiers, params, + /* FIXME: Should params be reconstruct() as well? */ + _is_variadic, variadic_attrs, return_type->reconstruct (), locus); + } + protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ + /* Use covariance to implement clone function as returning this object + * rather than base */ BareFunctionType *clone_type_no_bounds_impl () const override { return new BareFunctionType (*this); @@ -999,13 +1076,13 @@ class MacroInvocation; * function item type? * closure expression types? * primitive types (bool, int, float, char, str (the slice)) - * Although supposedly TypePaths are used to reference these types (including - * primitives) */ + * Although supposedly TypePaths are used to reference these types + * (including primitives) */ /* FIXME: Incomplete spec references: - * anonymous type parameters, aka "impl Trait in argument position" - impl then - * trait bounds abstract return types, aka "impl Trait in return position" - - * impl then trait bounds */ + * anonymous type parameters, aka "impl Trait in argument position" - impl + * then trait bounds abstract return types, aka "impl Trait in return + * position" - impl then trait bounds */ } // namespace AST } // namespace Rust From e4a25ec213e2fd534609bf0300bc5ca58f060f5a Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 20 May 2025 15:08:06 +0200 Subject: [PATCH 116/161] ast: builder: Remove ASTTypeBuilder gcc/rust/ChangeLog: * Make-lang.in: Remove object file for ASTTypeBuilder. * ast/rust-ast-builder.h: Remove function. * ast/rust-ast-builder.cc (Builder::new_type): Likewise. (Builder::new_const_param): Use reconstruct_type() instead. (Builder::new_generic_args): Likewise. * expand/rust-derive-default.cc (DeriveDefault::visit_struct): Likewise. (DeriveDefault::visit_tuple): Likewise. * expand/rust-derive-eq.cc (DeriveEq::visit_tuple): Likewise. (DeriveEq::visit_struct): Likewise. (DeriveEq::visit_enum): Likewise. (DeriveEq::visit_union): Likewise. * ast/rust-ast-builder-type.cc: Removed. * ast/rust-ast-builder-type.h: Removed. --- gcc/rust/Make-lang.in | 1 - gcc/rust/ast/rust-ast-builder-type.cc | 166 ------------------------- gcc/rust/ast/rust-ast-builder-type.h | 57 --------- gcc/rust/ast/rust-ast-builder.cc | 33 +++-- gcc/rust/ast/rust-ast-builder.h | 2 - gcc/rust/expand/rust-derive-default.cc | 4 +- gcc/rust/expand/rust-derive-eq.cc | 25 +--- 7 files changed, 22 insertions(+), 266 deletions(-) delete mode 100644 gcc/rust/ast/rust-ast-builder-type.cc delete mode 100644 gcc/rust/ast/rust-ast-builder-type.h diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 2a2e79d29f5f..c7846892d895 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -93,7 +93,6 @@ GRS_OBJS = \ rust/rust-cfg-strip.o \ rust/rust-expand-visitor.o \ rust/rust-ast-builder.o \ - rust/rust-ast-builder-type.o \ rust/rust-derive.o \ rust/rust-derive-cmp-common.o \ rust/rust-derive-clone.o \ diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc deleted file mode 100644 index 7f8571ac89f1..000000000000 --- a/gcc/rust/ast/rust-ast-builder-type.cc +++ /dev/null @@ -1,166 +0,0 @@ -// 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 -// . - -#include "rust-ast-builder-type.h" -#include "rust-ast-builder.h" -#include "rust-ast-full.h" -#include "rust-common.h" - -namespace Rust { -namespace AST { - -ASTTypeBuilder::ASTTypeBuilder () : translated (nullptr) {} - -Type * -ASTTypeBuilder::build (Type &type) -{ - ASTTypeBuilder builder; - type.accept_vis (builder); - rust_assert (builder.translated != nullptr); - return builder.translated; -} - -void -ASTTypeBuilder::visit (BareFunctionType &fntype) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (TupleType &tuple) -{ - std::vector > elems; - for (auto &elem : tuple.get_elems ()) - { - Type *t = ASTTypeBuilder::build (*elem.get ()); - std::unique_ptr ty (t); - elems.push_back (std::move (ty)); - } - translated = new TupleType (std::move (elems), tuple.get_locus ()); -} - -void -ASTTypeBuilder::visit (TypePath &path) -{ - std::vector > segments; - for (auto &seg : path.get_segments ()) - { - switch (seg->get_type ()) - { - case TypePathSegment::REG: - { - const TypePathSegment &segment - = (const TypePathSegment &) (*seg.get ()); - TypePathSegment *s - = new TypePathSegment (segment.get_ident_segment (), - segment.get_separating_scope_resolution (), - segment.get_locus ()); - std::unique_ptr sg (s); - segments.push_back (std::move (sg)); - } - break; - - case TypePathSegment::GENERIC: - { - TypePathSegmentGeneric &generic - = (TypePathSegmentGeneric &) (*seg.get ()); - - GenericArgs args - = Builder::new_generic_args (generic.get_generic_args ()); - TypePathSegmentGeneric *s - = new TypePathSegmentGeneric (generic.get_ident_segment (), false, - std::move (args), - generic.get_locus ()); - std::unique_ptr sg (s); - segments.push_back (std::move (sg)); - } - break; - - case TypePathSegment::FUNCTION: - { - rust_unreachable (); - // TODO - // const TypePathSegmentFunction &fn - // = (const TypePathSegmentFunction &) (*seg.get ()); - } - break; - } - } - - translated = new TypePath (std::move (segments), path.get_locus (), - path.has_opening_scope_resolution_op ()); -} - -void -ASTTypeBuilder::visit (QualifiedPathInType &path) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (ArrayType &type) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (ReferenceType &type) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (RawPointerType &type) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (SliceType &type) -{ - Type *t = ASTTypeBuilder::build (type.get_elem_type ()); - std::unique_ptr ty (t); - translated = new SliceType (std::move (ty), type.get_locus ()); -} - -void -ASTTypeBuilder::visit (InferredType &type) -{ - translated = new InferredType (type.get_locus ()); -} - -void -ASTTypeBuilder::visit (NeverType &type) -{ - translated = new NeverType (type.get_locus ()); -} - -void -ASTTypeBuilder::visit (TraitObjectTypeOneBound &type) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (TraitObjectType &type) -{ - /* TODO */ -} - -} // namespace AST -} // namespace Rust diff --git a/gcc/rust/ast/rust-ast-builder-type.h b/gcc/rust/ast/rust-ast-builder-type.h deleted file mode 100644 index b67ae3b553ff..000000000000 --- a/gcc/rust/ast/rust-ast-builder-type.h +++ /dev/null @@ -1,57 +0,0 @@ -// 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 -// . - -#ifndef RUST_AST_BUILDER_TYPE -#define RUST_AST_BUILDER_TYPE - -#include "rust-ast-visitor.h" - -namespace Rust { -namespace AST { - -class ASTTypeBuilder : public DefaultASTVisitor -{ -protected: - using DefaultASTVisitor::visit; - -public: - static Type *build (Type &type); - - void visit (BareFunctionType &fntype) override; - void visit (TupleType &tuple) override; - void visit (TypePath &path) override; - void visit (QualifiedPathInType &path) override; - void visit (ArrayType &type) override; - void visit (ReferenceType &type) override; - void visit (RawPointerType &type) override; - void visit (SliceType &type) override; - void visit (InferredType &type) override; - void visit (NeverType &type) override; - void visit (TraitObjectTypeOneBound &type) override; - void visit (TraitObjectType &type) override; - -private: - ASTTypeBuilder (); - - Type *translated; -}; - -} // namespace AST -} // namespace Rust - -#endif // RUST_AST_BUILDER_TYPE diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 914b321279f5..914477120d2b 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -18,7 +18,6 @@ #include "rust-ast-builder.h" #include "optional.h" -#include "rust-ast-builder-type.h" #include "rust-ast.h" #include "rust-common.h" #include "rust-expr.h" @@ -552,13 +551,6 @@ Builder::discriminant_value (std::string binding_name, std::string instance) call (std::move (intrinsic), identifier (instance))); } -std::unique_ptr -Builder::new_type (Type &type) -{ - Type *t = ASTTypeBuilder::build (type); - return std::unique_ptr (t); -} - std::unique_ptr Builder::new_lifetime_param (LifetimeParam ¶m) { @@ -596,7 +588,7 @@ Builder::new_type_param ( std::unique_ptr type = nullptr; if (param.has_type ()) - type = new_type (param.get_type ()); + type = param.get_type ().reconstruct (); for (auto &&extra_bound : extra_bounds) type_param_bounds.emplace_back (std::move (extra_bound)); @@ -726,7 +718,7 @@ Builder::new_generic_args (GenericArgs &args) for (auto &binding : args.get_binding_args ()) { Type &t = *binding.get_type_ptr ().get (); - std::unique_ptr ty = new_type (t); + std::unique_ptr ty = t.reconstruct (); GenericArgsBinding b (binding.get_identifier (), std::move (ty), binding.get_locus ()); binding_args.push_back (std::move (b)); @@ -734,20 +726,25 @@ Builder::new_generic_args (GenericArgs &args) for (auto &arg : args.get_generic_args ()) { + tl::optional new_arg = tl::nullopt; + switch (arg.get_kind ()) { case GenericArg::Kind::Type: - { - std::unique_ptr ty = new_type (arg.get_type ()); - GenericArg arg = GenericArg::create_type (std::move (ty)); - } + new_arg = GenericArg::create_type (arg.get_type ().reconstruct ()); break; - - default: - // FIXME - rust_unreachable (); + case GenericArg::Kind::Either: + new_arg + = GenericArg::create_ambiguous (arg.get_path (), arg.get_locus ()); + break; + case GenericArg::Kind::Const: + new_arg + = GenericArg::create_const (arg.get_expression ().clone_expr ()); + // FIXME: Use `reconstruct()` here, not `clone_expr()` break; } + + generic_args.emplace_back (*new_arg); } return GenericArgs (std::move (lifetime_args), std::move (generic_args), diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index fa3c95ce4fdf..843bab896c74 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -315,8 +315,6 @@ class Builder std::unique_ptr discriminant_value (std::string binding_name, std::string instance = "self"); - static std::unique_ptr new_type (Type &type); - static std::unique_ptr new_lifetime_param (LifetimeParam ¶m); diff --git a/gcc/rust/expand/rust-derive-default.cc b/gcc/rust/expand/rust-derive-default.cc index 1b497b5923b0..26ee5461095a 100644 --- a/gcc/rust/expand/rust-derive-default.cc +++ b/gcc/rust/expand/rust-derive-default.cc @@ -98,7 +98,7 @@ DeriveDefault::visit_struct (StructStruct &item) for (auto &field : item.get_fields ()) { auto name = field.get_field_name ().as_string (); - auto type = Builder::new_type (field.get_field_type ()); + auto type = field.get_field_type ().reconstruct (); auto expr = default_call (std::move (type)); cloned_fields.emplace_back ( @@ -120,7 +120,7 @@ DeriveDefault::visit_tuple (TupleStruct &tuple_item) for (auto &field : tuple_item.get_fields ()) { - auto type = Builder::new_type (field.get_field_type ()); + auto type = field.get_field_type ().reconstruct (); defaulted_fields.emplace_back (default_call (std::move (type))); } diff --git a/gcc/rust/expand/rust-derive-eq.cc b/gcc/rust/expand/rust-derive-eq.cc index 97651270bc55..7da137fb5c27 100644 --- a/gcc/rust/expand/rust-derive-eq.cc +++ b/gcc/rust/expand/rust-derive-eq.cc @@ -142,10 +142,7 @@ DeriveEq::visit_tuple (TupleStruct &item) auto types = std::vector> (); for (auto &field : item.get_fields ()) - { - auto type = Builder::new_type (field.get_field_type ()); - types.emplace_back (std::move (type)); - } + types.emplace_back (field.get_field_type ().reconstruct ()); expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)), item.get_identifier ().as_string (), @@ -158,10 +155,7 @@ DeriveEq::visit_struct (StructStruct &item) auto types = std::vector> (); for (auto &field : item.get_fields ()) - { - auto type = Builder::new_type (field.get_field_type ()); - types.emplace_back (std::move (type)); - } + types.emplace_back (field.get_field_type ().reconstruct ()); expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)), item.get_identifier ().as_string (), @@ -186,10 +180,7 @@ DeriveEq::visit_enum (Enum &item) auto &tuple = static_cast (*variant); for (auto &field : tuple.get_tuple_fields ()) - { - auto type = Builder::new_type (field.get_field_type ()); - types.emplace_back (std::move (type)); - } + types.emplace_back (field.get_field_type ().reconstruct ()); break; } case EnumItem::Kind::Struct: @@ -197,10 +188,7 @@ DeriveEq::visit_enum (Enum &item) auto &tuple = static_cast (*variant); for (auto &field : tuple.get_struct_fields ()) - { - auto type = Builder::new_type (field.get_field_type ()); - types.emplace_back (std::move (type)); - } + types.emplace_back (field.get_field_type ().reconstruct ()); break; } @@ -218,10 +206,7 @@ DeriveEq::visit_union (Union &item) auto types = std::vector> (); for (auto &field : item.get_variants ()) - { - auto type = Builder::new_type (field.get_field_type ()); - types.emplace_back (std::move (type)); - } + types.emplace_back (field.get_field_type ().reconstruct ()); expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)), item.get_identifier ().as_string (), From 14471d90d7fc4d242f0502ad843c5a71a696b9a5 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 26 May 2025 11:31:40 +0200 Subject: [PATCH 117/161] reconstruct_vec: Allocate size when creating the vector gcc/rust/ChangeLog: * ast/rust-ast.h (reconstruct_vec): Pre-allocate size of vector. --- gcc/rust/ast/rust-ast.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index ecbc29181300..0d853e744c76 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -107,6 +107,7 @@ std::vector> reconstruct_vec (const std::vector> &to_reconstruct) { std::vector> reconstructed; + reconstructed.reserve (to_reconstruct.size ()); for (const auto &elt : to_reconstruct) reconstructed.emplace_back (std::unique_ptr (elt->reconstruct_impl ())); From 46d0d80b86ed799daa31e6b6d66aaccdd86464fa Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 13 Jun 2025 10:04:41 +0200 Subject: [PATCH 118/161] chore: ast: Fix formatting and includes gcc/rust/ChangeLog: * ast/rust-ast-builder.cc: Remove extra include, fix new formatting. --- gcc/rust/ast/rust-ast-builder.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 914477120d2b..ed10ce7f9a18 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -28,7 +28,6 @@ #include "rust-pattern.h" #include "rust-system.h" #include "rust-token.h" -#include namespace Rust { namespace AST { From ae5484919bdab2e9d5c4f3a94df80d7a150b1505 Mon Sep 17 00:00:00 2001 From: Zhi Heng Date: Sat, 28 Jun 2025 20:59:54 +0800 Subject: [PATCH 119/161] gccrs: Fix type checking logic for TuplePattern gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-pattern.cc (visit(TuplePattern)): Fix incorrect logic for field size checking. gcc/testsuite/ChangeLog: * rust/compile/tuple_mismatch.rs: Include RestPattern in test. Signed-off-by: Yap Zhi Heng --- gcc/rust/typecheck/rust-hir-type-check-pattern.cc | 4 ++-- gcc/testsuite/rust/compile/tuple_mismatch.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index d87916ec7985..537c3491265b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -511,12 +511,12 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) HIR::TuplePatternItemsRanged &ref = static_cast (pattern.get_items ()); - // Check whether size of lower and upper patterns <= parent size const auto &lower = ref.get_lower_patterns (); const auto &upper = ref.get_upper_patterns (); size_t min_size_required = lower.size () + upper.size (); - if (par.get_fields ().size () > min_size_required) + // Ensure that size of lower and upper patterns <= parent size + if (min_size_required > par.get_fields ().size ()) { emit_pattern_size_error (pattern, par.get_fields ().size (), min_size_required); diff --git a/gcc/testsuite/rust/compile/tuple_mismatch.rs b/gcc/testsuite/rust/compile/tuple_mismatch.rs index 828586b0f09d..1ff358be60a1 100644 --- a/gcc/testsuite/rust/compile/tuple_mismatch.rs +++ b/gcc/testsuite/rust/compile/tuple_mismatch.rs @@ -3,6 +3,7 @@ fn main() { let (_,) = (1, 2); // { dg-error "expected a tuple with 2 elements, found one with 1 element" } let (_, _) = (1, 2, 3); // { dg-error "expected a tuple with 3 elements, found one with 2 elements" } let (_, _) = (1,); // { dg-error "expected a tuple with 1 element, found one with 2 elements" } + let (_, .., _) = (1,); // { dg-error "expected a tuple with 1 element, found one with 2 elements" } } // The lhs and rhs sizes don't match, but we still resolve 'a' to be bool, we don't From f42c4c6288390e5ee860bc4005fda9cf10db24cd Mon Sep 17 00:00:00 2001 From: Zhi Heng Date: Sun, 29 Jun 2025 10:44:31 +0800 Subject: [PATCH 120/161] gccrs: Implement compilation support for TuplePatternItems::RANGED Example GIMPLE output of the match statement for match-restpattern-tuple-1.rs: ... RUSTTMP.2 = x; _1 = RUSTTMP.2.__0; _2 = _1 == 1; _3 = RUSTTMP.2.__3; _4 = _3 == 4; _5 = _2 & _4; if (_5 != 0) goto ; else goto ; : { { } goto ; } : if (1 != 0) goto ; else goto ; : { { } goto ; } : : ... gcc/rust/ChangeLog: * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit(TuplePattern)): Implement check expression compilation for TuplePatternItems::RANGED. Signed-off-by: Yap Zhi Heng --- gcc/rust/backend/rust-compile-pattern.cc | 46 ++++++++++++++++++- .../rust/compile/match-restpattern-tuple-1.rs | 8 ++++ .../rust/compile/match-restpattern-tuple-2.rs | 8 ++++ .../torture/match-restpattern-tuple.rs | 27 +++++++++++ 4 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs create mode 100644 gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs create mode 100644 gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index cd1c77be5eb7..3351becd1d99 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -430,8 +430,50 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) { case HIR::TuplePatternItems::RANGED: { - // TODO - gcc_unreachable (); + auto &items + = static_cast (pattern.get_items ()); + size_t tuple_field_index = 0; + + // lookup the type to find out number of fields + TyTy::BaseType *ty = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + pattern.get_mappings ().get_hirid (), &ty); + rust_assert (ok); + rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE); + + // compile check expr for lower patterns + for (auto &pat : items.get_lower_patterns ()) + { + tree field_expr + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, + pat->get_locus ()); + + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pat->get_locus ()); + } + + // skip the fields that are not checked + tuple_field_index = static_cast (*ty).num_fields () + - items.get_upper_patterns ().size (); + + // compile check expr for upper patterns + for (auto &pat : items.get_upper_patterns ()) + { + tree field_expr + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, + pat->get_locus ()); + + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pat->get_locus ()); + } } break; diff --git a/gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs b/gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs new file mode 100644 index 000000000000..5cce3c409f0e --- /dev/null +++ b/gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs @@ -0,0 +1,8 @@ +fn main() { + let x = (1, 2, 3, 4); + + match x { + (1, .., 4) => {}, + _ => {} + } +} \ No newline at end of file diff --git a/gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs b/gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs new file mode 100644 index 000000000000..40900a36bece --- /dev/null +++ b/gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs @@ -0,0 +1,8 @@ +fn main() { + let x = (1, 2, 3, 4); + + match x { + (1, .., 2, 3, 4, 5) => {}, // { dg-error "expected a tuple with 4 elements, found one with 5 elements" } + _ => {} + } +} \ No newline at end of file diff --git a/gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs b/gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs new file mode 100644 index 000000000000..2c1418c551d0 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs @@ -0,0 +1,27 @@ +// { dg-output "correct\r*" } +extern "C" { + fn puts(s: *const i8); +} + +fn main() -> i32 { + let x = (1, 2, 3, 4); + let mut ret = 1; + + match x { + (1, .., 2, 4) => { + /* should not take this path */ + unsafe { puts("wrong\0" as *const str as *const i8) } + }, + (2, ..) => { + /* should not take this path */ + unsafe { puts("wrong\0" as *const str as *const i8) } + }, + (b, .., 4) => { + ret -= b; + unsafe { puts("correct\0" as *const str as *const i8) } + }, + _ => {} + } + + ret +} \ No newline at end of file From 05b03ffd75f639e1e9679642dc80ce7cb986db5b Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 9 May 2025 17:50:22 -0400 Subject: [PATCH 121/161] nr2.0: Enable by default gcc/rust/ChangeLog: * lang.opt (frust-name-resolution-2.0): Enable by default. gcc/testsuite/ChangeLog: * rust/compile/nr2/compile.exp: Removed. * rust/compile/nr2/exclude: Removed. Signed-off-by: Owen Avery --- gcc/rust/lang.opt | 2 +- gcc/testsuite/rust/compile/nr2/compile.exp | 149 --------------------- gcc/testsuite/rust/compile/nr2/exclude | 1 - 3 files changed, 1 insertion(+), 151 deletions(-) delete mode 100644 gcc/testsuite/rust/compile/nr2/compile.exp delete mode 100644 gcc/testsuite/rust/compile/nr2/exclude diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt index 9cdbce2bc0af..4c48816affa5 100644 --- a/gcc/rust/lang.opt +++ b/gcc/rust/lang.opt @@ -205,7 +205,7 @@ EnumValue Enum(frust_compile_until) String(end) Value(13) frust-name-resolution-2.0 -Rust Var(flag_name_resolution_2_0) +Rust Var(flag_name_resolution_2_0) Init(1) Use the temporary and experimental name resolution pipeline instead of the stable one frust-borrowcheck diff --git a/gcc/testsuite/rust/compile/nr2/compile.exp b/gcc/testsuite/rust/compile/nr2/compile.exp deleted file mode 100644 index 9e15cdd7253a..000000000000 --- a/gcc/testsuite/rust/compile/nr2/compile.exp +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright (C) 2021-2024 Free Software Foundation, Inc. - -# This program 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 of the License, or -# (at your option) any later version. -# -# This program 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 -# . - -# Run compile tests with name resolution 2.0 enabled - -# Load support procs. -load_lib rust-dg.exp - -# These tests don't run runtest_file_p consistently if it -# doesn't return the same values, so disable parallelization -# of this *.exp file. The first parallel runtest to reach -# this will run all the tests serially. -if ![gcc_parallel_test_run_p compile] { - return -} -gcc_parallel_test_enable 0 - -# Initialize `dg'. -dg-init - -namespace eval rust-nr2-ns { - # Exclude tests which aren't passing yet - # These should be removed from the exclude file over time - - set exclude_fh [open $srcdir/$subdir/exclude r] - set exclude_raw [lsort [split [read $exclude_fh] "\n"]] - close $exclude_fh - unset exclude_fh - - set exclude "" - foreach ent $exclude_raw { - if [regexp {^[^#].*} $ent] { - lappend exclude $ent - } - } - unset exclude_raw - - # Run tests in directories - # Manually specifying these, in case some other test file - # does something weird - set test_dirs {{} {macros builtin} {macros mbe} {macros proc} {torture}} - - set tests_expect_ok "" - set tests_expect_err "" - - set compile_dir [list {*}[file split $srcdir] {*}[file split $subdir]] - set compile_dir [lreplace $compile_dir end end] - - foreach test_dir $test_dirs { - foreach test [lsort [glob -nocomplain -tails -directory [file join {*}$compile_dir {*}$test_dir] *.rs]] { - # use '/' as the path seperator for entries in the exclude file - set test_lbl [join [list {*}$test_dir $test] "/"] - set idx [lsearch -exact -sorted $exclude $test_lbl] - if {$idx == -1} { - if {[runtest_file_p $runtests [file join {*}$compile_dir {*}$test_dir $test]]} { - lappend tests_expect_ok [list {*}$test_dir $test] - } - } else { - if {[runtest_file_p $runtests [file join {*}$compile_dir {*}$test_dir $test]]} { - lappend tests_expect_err [list {*}$test_dir $test] - } - set exclude [lreplace $exclude $idx $idx] - } - } - } - - # Generate failures for unmatched tests in the exclude list - foreach ent $exclude { - fail "$ent: could not exclude test" - } - unset exclude - - # run a test while catching record_test calls - set record_test_out "" - proc try_test { test } { - variable record_test_out - rename ::record_test record_test_old - - proc ::record_test { type msg args } { - namespace eval ::rust-nr2-ns { - set type [uplevel 1 {set type}] - set msg [uplevel 1 {set msg}] - variable record_test_out - switch $type { - FAIL { - lappend record_test_out [list $type $msg] - } - XPASS { - lappend record_test_out [list $type $msg] - } - } - } - } - - namespace eval :: { - set saved-dg-do-what-default ${dg-do-what-default} - set dg-do-what-default "compile" - dg-runtest [list [uplevel 1 {set test}]] "-frust-name-resolution-2.0" "" - set dg-do-what-default ${saved-dg-do-what-default} - } - - rename ::record_test "" - rename record_test_old ::record_test - - set record_test_cache $record_test_out - set record_test_out "" - return $record_test_cache - } - - # check for unexpected failures - foreach test $tests_expect_ok { - set fails [try_test [file join {*}$compile_dir {*}$test]] - if {[llength $fails] != 0} { - foreach ent $fails { - record_test [lindex $ent 0] "on nr2: [lindex $ent 1]" - } - } else { - record_test PASS "[file join {*}$test] on nr2" - } - } - - #check for unexpected successes - foreach test $tests_expect_err { - set fails [try_test [file join {*}$compile_dir {*}$test]] - if {[llength $fails] == 0} { - record_test XPASS "[file join {*}$test] on nr2" - } else { - record_test XFAIL "[file join {*}$test] on nr2 was rightfully excluded" - } - } -} - -# All done. -dg-finish - -gcc_parallel_test_enable 1 diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude deleted file mode 100644 index b8eaa81dbf73..000000000000 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ /dev/null @@ -1 +0,0 @@ -# please don't delete the trailing newline From 86de5fab4a82050670e78dd8437d56ccbaca3d84 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Thu, 3 Jul 2025 17:43:55 -0400 Subject: [PATCH 122/161] Remove -frust-name-resolution-2.0 usage in tests gcc/testsuite/ChangeLog: * rust/compile/additional-trait-bounds2nr2.rs: Remove -frust-name-resolution-2.0 usage. * rust/compile/const_generics_3.rs: Likewise. * rust/compile/enum_variant_name.rs: Likewise. * rust/compile/generics9.rs: Likewise. * rust/compile/invalid_label_name.rs: Likewise. * rust/compile/issue-3304.rs: Likewise. * rust/compile/macros/mbe/macro-issue3708.rs: Likewise. * rust/compile/macros/mbe/macro-issue3709-2.rs: Likewise. * rust/compile/name_resolution10.rs: Likewise. * rust/compile/name_resolution11.rs: Likewise. * rust/compile/name_resolution12.rs: Likewise. * rust/compile/name_resolution13.rs: Likewise. * rust/compile/name_resolution14.rs: Likewise. * rust/compile/name_resolution15.rs: Likewise. * rust/compile/name_resolution16.rs: Likewise. * rust/compile/name_resolution17.rs: Likewise. * rust/compile/name_resolution18.rs: Likewise. * rust/compile/name_resolution20.rs: Likewise. * rust/compile/name_resolution22.rs: Likewise. * rust/compile/name_resolution23.rs: Likewise. * rust/compile/name_resolution24.rs: Likewise. * rust/compile/name_resolution25.rs: Likewise. * rust/compile/name_resolution6.rs: Likewise. * rust/compile/name_resolution7.rs: Likewise. * rust/compile/name_resolution8.rs: Likewise. * rust/compile/name_resolution9.rs: Likewise. * rust/compile/nested_macro_definition.rs: Likewise. * rust/compile/pub_restricted_1.rs: Likewise. * rust/compile/pub_restricted_2.rs: Likewise. * rust/compile/self-in-impl.rs: Likewise. * rust/compile/self_import_namespace.rs: Likewise. * rust/compile/use_1.rs: Likewise. * rust/compile/xfail/name_resolution21.rs: Likewise. * rust/execute/torture/name_resolution.rs: Likewise. Signed-off-by: Owen Avery --- gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs | 2 -- gcc/testsuite/rust/compile/const_generics_3.rs | 2 +- gcc/testsuite/rust/compile/enum_variant_name.rs | 2 +- gcc/testsuite/rust/compile/generics9.rs | 1 - gcc/testsuite/rust/compile/invalid_label_name.rs | 1 - gcc/testsuite/rust/compile/issue-3304.rs | 1 - gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs | 2 +- gcc/testsuite/rust/compile/macros/mbe/macro-issue3709-2.rs | 2 +- gcc/testsuite/rust/compile/name_resolution10.rs | 2 +- gcc/testsuite/rust/compile/name_resolution11.rs | 2 +- gcc/testsuite/rust/compile/name_resolution12.rs | 2 +- gcc/testsuite/rust/compile/name_resolution13.rs | 2 -- gcc/testsuite/rust/compile/name_resolution14.rs | 2 -- gcc/testsuite/rust/compile/name_resolution15.rs | 1 - gcc/testsuite/rust/compile/name_resolution16.rs | 1 - gcc/testsuite/rust/compile/name_resolution17.rs | 2 -- gcc/testsuite/rust/compile/name_resolution18.rs | 2 -- gcc/testsuite/rust/compile/name_resolution20.rs | 2 -- gcc/testsuite/rust/compile/name_resolution22.rs | 1 - gcc/testsuite/rust/compile/name_resolution23.rs | 2 -- gcc/testsuite/rust/compile/name_resolution24.rs | 2 -- gcc/testsuite/rust/compile/name_resolution25.rs | 2 -- gcc/testsuite/rust/compile/name_resolution6.rs | 2 +- gcc/testsuite/rust/compile/name_resolution7.rs | 2 -- gcc/testsuite/rust/compile/name_resolution8.rs | 2 -- gcc/testsuite/rust/compile/name_resolution9.rs | 2 -- gcc/testsuite/rust/compile/nested_macro_definition.rs | 2 -- gcc/testsuite/rust/compile/pub_restricted_1.rs | 2 -- gcc/testsuite/rust/compile/pub_restricted_2.rs | 2 +- gcc/testsuite/rust/compile/self-in-impl.rs | 2 -- gcc/testsuite/rust/compile/self_import_namespace.rs | 2 -- gcc/testsuite/rust/compile/use_1.rs | 1 - gcc/testsuite/rust/compile/xfail/name_resolution21.rs | 2 -- gcc/testsuite/rust/execute/torture/name_resolution.rs | 1 - 34 files changed, 9 insertions(+), 51 deletions(-) diff --git a/gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs b/gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs index 6764f6e80120..1c49b750319a 100644 --- a/gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs +++ b/gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs @@ -1,5 +1,3 @@ -// { dg-additional-options "-frust-name-resolution-2.0" } - #![feature(optin_builtin_traits)] pub unsafe auto trait Send {} diff --git a/gcc/testsuite/rust/compile/const_generics_3.rs b/gcc/testsuite/rust/compile/const_generics_3.rs index bd9172949846..09d5835074d1 100644 --- a/gcc/testsuite/rust/compile/const_generics_3.rs +++ b/gcc/testsuite/rust/compile/const_generics_3.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-w -frust-name-resolution-2.0 -frust-compile-until=compilation" } +// { dg-additional-options "-w -frust-compile-until=compilation" } #[lang = "sized"] trait Sized {} diff --git a/gcc/testsuite/rust/compile/enum_variant_name.rs b/gcc/testsuite/rust/compile/enum_variant_name.rs index 671fced2bb8c..965acd1a9cd7 100644 --- a/gcc/testsuite/rust/compile/enum_variant_name.rs +++ b/gcc/testsuite/rust/compile/enum_variant_name.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-w -frust-name-resolution-2.0" } +// { dg-additional-options "-w" } struct E1; enum Test { diff --git a/gcc/testsuite/rust/compile/generics9.rs b/gcc/testsuite/rust/compile/generics9.rs index 56c619833f4f..949fbb1a41cd 100644 --- a/gcc/testsuite/rust/compile/generics9.rs +++ b/gcc/testsuite/rust/compile/generics9.rs @@ -1,4 +1,3 @@ -// { dg-additional-options "-frust-name-resolution-2.0" } struct Foo(A, B); // { dg-error "type parameters with a default cannot use forward declared identifiers" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/invalid_label_name.rs b/gcc/testsuite/rust/compile/invalid_label_name.rs index 66e40a620e09..d1c5a33c62fb 100644 --- a/gcc/testsuite/rust/compile/invalid_label_name.rs +++ b/gcc/testsuite/rust/compile/invalid_label_name.rs @@ -1,4 +1,3 @@ -// { dg-additional-options "-frust-name-resolution-2.0" } pub fn function() { 'continue: loop { // { dg-error "invalid label name .'continue." "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/issue-3304.rs b/gcc/testsuite/rust/compile/issue-3304.rs index 6ab614fa2d5d..cc376faeb9dc 100644 --- a/gcc/testsuite/rust/compile/issue-3304.rs +++ b/gcc/testsuite/rust/compile/issue-3304.rs @@ -1,4 +1,3 @@ -// { dg-additional-options "-frust-name-resolution-2.0" } #[lang = "sized"] trait Sized {} diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs b/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs index e5b38bb0da7e..bcbc8dd695af 100644 --- a/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs +++ b/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } +// { dg-additional-options "-frust-compile-until=lowering" } macro_rules! impl_fn_for_zst { ($( diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro-issue3709-2.rs b/gcc/testsuite/rust/compile/macros/mbe/macro-issue3709-2.rs index cfc8ab460b78..47514f1e998b 100644 --- a/gcc/testsuite/rust/compile/macros/mbe/macro-issue3709-2.rs +++ b/gcc/testsuite/rust/compile/macros/mbe/macro-issue3709-2.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } +// { dg-additional-options "-frust-compile-until=lowering" } macro_rules! impl_fn_for_zst { ($( diff --git a/gcc/testsuite/rust/compile/name_resolution10.rs b/gcc/testsuite/rust/compile/name_resolution10.rs index 33643bd1a147..f156f98c968a 100644 --- a/gcc/testsuite/rust/compile/name_resolution10.rs +++ b/gcc/testsuite/rust/compile/name_resolution10.rs @@ -1,4 +1,4 @@ -// { dg-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } +// { dg-options "-frust-compile-until=lowering" } #![feature(decl_macro)] diff --git a/gcc/testsuite/rust/compile/name_resolution11.rs b/gcc/testsuite/rust/compile/name_resolution11.rs index a464d2a0fd3e..329567afe960 100644 --- a/gcc/testsuite/rust/compile/name_resolution11.rs +++ b/gcc/testsuite/rust/compile/name_resolution11.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } +// { dg-additional-options "-frust-compile-until=lowering" } fn foo() { let b = 10; fn bar() { diff --git a/gcc/testsuite/rust/compile/name_resolution12.rs b/gcc/testsuite/rust/compile/name_resolution12.rs index 9cce31ceb5c2..0f217aa064d7 100644 --- a/gcc/testsuite/rust/compile/name_resolution12.rs +++ b/gcc/testsuite/rust/compile/name_resolution12.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } +// { dg-additional-options "-frust-compile-until=lowering" } const TOTO: i32 = 10; diff --git a/gcc/testsuite/rust/compile/name_resolution13.rs b/gcc/testsuite/rust/compile/name_resolution13.rs index 33edbf9312e2..8356cf6d2d3a 100644 --- a/gcc/testsuite/rust/compile/name_resolution13.rs +++ b/gcc/testsuite/rust/compile/name_resolution13.rs @@ -1,5 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } - pub mod foo { pub macro bar() {} } diff --git a/gcc/testsuite/rust/compile/name_resolution14.rs b/gcc/testsuite/rust/compile/name_resolution14.rs index eaef6a52f160..44c43aa2c0fd 100644 --- a/gcc/testsuite/rust/compile/name_resolution14.rs +++ b/gcc/testsuite/rust/compile/name_resolution14.rs @@ -1,5 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } - pub mod foo { pub macro bar() {} } diff --git a/gcc/testsuite/rust/compile/name_resolution15.rs b/gcc/testsuite/rust/compile/name_resolution15.rs index 45f38da768af..e82c90eafb51 100644 --- a/gcc/testsuite/rust/compile/name_resolution15.rs +++ b/gcc/testsuite/rust/compile/name_resolution15.rs @@ -1,4 +1,3 @@ -// { dg-additional-options "-frust-name-resolution-2.0" } #![feature(decl_macro)] pub mod foo { diff --git a/gcc/testsuite/rust/compile/name_resolution16.rs b/gcc/testsuite/rust/compile/name_resolution16.rs index 230722ef819c..4db7b2ea164b 100644 --- a/gcc/testsuite/rust/compile/name_resolution16.rs +++ b/gcc/testsuite/rust/compile/name_resolution16.rs @@ -1,4 +1,3 @@ -// { dg-additional-options "-frust-name-resolution-2.0" } #![feature(decl_macro)] pub mod foo { diff --git a/gcc/testsuite/rust/compile/name_resolution17.rs b/gcc/testsuite/rust/compile/name_resolution17.rs index 485947647a95..84ad380fd956 100644 --- a/gcc/testsuite/rust/compile/name_resolution17.rs +++ b/gcc/testsuite/rust/compile/name_resolution17.rs @@ -1,5 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } - struct Foo; fn Foo() {} // { dg-error ".Foo. defined multiple times" } diff --git a/gcc/testsuite/rust/compile/name_resolution18.rs b/gcc/testsuite/rust/compile/name_resolution18.rs index 5940149d3bbf..17a335280278 100644 --- a/gcc/testsuite/rust/compile/name_resolution18.rs +++ b/gcc/testsuite/rust/compile/name_resolution18.rs @@ -1,5 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } - struct Marker; struct Foo { diff --git a/gcc/testsuite/rust/compile/name_resolution20.rs b/gcc/testsuite/rust/compile/name_resolution20.rs index e6c2dd5ea8f9..f131bb41c170 100644 --- a/gcc/testsuite/rust/compile/name_resolution20.rs +++ b/gcc/testsuite/rust/compile/name_resolution20.rs @@ -1,5 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } - pub mod foo { pub macro bar() {} } diff --git a/gcc/testsuite/rust/compile/name_resolution22.rs b/gcc/testsuite/rust/compile/name_resolution22.rs index c49331ef38cd..bb5edda6834b 100644 --- a/gcc/testsuite/rust/compile/name_resolution22.rs +++ b/gcc/testsuite/rust/compile/name_resolution22.rs @@ -1,4 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } struct Marker; struct Foo(Marker); diff --git a/gcc/testsuite/rust/compile/name_resolution23.rs b/gcc/testsuite/rust/compile/name_resolution23.rs index 50b8e8111525..843be2a8a49a 100644 --- a/gcc/testsuite/rust/compile/name_resolution23.rs +++ b/gcc/testsuite/rust/compile/name_resolution23.rs @@ -1,5 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } - mod a { pub mod b { pub fn foo() {} diff --git a/gcc/testsuite/rust/compile/name_resolution24.rs b/gcc/testsuite/rust/compile/name_resolution24.rs index f4eb7b2d38fd..4350cd85bd69 100644 --- a/gcc/testsuite/rust/compile/name_resolution24.rs +++ b/gcc/testsuite/rust/compile/name_resolution24.rs @@ -1,5 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } - mod a { pub mod b { pub fn baz() {} diff --git a/gcc/testsuite/rust/compile/name_resolution25.rs b/gcc/testsuite/rust/compile/name_resolution25.rs index 3cacac7f64bd..0cadd9e1c216 100644 --- a/gcc/testsuite/rust/compile/name_resolution25.rs +++ b/gcc/testsuite/rust/compile/name_resolution25.rs @@ -1,5 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } - struct Test; // { dg-warning "struct is never constructed: .Test." } impl Test {} diff --git a/gcc/testsuite/rust/compile/name_resolution6.rs b/gcc/testsuite/rust/compile/name_resolution6.rs index e4087e6281ca..b2b5f6bfc98f 100644 --- a/gcc/testsuite/rust/compile/name_resolution6.rs +++ b/gcc/testsuite/rust/compile/name_resolution6.rs @@ -1,4 +1,4 @@ -// { dg-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } +// { dg-options "-frust-compile-until=lowering" } pub mod foo { pub mod bar { diff --git a/gcc/testsuite/rust/compile/name_resolution7.rs b/gcc/testsuite/rust/compile/name_resolution7.rs index fa84e2ffb839..78cb0b2df708 100644 --- a/gcc/testsuite/rust/compile/name_resolution7.rs +++ b/gcc/testsuite/rust/compile/name_resolution7.rs @@ -1,5 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } - // check that macros by example do not get inserted in ribs like regular items pub mod foo { pub mod bar { diff --git a/gcc/testsuite/rust/compile/name_resolution8.rs b/gcc/testsuite/rust/compile/name_resolution8.rs index 6fb517033824..aca19459fd5b 100644 --- a/gcc/testsuite/rust/compile/name_resolution8.rs +++ b/gcc/testsuite/rust/compile/name_resolution8.rs @@ -1,5 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } - // check that macros by example get exported to the crate's root with #[macro_export] pub mod foo { pub mod bar { diff --git a/gcc/testsuite/rust/compile/name_resolution9.rs b/gcc/testsuite/rust/compile/name_resolution9.rs index 792b3bdd6b5c..84ba3c5c7258 100644 --- a/gcc/testsuite/rust/compile/name_resolution9.rs +++ b/gcc/testsuite/rust/compile/name_resolution9.rs @@ -1,5 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } - pub mod foo { pub mod bar { fn f() { diff --git a/gcc/testsuite/rust/compile/nested_macro_definition.rs b/gcc/testsuite/rust/compile/nested_macro_definition.rs index c0b72506accd..b71afbd7166e 100644 --- a/gcc/testsuite/rust/compile/nested_macro_definition.rs +++ b/gcc/testsuite/rust/compile/nested_macro_definition.rs @@ -1,5 +1,3 @@ -// { dg-options "-frust-name-resolution-2.0" } - macro_rules! toto { () => { macro_rules! tata { diff --git a/gcc/testsuite/rust/compile/pub_restricted_1.rs b/gcc/testsuite/rust/compile/pub_restricted_1.rs index 44989a887e93..2afbeb419359 100644 --- a/gcc/testsuite/rust/compile/pub_restricted_1.rs +++ b/gcc/testsuite/rust/compile/pub_restricted_1.rs @@ -1,5 +1,3 @@ -// { dg-additional-options "-frust-name-resolution-2.0" } - pub mod foo { pub mod bar { pub fn baz() {} diff --git a/gcc/testsuite/rust/compile/pub_restricted_2.rs b/gcc/testsuite/rust/compile/pub_restricted_2.rs index 91f072e890f8..fea9379bf42a 100644 --- a/gcc/testsuite/rust/compile/pub_restricted_2.rs +++ b/gcc/testsuite/rust/compile/pub_restricted_2.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-w -frust-name-resolution-2.0" } +// { dg-additional-options "-w" } mod foo { mod bar { diff --git a/gcc/testsuite/rust/compile/self-in-impl.rs b/gcc/testsuite/rust/compile/self-in-impl.rs index f888162a9f06..a56789753e22 100644 --- a/gcc/testsuite/rust/compile/self-in-impl.rs +++ b/gcc/testsuite/rust/compile/self-in-impl.rs @@ -1,5 +1,3 @@ -// { dg-additional-options "-frust-name-resolution-2.0" } - // the error message here is what rustc >=1.66 emits // rustc <1.66 emits a "cycle detected" error when // trying to calculate the impl type diff --git a/gcc/testsuite/rust/compile/self_import_namespace.rs b/gcc/testsuite/rust/compile/self_import_namespace.rs index 2d9b2ed8e0fc..a63c1d715a8d 100644 --- a/gcc/testsuite/rust/compile/self_import_namespace.rs +++ b/gcc/testsuite/rust/compile/self_import_namespace.rs @@ -1,5 +1,3 @@ -// { dg-additional-options "-frust-name-resolution-2.0" } - mod bar { pub mod foo {} pub fn foo() {} diff --git a/gcc/testsuite/rust/compile/use_1.rs b/gcc/testsuite/rust/compile/use_1.rs index e8e2037aac3f..21ee3e17a25e 100644 --- a/gcc/testsuite/rust/compile/use_1.rs +++ b/gcc/testsuite/rust/compile/use_1.rs @@ -1,4 +1,3 @@ -// { dg-additional-options "-frust-name-resolution-2.0" } mod frob {} use foo::bar::baz; // { dg-error "unresolved import .foo::bar::baz." } diff --git a/gcc/testsuite/rust/compile/xfail/name_resolution21.rs b/gcc/testsuite/rust/compile/xfail/name_resolution21.rs index df48d0015987..fc8e94b4b2c8 100644 --- a/gcc/testsuite/rust/compile/xfail/name_resolution21.rs +++ b/gcc/testsuite/rust/compile/xfail/name_resolution21.rs @@ -1,5 +1,3 @@ -// { dg-additional-options "-frust-name-resolution-2.0" } - pub mod foo { pub macro bar() {} } diff --git a/gcc/testsuite/rust/execute/torture/name_resolution.rs b/gcc/testsuite/rust/execute/torture/name_resolution.rs index 749218352d64..a2eaf4867239 100644 --- a/gcc/testsuite/rust/execute/torture/name_resolution.rs +++ b/gcc/testsuite/rust/execute/torture/name_resolution.rs @@ -1,4 +1,3 @@ -// { dg-additional-options "-frust-name-resolution-2.0" } // { dg-output "Value is 10\r*\n" } const BAZ: i32 = 10; From 7f784d8977a5f7cde41e356c5b19031a0688140d Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Thu, 3 Jul 2025 17:48:11 -0400 Subject: [PATCH 123/161] nr1.0: Remove rust/backend support This is the first patch in a set intended to fully remove name resolution 1.0. As such, it should leave name resolution 1.0 technically available but broken. gcc/rust/ChangeLog: * backend/rust-compile-context.cc (Context::Context): Remove initialization of resolver field. * backend/rust-compile-context.h (Context::get_resolver): Remove function. (Context::resolver): Remove field. * backend/rust-compile-expr.cc (CompileExpr::visit): Assume name resolution 2.0 is always enabled. (CompileExpr::generate_closure_function): Likewise. * backend/rust-compile-implitem.cc (CompileTraitItem::visit): Likewise. * backend/rust-compile-item.cc (CompileItem::visit): Likewise. * backend/rust-compile-resolve-path.cc (ResolvePathRef::resolve): Likewise. Signed-off-by: Owen Avery --- gcc/rust/backend/rust-compile-context.cc | 3 +- gcc/rust/backend/rust-compile-context.h | 2 - gcc/rust/backend/rust-compile-expr.cc | 66 +++++-------------- gcc/rust/backend/rust-compile-implitem.cc | 42 +++--------- gcc/rust/backend/rust-compile-item.cc | 66 +++++-------------- gcc/rust/backend/rust-compile-resolve-path.cc | 27 ++------ 6 files changed, 51 insertions(+), 155 deletions(-) diff --git a/gcc/rust/backend/rust-compile-context.cc b/gcc/rust/backend/rust-compile-context.cc index 284a5aa4ca7c..3f328d33e7fb 100644 --- a/gcc/rust/backend/rust-compile-context.cc +++ b/gcc/rust/backend/rust-compile-context.cc @@ -23,8 +23,7 @@ namespace Rust { namespace Compile { Context::Context () - : resolver (Resolver::Resolver::get ()), - tyctx (Resolver::TypeCheckContext::get ()), + : tyctx (Resolver::TypeCheckContext::get ()), mappings (Analysis::Mappings::get ()), mangler (Mangler ()) { setup_builtins (); diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index ce81a1d0db2c..bb942816946d 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -90,7 +90,6 @@ class Context return type; } - Resolver::Resolver *get_resolver () { return resolver; } Resolver::TypeCheckContext *get_tyctx () { return tyctx; } Analysis::Mappings &get_mappings () { return mappings; } @@ -391,7 +390,6 @@ class Context } private: - Resolver::Resolver *resolver; Resolver::TypeCheckContext *tyctx; Analysis::Mappings &mappings; Mangler mangler; diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 3ce5961f10e1..a93e848304e6 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -802,25 +802,16 @@ CompileExpr::visit (HIR::BreakExpr &expr) if (expr.has_label ()) { - NodeId resolved_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (auto id - = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ())) - resolved_node_id = *id; - } - else + NodeId resolved_node_id; + if (auto id + = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ())) { - NodeId tmp = UNKNOWN_NODEID; - if (ctx->get_resolver ()->lookup_resolved_label ( - expr.get_label ().get_mappings ().get_nodeid (), &tmp)) - resolved_node_id = tmp; + resolved_node_id = *id; } - - if (resolved_node_id == UNKNOWN_NODEID) + else { rust_error_at ( expr.get_label ().get_locus (), @@ -864,26 +855,16 @@ CompileExpr::visit (HIR::ContinueExpr &expr) tree label = ctx->peek_loop_begin_label (); if (expr.has_label ()) { - NodeId resolved_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (auto id - = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ())) - resolved_node_id = *id; - } - else + NodeId resolved_node_id; + if (auto id + = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ())) { - NodeId tmp = UNKNOWN_NODEID; - - if (ctx->get_resolver ()->lookup_resolved_label ( - expr.get_label ().get_mappings ().get_nodeid (), &tmp)) - resolved_node_id = tmp; + resolved_node_id = *id; } - - if (resolved_node_id == UNKNOWN_NODEID) + else { rust_error_at ( expr.get_label ().get_locus (), @@ -2512,23 +2493,12 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr, if (is_block_expr) { auto body_mappings = function_body.get_mappings (); - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto candidate = nr_ctx.values.to_rib (body_mappings.get_nodeid ()); + auto candidate = nr_ctx.values.to_rib (body_mappings.get_nodeid ()); - rust_assert (candidate.has_value ()); - } - else - { - Resolver::Rib *rib = nullptr; - bool ok - = ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), - &rib); - rust_assert (ok); - } + rust_assert (candidate.has_value ()); } tree enclosing_scope = NULL_TREE; diff --git a/gcc/rust/backend/rust-compile-implitem.cc b/gcc/rust/backend/rust-compile-implitem.cc index f9172c5282c6..63df2f57c16e 100644 --- a/gcc/rust/backend/rust-compile-implitem.cc +++ b/gcc/rust/backend/rust-compile-implitem.cc @@ -27,22 +27,11 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant) rust_assert (concrete != nullptr); TyTy::BaseType *resolved_type = concrete; - tl::optional canonical_path; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path - = nr_ctx.to_canonical_path (constant.get_mappings ().get_nodeid ()); - } - else - { - canonical_path = ctx->get_mappings ().lookup_canonical_path ( - constant.get_mappings ().get_nodeid ()); - } + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - rust_assert (canonical_path); + Resolver::CanonicalPath canonical_path + = nr_ctx.to_canonical_path (constant.get_mappings ().get_nodeid ()); HIR::Expr &const_value_expr = constant.get_expr (); TyTy::BaseType *expr_type = nullptr; @@ -52,7 +41,7 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant) tree const_expr = compile_constant_item (constant.get_mappings ().get_hirid (), expr_type, - resolved_type, *canonical_path, const_value_expr, + resolved_type, canonical_path, const_value_expr, constant.get_locus (), const_value_expr.get_locus ()); ctx->push_const (const_expr); @@ -96,22 +85,11 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func) fntype->override_context (); } - tl::optional canonical_path; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path - = nr_ctx.to_canonical_path (func.get_mappings ().get_nodeid ()); - } - else - { - canonical_path = ctx->get_mappings ().lookup_canonical_path ( - func.get_mappings ().get_nodeid ()); - } + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - rust_assert (canonical_path); + Resolver::CanonicalPath canonical_path + = nr_ctx.to_canonical_path (func.get_mappings ().get_nodeid ()); // FIXME: How do we get the proper visibility here? auto vis = HIR::Visibility (HIR::Visibility::VisType::PUBLIC); @@ -121,7 +99,7 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func) function.get_self (), function.get_function_params (), function.get_qualifiers (), vis, func.get_outer_attrs (), func.get_locus (), - &func.get_block_expr (), *canonical_path, fntype); + &func.get_block_expr (), canonical_path, fntype); reference = address_expression (fndecl, ref_locus); } diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc index 78f6f571e9ce..b72e70d113ec 100644 --- a/gcc/rust/backend/rust-compile-item.cc +++ b/gcc/rust/backend/rust-compile-item.cc @@ -50,33 +50,21 @@ CompileItem::visit (HIR::StaticItem &var) tree type = TyTyResolveCompile::compile (ctx, resolved_type); - tl::optional canonical_path; + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path - = nr_ctx.to_canonical_path (var.get_mappings ().get_nodeid ()); - } - else - { - canonical_path = ctx->get_mappings ().lookup_canonical_path ( - var.get_mappings ().get_nodeid ()); - } - - rust_assert (canonical_path.has_value ()); + Resolver::CanonicalPath canonical_path + = nr_ctx.to_canonical_path (var.get_mappings ().get_nodeid ()); ctx->push_const_context (); tree value = compile_constant_item (var.get_mappings ().get_hirid (), expr_type, - resolved_type, *canonical_path, const_value_expr, + resolved_type, canonical_path, const_value_expr, var.get_locus (), const_value_expr.get_locus ()); ctx->pop_const_context (); - std::string name = canonical_path->get (); - std::string asm_name = ctx->mangle_item (resolved_type, *canonical_path); + std::string name = canonical_path.get (); + std::string asm_name = ctx->mangle_item (resolved_type, canonical_path); bool is_external = false; bool is_hidden = false; @@ -115,23 +103,12 @@ CompileItem::visit (HIR::ConstantItem &constant) const_value_expr.get_mappings ().get_hirid (), &expr_type); rust_assert (ok); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + // canonical path Resolver::CanonicalPath canonical_path - = Resolver::CanonicalPath::create_empty (); - - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path = nr_ctx.to_canonical_path (mappings.get_nodeid ()); - } - else - { - canonical_path = ctx->get_mappings () - .lookup_canonical_path (mappings.get_nodeid ()) - .value (); - } + = nr_ctx.to_canonical_path (mappings.get_nodeid ()); ctx->push_const_context (); tree const_expr @@ -209,24 +186,11 @@ CompileItem::visit (HIR::Function &function) } } - Resolver::CanonicalPath canonical_path - = Resolver::CanonicalPath::create_empty (); - - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - canonical_path - = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ()); - } - else - { - auto path = ctx->get_mappings ().lookup_canonical_path ( - function.get_mappings ().get_nodeid ()); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - canonical_path = *path; - } + Resolver::CanonicalPath canonical_path + = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ()); const std::string asm_name = ctx->mangle_item (fntype, canonical_path); diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 1ce9676913d3..a80484acf097 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -220,30 +220,17 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, // this can fail because it might be a Constructor for something // in that case the caller should attempt ResolvePathType::Compile - NodeId ref_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - auto resolved = nr_ctx.lookup (mappings.get_nodeid ()); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (!resolved) - return attempt_constructor_expression_lookup (lookup, ctx, mappings, - expr_locus); + auto resolved = nr_ctx.lookup (mappings.get_nodeid ()); - ref_node_id = *resolved; - } - else - { - if (!ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (), - &ref_node_id)) - return attempt_constructor_expression_lookup (lookup, ctx, mappings, - expr_locus); - } + if (!resolved) + return attempt_constructor_expression_lookup (lookup, ctx, mappings, + expr_locus); return resolve_with_node_id (final_segment, mappings, expr_locus, - is_qualified_path, ref_node_id); + is_qualified_path, *resolved); } tree From 411928ef998a41ac1e45cc593d6d2633a52afedf Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Tue, 1 Jul 2025 15:54:27 -0400 Subject: [PATCH 124/161] Remove Late visitor override for StructStruct DefaultResolver already handles StructStruct in a more correct fashion. gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove override for StructStruct visitor. * resolve/rust-late-name-resolver-2.0.h (Late::visit): Likewise. Signed-off-by: Owen Avery --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 7 ------- gcc/rust/resolve/rust-late-name-resolver-2.0.h | 1 - 2 files changed, 8 deletions(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index bd15894268c1..03149c49ece5 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -616,13 +616,6 @@ Late::visit (AST::Trait &trait) DefaultResolver::visit (trait); } -void -Late::visit (AST::StructStruct &s) -{ - auto s_vis = [this, &s] () { AST::DefaultASTVisitor::visit (s); }; - ctx.scoped (Rib::Kind::Item, s.get_node_id (), s_vis); -} - void Late::visit (AST::StructExprStruct &s) { diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index f2907c90514e..65af6139e80a 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -66,7 +66,6 @@ class Late : public DefaultResolver void visit (AST::StructExprStruct &) override; void visit (AST::StructExprStructBase &) override; void visit (AST::StructExprStructFields &) override; - void visit (AST::StructStruct &) override; void visit (AST::GenericArgs &) override; void visit (AST::GenericArg &); void visit_closure_params (AST::ClosureExpr &) override; From d939c91e7734be02c99498447a5a7fa089a4d473 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Tue, 1 Jul 2025 17:18:28 -0400 Subject: [PATCH 125/161] Remove reinterpret_cast usages in DefaultASTVisitor gcc/rust/ChangeLog: * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Replace usages of reinterpret_cast with static_cast. Signed-off-by: Owen Avery --- gcc/rust/ast/rust-ast-visitor.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index f21a5bbfcb75..c24425bbb381 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -942,7 +942,7 @@ DefaultASTVisitor::visit (AST::EnumItem &item) void DefaultASTVisitor::visit (AST::EnumItemTuple &item) { - DefaultASTVisitor::visit (reinterpret_cast (item)); + DefaultASTVisitor::visit (static_cast (item)); for (auto &field : item.get_tuple_fields ()) visit (field); } @@ -950,7 +950,7 @@ DefaultASTVisitor::visit (AST::EnumItemTuple &item) void DefaultASTVisitor::visit (AST::EnumItemStruct &item) { - DefaultASTVisitor::visit (reinterpret_cast (item)); + DefaultASTVisitor::visit (static_cast (item)); for (auto &field : item.get_struct_fields ()) visit (field); } @@ -958,7 +958,7 @@ DefaultASTVisitor::visit (AST::EnumItemStruct &item) void DefaultASTVisitor::visit (AST::EnumItemDiscriminant &item) { - DefaultASTVisitor::visit (reinterpret_cast (item)); + DefaultASTVisitor::visit (static_cast (item)); visit (item.get_expr ()); } From c062b44fa172aded34edd05c71c2b82b7a033d1d Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 7 Jul 2025 13:03:10 +0200 Subject: [PATCH 126/161] Change enum to enum class gcc/rust/ChangeLog: * parse/rust-parse-impl.h: Add enum prefix. * parse/rust-parse.h (enum ParseSelfError): Change from enum... (enum class): To enum class. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/parse/rust-parse-impl.h | 6 ++++-- gcc/rust/parse/rust-parse.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 9c9208f9ba49..120817b88b8a 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -5604,7 +5604,8 @@ Parser::parse_inherent_impl_function_or_method ( // param auto initial_param = parse_self_param (); - if (!initial_param.has_value () && initial_param.error () != NOT_SELF) + if (!initial_param.has_value () + && initial_param.error () != ParseSelfError::NOT_SELF) return nullptr; /* FIXME: ensure that self param doesn't accidently consume tokens for a @@ -5803,7 +5804,8 @@ Parser::parse_trait_impl_function_or_method ( // param auto initial_param = parse_self_param (); - if (!initial_param.has_value () && initial_param.error () != NOT_SELF) + if (!initial_param.has_value () + && initial_param.error () != ParseSelfError::NOT_SELF) return nullptr; // FIXME: ensure that self param doesn't accidently consume tokens for a diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 4fab60ffb080..c9b6edb60e98 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -39,7 +39,7 @@ enum class ParseLoopLabelError NOT_LOOP_LABEL, MISSING_COLON, }; -enum ParseSelfError +enum class ParseSelfError { SELF_PTR, PARSING, From b6a90d430ed77b67086116b993a423f7050ffcb1 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Tue, 1 Jul 2025 13:47:59 -0400 Subject: [PATCH 127/161] Allow format_args to accept a raw string literal gcc/rust/ChangeLog: * expand/rust-macro-builtins-format-args.cc (format_args_parse_arguments): Accept a RAW_STRING_LITERAL token as the first argument. Signed-off-by: Owen Avery --- gcc/rust/expand/rust-macro-builtins-format-args.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/gcc/rust/expand/rust-macro-builtins-format-args.cc b/gcc/rust/expand/rust-macro-builtins-format-args.cc index 3e1249d3d36f..b20c84953206 100644 --- a/gcc/rust/expand/rust-macro-builtins-format-args.cc +++ b/gcc/rust/expand/rust-macro-builtins-format-args.cc @@ -52,8 +52,15 @@ format_args_parse_arguments (AST::MacroInvocData &invoc) // TODO: Handle the case where we're not parsing a string literal (macro // invocation for e.g.) - if (parser.peek_current_token ()->get_id () == STRING_LITERAL) - format_expr = parser.parse_literal_expr (); + switch (parser.peek_current_token ()->get_id ()) + { + case STRING_LITERAL: + case RAW_STRING_LITERAL: + format_expr = parser.parse_literal_expr (); + default: + // do nothing + ; + } rust_assert (format_expr); From c55ef858d3aa8b1d1822cb691d3f00782b24f94a Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Wed, 2 Jul 2025 18:48:07 -0400 Subject: [PATCH 128/161] Parse try expressions This doesn't do anything beyond creating TryExpr and parsing them, so try expressions shouldn't be able to make it past AST lowering yet. gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Add visitor for TryExpr. * ast/rust-ast-collector.h (TokenCollector::visit): Likewise. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. * ast/rust-ast-visitor.h (ASTVisitor::visit): Likewise. (DefaultASTVisitor::visit): Likewise. * expand/rust-derive.h (DeriveVisitor::visit): Likewise. * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise. * hir/rust-ast-lower-base.h (ASTLoweringBase::visit): Likewise. * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise. * resolve/rust-ast-resolve-base.h (ResolverBase::visit): Likewise. * ast/rust-ast-full-decls.h (class TryExpr): New forward class declaration. * ast/rust-ast.cc (TryExpr::as_string): New function. (TryExpr::accept_vis): Likewise. * ast/rust-expr.h (class TryExpr): New class. * parse/rust-parse.h (Parser::parse_try_expr): New function. * parse/rust-parse-impl.h (Parser::parse_try_expr): Likewise. (Parser::null_denotation_not_path): Use parse_try_expr to parse try expressions. Signed-off-by: Owen Avery --- gcc/rust/ast/rust-ast-collector.cc | 7 +++ gcc/rust/ast/rust-ast-collector.h | 1 + gcc/rust/ast/rust-ast-full-decls.h | 1 + gcc/rust/ast/rust-ast-visitor.cc | 7 +++ gcc/rust/ast/rust-ast-visitor.h | 2 + gcc/rust/ast/rust-ast.cc | 19 ++++++ gcc/rust/ast/rust-expr.h | 76 +++++++++++++++++++++++ gcc/rust/expand/rust-derive.h | 1 + gcc/rust/hir/rust-ast-lower-base.cc | 3 + gcc/rust/hir/rust-ast-lower-base.h | 1 + gcc/rust/parse/rust-parse-impl.h | 31 +++++++++ gcc/rust/parse/rust-parse.h | 3 + gcc/rust/resolve/rust-ast-resolve-base.cc | 4 ++ gcc/rust/resolve/rust-ast-resolve-base.h | 1 + 14 files changed, 157 insertions(+) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 5a8d462dbd7b..0b5f27d36d2c 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -1370,6 +1370,13 @@ TokenCollector::visit (ReturnExpr &expr) visit (expr.get_returned_expr ()); } +void +TokenCollector::visit (TryExpr &expr) +{ + push (Rust::Token::make (TRY, expr.get_locus ())); + visit (expr.get_block_expr ()); +} + void TokenCollector::visit (UnsafeBlockExpr &expr) { diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index cec2365892ec..e8af5878a2cd 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -289,6 +289,7 @@ class TokenCollector : public ASTVisitor void visit (RangeFromToInclExpr &expr); void visit (RangeToInclExpr &expr); void visit (ReturnExpr &expr); + void visit (TryExpr &expr); void visit (BoxExpr &expr); void visit (UnsafeBlockExpr &expr); void visit (LoopExpr &expr); diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index b410f3ad006e..eb1f3ea890c7 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -128,6 +128,7 @@ class RangeFullExpr; class RangeFromToInclExpr; class RangeToInclExpr; class ReturnExpr; +class TryExpr; class UnsafeBlockExpr; class LoopLabel; class BaseLoopExpr; diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index c24425bbb381..fd45fb1060d3 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -549,6 +549,13 @@ DefaultASTVisitor::visit (AST::ReturnExpr &expr) visit (expr.get_returned_expr ()); } +void +DefaultASTVisitor::visit (AST::TryExpr &expr) +{ + visit_outer_attrs (expr); + visit (expr.get_block_expr ()); +} + void DefaultASTVisitor::visit (AST::BoxExpr &expr) { diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index 22fd98b6ea8c..6111b0548edc 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -116,6 +116,7 @@ class ASTVisitor virtual void visit (RangeFromToInclExpr &expr) = 0; virtual void visit (RangeToInclExpr &expr) = 0; virtual void visit (ReturnExpr &expr) = 0; + virtual void visit (TryExpr &expr) = 0; virtual void visit (BoxExpr &expr) = 0; virtual void visit (UnsafeBlockExpr &expr) = 0; virtual void visit (LoopExpr &expr) = 0; @@ -307,6 +308,7 @@ class DefaultASTVisitor : public ASTVisitor virtual void visit (AST::RangeFromToInclExpr &expr) override; virtual void visit (AST::RangeToInclExpr &expr) override; virtual void visit (AST::ReturnExpr &expr) override; + virtual void visit (AST::TryExpr &expr) override; virtual void visit (AST::BoxExpr &expr) override; virtual void visit (AST::UnsafeBlockExpr &expr) override; virtual void visit (AST::LoopExpr &expr) override; diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 916829fe95c0..4d928ca7a2d5 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -1636,6 +1636,19 @@ ReturnExpr::as_string () const return str; } +std::string +TryExpr::as_string () const +{ + /* TODO: find way to incorporate outer attrs - may have to represent in + * different style (i.e. something more like BorrowExpr: \n outer attrs) */ + + std::string str ("try "); + + str += block_expr->as_string (); + + return str; +} + std::string RangeToExpr::as_string () const { @@ -4604,6 +4617,12 @@ ReturnExpr::accept_vis (ASTVisitor &vis) vis.visit (*this); } +void +TryExpr::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + void UnsafeBlockExpr::accept_vis (ASTVisitor &vis) { diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 21e856bb1d0e..3e50c46e58de 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -3700,6 +3700,82 @@ class ReturnExpr : public ExprWithoutBlock } }; +// Try expression AST node representation +class TryExpr : public ExprWithBlock +{ + std::vector outer_attrs; + std::unique_ptr block_expr; + location_t locus; + + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + +public: + std::string as_string () const override; + + // Constructor for ReturnExpr. + TryExpr (std::unique_ptr block_expr, + std::vector outer_attribs, location_t locus) + : outer_attrs (std::move (outer_attribs)), + block_expr (std::move (block_expr)), locus (locus) + { + rust_assert (this->block_expr); + } + + // Copy constructor with clone + TryExpr (TryExpr const &other) + : ExprWithBlock (other), outer_attrs (other.outer_attrs), + block_expr (other.block_expr->clone_block_expr ()), locus (other.locus), + marked_for_strip (other.marked_for_strip) + {} + + // Overloaded assignment operator to clone return_expr pointer + TryExpr &operator= (TryExpr const &other) + { + ExprWithBlock::operator= (other); + locus = other.locus; + marked_for_strip = other.marked_for_strip; + outer_attrs = other.outer_attrs; + + block_expr = other.block_expr->clone_block_expr (); + + return *this; + } + + // move constructors + TryExpr (TryExpr &&other) = default; + TryExpr &operator= (TryExpr &&other) = default; + + location_t get_locus () const override final { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } + + // TODO: is this better? Or is a "vis_block" better? + BlockExpr &get_block_expr () { return *block_expr; } + + const std::vector &get_outer_attrs () const { return outer_attrs; } + std::vector &get_outer_attrs () override { return outer_attrs; } + + void set_outer_attrs (std::vector new_attrs) override + { + outer_attrs = std::move (new_attrs); + } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::Return; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TryExpr *clone_expr_with_block_impl () const override + { + return new TryExpr (*this); + } +}; + // Forward decl - defined in rust-macro.h class MacroInvocation; diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index ff4f427695ad..61c7355e7ab2 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -159,6 +159,7 @@ class DeriveVisitor : public AST::ASTVisitor virtual void visit (RangeFromToInclExpr &expr) override final{}; virtual void visit (RangeToInclExpr &expr) override final{}; virtual void visit (ReturnExpr &expr) override final{}; + virtual void visit (TryExpr &expr) override final{}; virtual void visit (BoxExpr &expr) override final{}; virtual void visit (UnsafeBlockExpr &expr) override final{}; virtual void visit (LoopExpr &expr) override final{}; diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index 5b35052b6656..b07ac0c07500 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -242,6 +242,9 @@ void ASTLoweringBase::visit (AST::ReturnExpr &) {} void +ASTLoweringBase::visit (AST::TryExpr &) +{} +void ASTLoweringBase::visit (AST::UnsafeBlockExpr &) {} void diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index 51912be66b4f..0284ff0c82bb 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -144,6 +144,7 @@ class ASTLoweringBase : public AST::ASTVisitor virtual void visit (AST::RangeToInclExpr &expr) override; virtual void visit (AST::BoxExpr &expr) override; virtual void visit (AST::ReturnExpr &expr) override; + virtual void visit (AST::TryExpr &expr) override; virtual void visit (AST::UnsafeBlockExpr &expr) override; virtual void visit (AST::LoopExpr &expr) override; virtual void visit (AST::WhileLoopExpr &expr) override; diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 120817b88b8a..9608cd885f4a 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -7570,6 +7570,34 @@ Parser::parse_return_expr (AST::AttrVec outer_attrs, locus)); } +// Parses a try expression. +template +std::unique_ptr +Parser::parse_try_expr (AST::AttrVec outer_attrs, + location_t pratt_parsed_loc) +{ + location_t locus = pratt_parsed_loc; + if (locus == UNKNOWN_LOCATION) + { + locus = lexer.peek_token ()->get_locus (); + skip_token (TRY); + } + + std::unique_ptr block_expr = parse_block_expr (); + + if (!block_expr) + { + Error error (lexer.peek_token ()->get_locus (), + "failed to parse try block expression"); + add_error (std::move (error)); + + return nullptr; + } + + return std::unique_ptr ( + new AST::TryExpr (std::move (block_expr), std::move (outer_attrs), locus)); +} + /* Parses a break expression (including any label to break to AND any return * expression). */ template @@ -12508,6 +12536,9 @@ Parser::null_denotation_not_path ( case RETURN_KW: // FIXME: is this really a null denotation expression? return parse_return_expr (std::move (outer_attrs), tok->get_locus ()); + case TRY: + // FIXME: is this really a null denotation expression? + return parse_try_expr (std::move (outer_attrs), tok->get_locus ()); case BREAK: // FIXME: is this really a null denotation expression? return parse_break_expr (std::move (outer_attrs), tok->get_locus ()); diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index c9b6edb60e98..36426d56f8d7 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -649,6 +649,9 @@ template class Parser std::unique_ptr parse_return_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); + std::unique_ptr + parse_try_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + location_t pratt_parsed_loc = UNKNOWN_LOCATION); std::unique_ptr parse_break_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc index 71c4c4834db2..05f34bc3f874 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ b/gcc/rust/resolve/rust-ast-resolve-base.cc @@ -283,6 +283,10 @@ void ResolverBase::visit (AST::ReturnExpr &) {} +void +ResolverBase::visit (AST::TryExpr &) +{} + void ResolverBase::visit (AST::UnsafeBlockExpr &) {} diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index e17bdcb5eaad..0cbf78e39abc 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -99,6 +99,7 @@ class ResolverBase : public AST::ASTVisitor void visit (AST::RangeToInclExpr &); void visit (AST::BoxExpr &); void visit (AST::ReturnExpr &); + void visit (AST::TryExpr &); void visit (AST::UnsafeBlockExpr &); void visit (AST::LoopExpr &); void visit (AST::WhileLoopExpr &); From 5ff8386bc606387eeafe134158e1a805e933dd30 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 19 May 2025 12:27:17 +0200 Subject: [PATCH 129/161] ast: Check before visiting a while-let's label gcc/rust/ChangeLog: * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Check that the WhileLet has a label before visiting it. gcc/testsuite/ChangeLog: * rust/compile/while_let_without_label.rs: New test. --- gcc/rust/ast/rust-ast-visitor.cc | 5 ++++- gcc/testsuite/rust/compile/while_let_without_label.rs | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/rust/compile/while_let_without_label.rs diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index fd45fb1060d3..ca7b3e495d0f 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -601,7 +601,10 @@ DefaultASTVisitor::visit (AST::WhileLetLoopExpr &expr) visit_outer_attrs (expr); for (auto &pattern : expr.get_patterns ()) visit (pattern); - visit (expr.get_loop_label ()); + + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + visit (expr.get_scrutinee_expr ()); visit (expr.get_loop_block ()); } diff --git a/gcc/testsuite/rust/compile/while_let_without_label.rs b/gcc/testsuite/rust/compile/while_let_without_label.rs new file mode 100644 index 000000000000..e04e4b59d1df --- /dev/null +++ b/gcc/testsuite/rust/compile/while_let_without_label.rs @@ -0,0 +1,11 @@ +// { dg-additional-options "-frust-compile-until=lowering" } + +enum Foo { + A(i32), +} + +fn main() { + let b = Foo::A(15); + + while let Foo::A(x) = b {} +} From dfbf9e349263a98bcf2d7887cdbac91c7f5a6f86 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 4 Jul 2025 15:40:02 +0200 Subject: [PATCH 130/161] nr2.0: Add proper handling for WhileLet loops. gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::visit): New visitor. * resolve/rust-late-name-resolver-2.0.h: Declare it. * resolve/rust-name-resolution-context.h (enum class): New binding context. --- .../resolve/rust-late-name-resolver-2.0.cc | 23 +++++++++++++++++++ .../resolve/rust-late-name-resolver-2.0.h | 1 + .../resolve/rust-name-resolution-context.h | 1 + 3 files changed, 25 insertions(+) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 03149c49ece5..d33ec3ca39d2 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -19,6 +19,7 @@ #include "optional.h" #include "rust-ast-full.h" #include "rust-diagnostics.h" +#include "rust-expr.h" #include "rust-hir-map.h" #include "rust-late-name-resolver-2.0.h" #include "rust-default-resolver.h" @@ -208,6 +209,28 @@ Late::visit (AST::LetStmt &let) // let.get_node_id (), [] () {}); } +void +Late::visit (AST::WhileLetLoopExpr &while_let) +{ + DefaultASTVisitor::visit_outer_attrs (while_let); + + if (while_let.has_loop_label ()) + visit (while_let.get_loop_label ()); + + // visit expression before pattern + // this makes variable shadowing work properly + visit (while_let.get_scrutinee_expr ()); + + ctx.bindings.enter (BindingSource::WhileLet); + + for (auto &pattern : while_let.get_patterns ()) + visit (pattern); + + ctx.bindings.exit (); + + visit (while_let.get_loop_block ()); +} + static void visit_identifier_as_pattern (NameResolutionContext &ctx, const Identifier &ident, location_t locus, diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 65af6139e80a..95540e340053 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -42,6 +42,7 @@ class Late : public DefaultResolver // some more label declarations void visit (AST::LetStmt &) override; + void visit (AST::WhileLetLoopExpr &) override; // TODO: Do we need this? // void visit (AST::Method &) override; void visit (AST::IdentifierPattern &) override; diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index 0180919db7e7..558b3cab6647 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -198,6 +198,7 @@ enum class BindingSource Match, Let, IfLet, + WhileLet, For, /* Closure param or function param */ Param From cdcc89bd0c1f18e64842cf290054de901022b504 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 8 Jul 2025 21:13:48 +0100 Subject: [PATCH 131/161] gccrs: Do proper const folding during typechecking for array capacities This patch adds proper folding to the const expression for array capacity we already have the const folding mechanics and the query system needed to handle cases where the capacity is a function call in a const context. This leverages and pulls the gcc tree capacity into the TyTy::ArrayType so it can be used for more typechecking and eventually doing more const generics work. Addresses Rust-GCC#3885 Fixes Rust-GCC#3882 gcc/rust/ChangeLog: * backend/rust-compile-base.cc (HIRCompileBase::query_compile_const_expr): new wrapper * backend/rust-compile-base.h: add prototype * backend/rust-compile-context.cc (Context::get): singleton helper * backend/rust-compile-context.h: likewise * backend/rust-compile-type.cc (TyTyResolveCompile::visit): handle infer's that can default * rust-session-manager.cc (Session::compile_crate): create the gcc context earlier for tychk * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): const fold it * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise * typecheck/rust-tyty.cc (BaseType::monomorphized_clone): fix constructor call (ArrayType::as_string): print capacity (ArrayType::clone): fix constructor call * typecheck/rust-tyty.h: track capacity * typecheck/rust-unify.cc (UnifyRules::expect_array): check the capacities gcc/testsuite/ChangeLog: * rust/compile/all-cast.rs: shows array capacity now * rust/compile/arrays2.rs: likewise * rust/compile/const3.rs: fix error message * rust/compile/const_generics_3.rs: disable until typecheck we get proper errors now! * rust/compile/usize1.rs: proper capacity error message Signed-off-by: Philip Herron --- gcc/rust/backend/rust-compile-base.cc | 19 +++++++++++++ gcc/rust/backend/rust-compile-base.h | 3 ++ gcc/rust/backend/rust-compile-context.cc | 10 +++++++ gcc/rust/backend/rust-compile-context.h | 4 ++- gcc/rust/backend/rust-compile-type.cc | 24 ++++++---------- gcc/rust/rust-session-manager.cc | 10 +++---- .../typecheck/rust-hir-type-check-base.cc | 7 +++-- .../typecheck/rust-hir-type-check-expr.cc | 28 +++++++++++++------ .../typecheck/rust-hir-type-check-type.cc | 12 ++++++-- gcc/rust/typecheck/rust-tyty.cc | 17 +++++++++-- gcc/rust/typecheck/rust-tyty.h | 18 ++++++------ gcc/rust/typecheck/rust-unify.cc | 27 ++++++++++++------ gcc/testsuite/rust/compile/all-cast.rs | 2 +- gcc/testsuite/rust/compile/arrays2.rs | 3 +- gcc/testsuite/rust/compile/const3.rs | 2 +- .../rust/compile/const_generics_3.rs | 2 +- gcc/testsuite/rust/compile/usize1.rs | 2 +- 17 files changed, 127 insertions(+), 63 deletions(-) diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index c9f9fbe76bfd..b2913ad3c381 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -575,6 +575,25 @@ HIRCompileBase::compile_constant_expr ( expr_locus); } +tree +HIRCompileBase::query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty, + HIR::Expr &const_value_expr) +{ + HIRCompileBase c (ctx); + + ctx->push_const_context (); + + HirId expr_id = const_value_expr.get_mappings ().get_hirid (); + location_t locus = const_value_expr.get_locus (); + tree capacity_expr = HIRCompileBase::compile_constant_expr ( + ctx, expr_id, expr_ty, expr_ty, Resolver::CanonicalPath::create_empty (), + const_value_expr, locus, locus); + + ctx->pop_const_context (); + + return fold_expr (capacity_expr); +} + tree HIRCompileBase::indirect_expression (tree expr, location_t locus) { diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index 6814abcf9deb..e9b85968fac3 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -38,6 +38,9 @@ class HIRCompileBase const Resolver::CanonicalPath &canonical_path, HIR::Expr &const_value_expr, location_t locus, location_t expr_locus); + static tree query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty, + HIR::Expr &const_value_expr); + protected: HIRCompileBase (Context *ctx) : ctx (ctx) {} diff --git a/gcc/rust/backend/rust-compile-context.cc b/gcc/rust/backend/rust-compile-context.cc index 3f328d33e7fb..349d4927cb48 100644 --- a/gcc/rust/backend/rust-compile-context.cc +++ b/gcc/rust/backend/rust-compile-context.cc @@ -22,6 +22,16 @@ namespace Rust { namespace Compile { +Context * +Context::get () +{ + static Context *instance; + if (instance == nullptr) + instance = new Context (); + + return instance; +} + Context::Context () : tyctx (Resolver::TypeCheckContext::get ()), mappings (Analysis::Mappings::get ()), mangler (Mangler ()) diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index bb942816946d..d4a642b653ca 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -49,7 +49,7 @@ struct CustomDeriveInfo class Context { public: - Context (); + static Context *get (); void setup_builtins (); @@ -390,6 +390,8 @@ class Context } private: + Context (); + Resolver::TypeCheckContext *tyctx; Analysis::Mappings &mappings; Mangler mangler; diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index c397b4beb4ca..8f13bba534b6 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -121,6 +121,13 @@ TyTyResolveCompile::visit (const TyTy::InferType &type) if (orig == lookup) { + TyTy::BaseType *def = nullptr; + if (type.default_type (&def)) + { + translated = TyTyResolveCompile::compile (ctx, def); + return; + } + translated = error_mark_node; return; } @@ -463,22 +470,7 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type) { tree element_type = TyTyResolveCompile::compile (ctx, type.get_element_type ()); - - ctx->push_const_context (); - - HIR::Expr &hir_capacity_expr = type.get_capacity_expr (); - TyTy::BaseType *capacity_expr_ty = nullptr; - bool ok = ctx->get_tyctx ()->lookup_type ( - hir_capacity_expr.get_mappings ().get_hirid (), &capacity_expr_ty); - rust_assert (ok); - tree capacity_expr = HIRCompileBase::compile_constant_expr ( - ctx, hir_capacity_expr.get_mappings ().get_hirid (), capacity_expr_ty, - capacity_expr_ty, Resolver::CanonicalPath::create_empty (), - hir_capacity_expr, type.get_locus (), hir_capacity_expr.get_locus ()); - - ctx->pop_const_context (); - - tree folded_capacity_expr = fold_expr (capacity_expr); + tree folded_capacity_expr = type.get_capacity (); // build_index_type takes the maximum index, which is one less than // the length. diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 3252fcdcc6c0..12cdc2e5dba9 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -681,6 +681,7 @@ Session::compile_crate (const char *filename) Resolver2_0::ImmutableNameResolutionContext::init (name_resolution_ctx); // type resolve + Compile::Context *ctx = Compile::Context::get (); Resolver::TypeResolution::Resolve (hir); Resolver::TypeCheckContext::get ()->get_variance_analysis_ctx ().solve (); @@ -728,16 +729,15 @@ Session::compile_crate (const char *filename) return; // do compile to gcc generic - Compile::Context ctx; - Compile::CompileCrate::Compile (hir, &ctx); + Compile::CompileCrate::Compile (hir, ctx); // we can't do static analysis if there are errors to worry about if (!saw_errors ()) { // lints Analysis::ScanDeadcode::Scan (hir); - Analysis::UnusedVariables::Lint (ctx); - Analysis::ReadonlyCheck::Lint (ctx); + Analysis::UnusedVariables::Lint (*ctx); + Analysis::ReadonlyCheck::Lint (*ctx); // metadata bool specified_emit_metadata @@ -758,7 +758,7 @@ Session::compile_crate (const char *filename) } // pass to GCC middle-end - ctx.write_to_backend (); + ctx->write_to_backend (); } void diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index 6d5806f967f8..4bbd52a29f45 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -17,6 +17,7 @@ // . #include "rust-hir-type-check-base.h" +#include "rust-compile-base.h" #include "rust-hir-type-check-expr.h" #include "rust-hir-type-check-type.h" #include "rust-hir-trait-resolve.h" @@ -287,9 +288,11 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, crate_num), UNKNOWN_LOCAL_DEFID); + auto ctx = Compile::Context::get (); + tree capacity = Compile::HIRCompileBase::query_compile_const_expr ( + ctx, expected_ty, *literal_capacity); TyTy::ArrayType *array - = new TyTy::ArrayType (array_mapping.get_hirid (), locus, - *literal_capacity, + = new TyTy::ArrayType (array_mapping.get_hirid (), locus, capacity, TyTy::TyVar (u8->get_ref ())); context->insert_type (array_mapping, array); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index eb50803814f4..ccde4dd77bff 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -31,6 +31,7 @@ #include "rust-hir-type-check-item.h" #include "rust-type-util.h" #include "rust-immutable-name-resolution-context.h" +#include "rust-compile-base.h" // for flag_name_resolution_2_0 #include "options.h" @@ -1031,6 +1032,7 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) HIR::Expr *capacity_expr = nullptr; TyTy::BaseType *element_type = nullptr; + TyTy::BaseType *capacity_type = nullptr; switch (elements.get_array_expr_type ()) { case HIR::ArrayElems::ArrayExprType::COPIED: @@ -1039,7 +1041,7 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) = static_cast (elements); element_type = TypeCheckExpr::Resolve (elems.get_elem_to_copy ()); - auto capacity_type + auto capacity_expr_ty = TypeCheckExpr::Resolve (elems.get_num_copies_expr ()); TyTy::BaseType *expected_ty = nullptr; @@ -1048,13 +1050,14 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) context->insert_type (elems.get_num_copies_expr ().get_mappings (), expected_ty); - unify_site (expr.get_mappings ().get_hirid (), - TyTy::TyWithLocation (expected_ty), - TyTy::TyWithLocation ( - capacity_type, elems.get_num_copies_expr ().get_locus ()), - expr.get_locus ()); + unify_site ( + expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty), + TyTy::TyWithLocation (capacity_expr_ty, + elems.get_num_copies_expr ().get_locus ()), + expr.get_locus ()); capacity_expr = &elems.get_num_copies_expr (); + capacity_type = expected_ty; } break; @@ -1096,13 +1099,20 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) bool ok = context->lookup_builtin ("usize", &expected_ty); rust_assert (ok); context->insert_type (mapping, expected_ty); + capacity_type = expected_ty; } break; } - infered = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), - expr.get_locus (), *capacity_expr, - TyTy::TyVar (element_type->get_ref ())); + rust_assert (capacity_expr); + rust_assert (capacity_type); + auto ctx = Compile::Context::get (); + tree capacity + = Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type, + *capacity_expr); + infered + = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), expr.get_locus (), + capacity, TyTy::TyVar (element_type->get_ref ())); } // empty struct diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index f23352baacda..462b3d487673 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -29,6 +29,7 @@ #include "rust-substitution-mapper.h" #include "rust-type-util.h" #include "rust-system.h" +#include "rust-compile-base.h" namespace Rust { namespace Resolver { @@ -710,9 +711,14 @@ TypeCheckType::visit (HIR::ArrayType &type) type.get_size_expr ().get_locus ()); TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ()); - translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (), - type.get_locus (), type.get_size_expr (), - TyTy::TyVar (base->get_ref ())); + + auto ctx = Compile::Context::get (); + tree capacity + = Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type, + type.get_size_expr ()); + translated + = new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (), + capacity, TyTy::TyVar (base->get_ref ())); } void diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index e2dfa743b9aa..75370e96c662 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -30,9 +30,11 @@ #include "rust-tyty-cmp.h" #include "rust-type-util.h" #include "rust-hir-type-bounds.h" +#include "print-tree.h" #include "options.h" #include "rust-system.h" +#include "tree.h" namespace Rust { namespace TyTy { @@ -574,7 +576,7 @@ BaseType::monomorphized_clone () const { TyVar elm = arr->get_var_element_type ().monomorphized_clone (); return new ArrayType (arr->get_ref (), arr->get_ty_ref (), ident.locus, - arr->get_capacity_expr (), elm, + arr->get_capacity (), elm, arr->get_combined_refs ()); } else if (auto slice = x->try_as ()) @@ -2486,7 +2488,16 @@ ArrayType::accept_vis (TyConstVisitor &vis) const std::string ArrayType::as_string () const { - return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]"; + std::string capacity_str = ""; + if (!error_operand_p (capacity)) + { + unsigned HOST_WIDE_INT length = wi::to_wide (capacity).to_uhwi (); + + char buf[64]; + snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_UNSIGNED, length); + capacity_str = std::string (buf); + } + return "[" + get_element_type ()->as_string () + "; " + capacity_str + "]"; } bool @@ -2525,7 +2536,7 @@ ArrayType::get_var_element_type () const BaseType * ArrayType::clone () const { - return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity_expr, + return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity, element_type, get_combined_refs ()); } diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index e8ddd3e1d91d..e0d0358e9e66 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -29,6 +29,7 @@ #include "rust-tyty-region.h" #include "rust-system.h" #include "rust-hir.h" +#include "tree.h" namespace Rust { @@ -1156,19 +1157,18 @@ class ArrayType : public BaseType public: static constexpr auto KIND = TypeKind::ARRAY; - ArrayType (HirId ref, location_t locus, HIR::Expr &capacity_expr, TyVar base, + ArrayType (HirId ref, location_t locus, tree capacity, TyVar base, std::set refs = std::set ()) : BaseType (ref, ref, TypeKind::ARRAY, {Resolver::CanonicalPath::create_empty (), locus}, refs), - element_type (base), capacity_expr (capacity_expr) + element_type (base), capacity (capacity) {} - ArrayType (HirId ref, HirId ty_ref, location_t locus, - HIR::Expr &capacity_expr, TyVar base, - std::set refs = std::set ()) + ArrayType (HirId ref, HirId ty_ref, location_t locus, tree capacity, + TyVar base, std::set refs = std::set ()) : BaseType (ref, ty_ref, TypeKind::ARRAY, {Resolver::CanonicalPath::create_empty (), locus}, refs), - element_type (base), capacity_expr (capacity_expr) + element_type (base), capacity (capacity) {} void accept_vis (TyVisitor &vis) override; @@ -1187,15 +1187,13 @@ class ArrayType : public BaseType BaseType *clone () const final override; - HIR::Expr &get_capacity_expr () const { return capacity_expr; } + tree get_capacity () const { return capacity; } ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings); private: TyVar element_type; - // FIXME: I dont think this should be in tyty - tyty should already be const - // evaluated - HIR::Expr &capacity_expr; + tree capacity; }; class SliceType : public BaseType diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 2a981acaf3a7..ac9019369826 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -17,6 +17,7 @@ // . #include "rust-unify.h" +#include "tree.h" namespace Rust { namespace Resolver { @@ -825,14 +826,24 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()), TyTy::TyWithLocation (type.get_element_type ())); - if (element_unify->get_kind () != TyTy::TypeKind::ERROR) - { - return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (), - type.get_ident ().locus, - type.get_capacity_expr (), - TyTy::TyVar ( - element_unify->get_ref ())); - } + if (element_unify->get_kind () == TyTy::TypeKind::ERROR) + return new TyTy::ErrorType (0); + + // TODO infer capacity? + tree lcap = ltype->get_capacity (); + tree rcap = type.get_capacity (); + if (error_operand_p (lcap) || error_operand_p (rcap)) + return new TyTy::ErrorType (0); + + auto lc = wi::to_wide (lcap).to_uhwi (); + auto rc = wi::to_wide (rcap).to_uhwi (); + if (lc != rc) + return new TyTy::ErrorType (0); + + return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (), + type.get_ident ().locus, + type.get_capacity (), + TyTy::TyVar (element_unify->get_ref ())); } break; diff --git a/gcc/testsuite/rust/compile/all-cast.rs b/gcc/testsuite/rust/compile/all-cast.rs index fa24373a6779..6d8576cc84f0 100644 --- a/gcc/testsuite/rust/compile/all-cast.rs +++ b/gcc/testsuite/rust/compile/all-cast.rs @@ -4,7 +4,7 @@ fn main() { 0u32 as char; // { dg-error "cannot cast .u32. as .char., only .u8. can be cast as .char." } - let x = &[1_usize, 2] as [usize]; // { dg-error "cast to unsized type: .& .usize:CAPACITY.. as ..usize.." } + let x = &[1_usize, 2] as [usize]; // { dg-error "cast to unsized type: .& .usize; 2.. as ..usize.." } let a = &0u8; // Here, `x` is a `&u8`. let y: u32 = a as u32; // { dg-error "casting .& u8. as .u32. is invalid" } diff --git a/gcc/testsuite/rust/compile/arrays2.rs b/gcc/testsuite/rust/compile/arrays2.rs index 668bcf0951b1..109005922c34 100644 --- a/gcc/testsuite/rust/compile/arrays2.rs +++ b/gcc/testsuite/rust/compile/arrays2.rs @@ -1,5 +1,4 @@ -// { dg-additional-options "-w" } fn main() { let array: [i32; 5] = [1, 2, 3]; - // { dg-error "mismatched types, expected an array with a fixed size of 5 elements, found one with 3 elements" "" { target *-*-* } .-1 } + // { dg-error "mismatched types, expected ..i32; 5.. but got ...integer.; 3.. .E0308." "" { target *-*-* } .-1 } } diff --git a/gcc/testsuite/rust/compile/const3.rs b/gcc/testsuite/rust/compile/const3.rs index 22dc3d356cac..c1d0f29ae199 100644 --- a/gcc/testsuite/rust/compile/const3.rs +++ b/gcc/testsuite/rust/compile/const3.rs @@ -3,5 +3,5 @@ fn size() -> usize { } fn main() { - let a = [15; size()]; // { dg-error "only functions marked as .const. are allowed to be called from constant contexts" } + let a = [15; size()]; // { dg-error "calls in constants are limited to constant functions, tuple structs and tuple variants" } } diff --git a/gcc/testsuite/rust/compile/const_generics_3.rs b/gcc/testsuite/rust/compile/const_generics_3.rs index 09d5835074d1..d8b2ddfedaf0 100644 --- a/gcc/testsuite/rust/compile/const_generics_3.rs +++ b/gcc/testsuite/rust/compile/const_generics_3.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-w -frust-compile-until=compilation" } +// { dg-additional-options "-w -frust-compile-until=typecheck" } #[lang = "sized"] trait Sized {} diff --git a/gcc/testsuite/rust/compile/usize1.rs b/gcc/testsuite/rust/compile/usize1.rs index 36cb99b5574a..08f6c9cf5cb4 100644 --- a/gcc/testsuite/rust/compile/usize1.rs +++ b/gcc/testsuite/rust/compile/usize1.rs @@ -1,5 +1,5 @@ fn main() { let a = [1, 2, 3]; let b: u32 = 1; - let c = a[b]; // { dg-error "the type ...integer..CAPACITY.. cannot be indexed by .u32." } + let c = a[b]; // { dg-error "the type ...integer.; 3.. cannot be indexed by .u32." } } From fafc801e4224cfdd37ef8e1cbd1695c40a6306d1 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 8 Jul 2025 22:33:02 +0100 Subject: [PATCH 132/161] gccrs: Fix ice with invalid borrow expression This is an invalid test case but we just need a guard for the missing borrow expression. Fixes Rust-GCC#3874 gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): check for missing borrow * ast/rust-expr.h: add helper gcc/testsuite/ChangeLog: * rust/compile/issue-3874.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/ast/rust-ast-collector.cc | 3 ++- gcc/rust/ast/rust-expr.h | 2 ++ gcc/testsuite/rust/compile/issue-3874.rs | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/rust/compile/issue-3874.rs diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 0b5f27d36d2c..4fe246d7a3ad 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -870,7 +870,8 @@ TokenCollector::visit (BorrowExpr &expr) push (Rust::Token::make (MUT, UNDEF_LOCATION)); } - visit (expr.get_borrowed_expr ()); + if (expr.has_borrow_expr ()) + visit (expr.get_borrowed_expr ()); } void diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 3e50c46e58de..296821131b1e 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -395,6 +395,8 @@ class BorrowExpr : public OperatorExpr return *main_or_left_expr; } + bool has_borrow_expr () const { return main_or_left_expr != nullptr; } + bool get_is_mut () const { return mutability == Mutability::Mut; } Mutability get_mutability () const { return mutability; } diff --git a/gcc/testsuite/rust/compile/issue-3874.rs b/gcc/testsuite/rust/compile/issue-3874.rs new file mode 100644 index 000000000000..ebce4b6da87d --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3874.rs @@ -0,0 +1,4 @@ +fn wow(){ + &#[serde] + // { dg-error "found unexpected token .#. in null denotation" "" { target *-*-* } .-1 } +} From 16f562f9c09f381fa120c49b4eb3f49cee3ff9a5 Mon Sep 17 00:00:00 2001 From: Yap Zhi Heng Date: Tue, 8 Jul 2025 22:10:46 +0800 Subject: [PATCH 133/161] gccrs: Add type checking for SlicePattern This commit implements basic type checking support for SlicePattern, based on rustc's check_pat_slice function. gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(SlicePattern)): Implement initial type checking for SlicePattern. Signed-off-by: Yap Zhi Heng --- .../typecheck/rust-hir-type-check-pattern.cc | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index 537c3491265b..c60d7868fdae 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -636,8 +636,44 @@ TypeCheckPattern::visit (HIR::ReferencePattern &pattern) void TypeCheckPattern::visit (HIR::SlicePattern &pattern) { - rust_sorry_at (pattern.get_locus (), - "type checking qualified path patterns not supported"); + auto resolved_parent = parent->destructure (); + TyTy::BaseType *parent_element_ty = nullptr; + switch (resolved_parent->get_kind ()) + { + case TyTy::ARRAY: + { + // FIXME: implement compile-time size checks when ArrayType's capacity + // is updated to be evaluated in compile-time + // https://github.com/Rust-GCC/gccrs/issues/3882 + auto &array_ty_ty = static_cast (*parent); + parent_element_ty = array_ty_ty.get_element_type (); + break; + } + case TyTy::SLICE: + { + auto &array_ty_ty = static_cast (*parent); + parent_element_ty = array_ty_ty.get_element_type (); + break; + } + default: + { + rust_error_at (pattern.get_locus (), "expected %s, found slice", + parent->as_string ().c_str ()); + return; + } + } + + rust_assert (parent_element_ty != nullptr); + // infered inherits array/slice typing from parent + infered = parent->clone (); + infered->set_ref (pattern.get_mappings ().get_hirid ()); + + // Type check every item in the SlicePattern against parent's element ty + // TODO update this after adding support for RestPattern in SlicePattern + for (const auto &item : pattern.get_items ()) + { + TypeCheckPattern::Resolve (*item, parent_element_ty); + } } void From c28db6616dd09f9e1a482d47b17487dbdbeea75a Mon Sep 17 00:00:00 2001 From: Yap Zhi Heng Date: Tue, 8 Jul 2025 22:15:09 +0800 Subject: [PATCH 134/161] gccrs: Improve LiteralPattern type checking This change is made to ensure that LiteralPatterns in SlicePattern are type-checked against the scrutinee array/slice's element type properly. gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-pattern.cc(TypeCheckPattern::visit(LiteralPattern)): Check LiteralPattern's type against its parent. Signed-off-by: Yap Zhi Heng --- gcc/rust/typecheck/rust-hir-type-check-pattern.cc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index c60d7868fdae..5608030db72c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -563,8 +563,18 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) void TypeCheckPattern::visit (HIR::LiteralPattern &pattern) { - infered = resolve_literal (pattern.get_mappings (), pattern.get_literal (), - pattern.get_locus ()); + TyTy::BaseType *resolved + = resolve_literal (pattern.get_mappings (), pattern.get_literal (), + pattern.get_locus ()); + if (resolved->get_kind () == TyTy::TypeKind::ERROR) + { + infered = resolved; + return; + } + + infered = unify_site (pattern.get_mappings ().get_hirid (), + TyTy::TyWithLocation (parent), + TyTy::TyWithLocation (resolved), pattern.get_locus ()); } void From 3961193eceba3624991e55a98d877f7f05b00885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Poulhi=C3=A8s?= Date: Thu, 3 Jul 2025 23:29:48 +0200 Subject: [PATCH 135/161] gccrs: Fix narrowing of Loan (size_t) into LoanId (uint32) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix narrowing: -../../gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc:145:46: warning: narrowing conversion of ‘loan’ from ‘Rust::Polonius::Loan’ {aka ‘long unsigned int’} to ‘uint32_t’ {aka ‘unsigned int’} [-Wnarrowing] gcc/rust/ChangeLog: * checks/errors/borrowck/rust-bir-place.h (LoanId::value): Make it size_t to match Loan's base type. Signed-off-by: Marc Poulhiès --- gcc/rust/checks/errors/borrowck/rust-bir-place.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h index 14f1dd660b0e..c4631c7b2f16 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h @@ -53,7 +53,7 @@ using Variance = TyTy::VarianceAnalysis::Variance; /** A unique identifier for a loan in the BIR. */ struct LoanId { - uint32_t value; + size_t value; // some overloads for comparision bool operator== (const LoanId &rhs) const { return value == rhs.value; } bool operator!= (const LoanId &rhs) const { return !(operator== (rhs)); } From 842899931ff77989f6f9f3ceb33aafbda1694e85 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 27 Jun 2025 17:13:29 +0100 Subject: [PATCH 136/161] gccrs: Fix bad bounds checking for PartialOrd This was a nasty issue to debug, the issue was very eager type bounds checking. So for example: pub trait PartialOrd: PartialEq The super trait of PartialEq is a generic substitution and we reuse our bounds code here for normal generic bounds and generics an invalid bounds check was occuring when PartialEq was getting substituted becase this is a trait doing proper bounds checking is not valid here because this is telling us about the bounds in this case. Fixes Rust-GCC#3836 gcc/rust/ChangeLog: * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): track is super trait * typecheck/rust-hir-type-bounds.h: refactor bounds scan * typecheck/rust-hir-type-check-base.h: track from super trait * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::is_bound_satisfied_for_type): refactor (TypeBoundsProbe::scan): likewise (TypeBoundPredicate::apply_generic_arguments): likewise * typecheck/rust-tyty-subst.cc: optional bounds checking on parm subst * typecheck/rust-tyty-subst.h: likewise * typecheck/rust-tyty.h: likewise gcc/testsuite/ChangeLog: * rust/compile/derive_partial_ord1.rs: this is now fully supported * rust/execute/torture/basic_partial_ord1.rs: add missing i32 impl * rust/execute/torture/basic_partial_ord2.rs: likewise * rust/compile/issue-3836.rs: New test. * rust/execute/torture/issue-3836.rs: New test. * rust/execute/torture/partial-ord-6.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/typecheck/rust-hir-trait-resolve.cc | 3 +- gcc/rust/typecheck/rust-hir-type-bounds.h | 4 + gcc/rust/typecheck/rust-hir-type-check-base.h | 2 +- .../typecheck/rust-hir-type-check-expr.cc | 2 +- gcc/rust/typecheck/rust-tyty-bounds.cc | 78 +-- gcc/rust/typecheck/rust-tyty-subst.cc | 6 +- gcc/rust/typecheck/rust-tyty-subst.h | 2 +- gcc/rust/typecheck/rust-tyty.h | 7 +- .../rust/compile/derive_partial_ord1.rs | 2 +- gcc/testsuite/rust/compile/issue-3836.rs | 67 +++ .../execute/torture/basic_partial_ord1.rs | 13 + .../execute/torture/basic_partial_ord2.rs | 13 + .../rust/execute/torture/issue-3836.rs | 454 +++++++++++++++ .../rust/execute/torture/partial-ord-6.rs | 518 ++++++++++++++++++ 14 files changed, 1128 insertions(+), 43 deletions(-) create mode 100644 gcc/testsuite/rust/compile/issue-3836.rs create mode 100644 gcc/testsuite/rust/execute/torture/issue-3836.rs create mode 100644 gcc/testsuite/rust/execute/torture/partial-ord-6.rs diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index fccc53ed6c2d..7f224076cd74 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -288,7 +288,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference) auto predicate = get_predicate_from_bound ( b->get_path (), - tl::nullopt /*this will setup a PLACEHOLDER for self*/); + tl::nullopt /*this will setup a PLACEHOLDER for self*/, + BoundPolarity::RegularBound, false, true); if (predicate.is_error ()) return &TraitReference::error_node (); diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h index 3cf77733e45a..5384700e97fb 100644 --- a/gcc/rust/typecheck/rust-hir-type-bounds.h +++ b/gcc/rust/typecheck/rust-hir-type-bounds.h @@ -37,6 +37,10 @@ class TypeBoundsProbe : public TypeCheckBase private: void scan (); + bool + process_impl_block (HirId id, HIR::ImplBlock *impl, + std::vector> + &possible_trait_paths); void assemble_marker_builtins (); void add_trait_bound (HIR::Trait *trait); void assemble_builtin_candidate (LangItem::Kind item); diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h index 580082a6adfb..a8084f2bf5b8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.h +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -46,7 +46,7 @@ class TypeCheckBase HIR::TypePath &path, tl::optional> associated_self, BoundPolarity polarity = BoundPolarity::RegularBound, - bool is_qualified_type = false); + bool is_qualified_type = false, bool is_super_trait = false); bool check_for_unconstrained ( const std::vector ¶ms_to_constrain, diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index ccde4dd77bff..c1404561f4d0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -1866,7 +1866,7 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr) args.get_type_args ().push_back (std::unique_ptr (implicit_tuple)); // apply the arguments - predicate.apply_generic_arguments (&args, false); + predicate.apply_generic_arguments (&args, false, false); // finally inherit the trait bound infered->inherit_bounds ({predicate}); diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index f5b18004c187..c34d3628895a 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -61,6 +61,39 @@ TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver, return false; } +bool +TypeBoundsProbe::process_impl_block ( + HirId id, HIR::ImplBlock *impl, + std::vector> + &possible_trait_paths) +{ + // we are filtering for trait-impl-blocks + if (!impl->has_trait_ref ()) + return true; + + // can be recursive trait resolution + HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ()); + if (t == nullptr) + return true; + // DefId trait_id = t->get_mappings ().get_defid (); + // if (context->trait_query_in_progress (trait_id)) + // return true; + + HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid (); + TyTy::BaseType *impl_type = nullptr; + if (!query_type (impl_ty_id, &impl_type)) + return true; + + if (!receiver->can_eq (impl_type, false)) + { + if (!impl_type->can_eq (receiver, false)) + return true; + } + + possible_trait_paths.push_back ({&impl->get_trait_ref (), impl}); + return true; +} + void TypeBoundsProbe::scan () { @@ -68,31 +101,7 @@ TypeBoundsProbe::scan () possible_trait_paths; mappings.iterate_impl_blocks ( [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool { - // we are filtering for trait-impl-blocks - if (!impl->has_trait_ref ()) - return true; - - // can be recursive trait resolution - HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ()); - if (t == nullptr) - return true; - DefId trait_id = t->get_mappings ().get_defid (); - if (context->trait_query_in_progress (trait_id)) - return true; - - HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid (); - TyTy::BaseType *impl_type = nullptr; - if (!query_type (impl_ty_id, &impl_type)) - return true; - - if (!receiver->can_eq (impl_type, false)) - { - if (!impl_type->can_eq (receiver, false)) - return true; - } - - possible_trait_paths.push_back ({&impl->get_trait_ref (), impl}); - return true; + return process_impl_block (id, impl, possible_trait_paths); }); for (auto &path : possible_trait_paths) @@ -212,7 +221,7 @@ TyTy::TypeBoundPredicate TypeCheckBase::get_predicate_from_bound ( HIR::TypePath &type_path, tl::optional> associated_self, - BoundPolarity polarity, bool is_qualified_type_path) + BoundPolarity polarity, bool is_qualified_type_path, bool is_super_trait) { TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error (); bool already_resolved @@ -335,7 +344,8 @@ TypeCheckBase::get_predicate_from_bound ( if (!args.is_empty () || predicate.requires_generic_args ()) { // this is applying generic arguments to a trait reference - predicate.apply_generic_arguments (&args, associated_self.has_value ()); + predicate.apply_generic_arguments (&args, associated_self.has_value (), + is_super_trait); } context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (), @@ -516,7 +526,8 @@ TypeBoundPredicate::is_object_safe (bool emit_error, location_t locus) const void TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args, - bool has_associated_self) + bool has_associated_self, + bool is_super_trait) { rust_assert (!substitutions.empty ()); if (has_associated_self) @@ -537,23 +548,26 @@ TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args, Resolver::TypeCheckContext::get ()->regions_from_generic_args ( *generic_args)); - apply_argument_mappings (args); + apply_argument_mappings (args, is_super_trait); } void TypeBoundPredicate::apply_argument_mappings ( - SubstitutionArgumentMappings &arguments) + SubstitutionArgumentMappings &arguments, bool is_super_trait) { used_arguments = arguments; error_flag |= used_arguments.is_error (); auto &subst_mappings = used_arguments; + + bool substs_need_bounds_check = !is_super_trait; for (auto &sub : get_substs ()) { SubstitutionArg arg = SubstitutionArg::error (); bool ok = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg); if (ok && arg.get_tyty () != nullptr) - sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ()); + sub.fill_param_ty (subst_mappings, subst_mappings.get_locus (), + substs_need_bounds_check); } // associated argument mappings @@ -574,7 +588,7 @@ TypeBoundPredicate::apply_argument_mappings ( auto adjusted = super_trait.adjust_mappings_for_this (used_arguments, true /*trait mode*/); - super_trait.apply_argument_mappings (adjusted); + super_trait.apply_argument_mappings (adjusted, is_super_trait); } } diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index 28d311a8aad2..2d5e87e5adda 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -115,7 +115,8 @@ SubstitutionParamMapping::need_substitution () const bool SubstitutionParamMapping::fill_param_ty ( - SubstitutionArgumentMappings &subst_mappings, location_t locus) + SubstitutionArgumentMappings &subst_mappings, location_t locus, + bool needs_bounds_check) { SubstitutionArg arg = SubstitutionArg::error (); bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg); @@ -139,8 +140,7 @@ SubstitutionParamMapping::fill_param_ty ( rust_debug_loc (locus, "fill_param_ty bounds_compatible: param %s type %s", param->get_name ().c_str (), type.get_name ().c_str ()); - - if (!param->is_implicit_self_trait ()) + if (needs_bounds_check && !param->is_implicit_self_trait ()) { if (!param->bounds_compatible (type, locus, true)) return false; diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h index 2f5de23aa00f..141db3d448b7 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.h +++ b/gcc/rust/typecheck/rust-tyty-subst.h @@ -51,7 +51,7 @@ class SubstitutionParamMapping std::string as_string () const; bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings, - location_t locus); + location_t locus, bool needs_bounds_check = true); SubstitutionParamMapping clone () const; diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index e0d0358e9e66..13e9184f29d7 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -539,14 +539,15 @@ class TypeBoundPredicate : public SubstitutionRef std::string get_name () const; - // check that this predicate is object-safe see: + // check that this is object-safe see: // https://doc.rust-lang.org/reference/items/traits.html#object-safety bool is_object_safe (bool emit_error, location_t locus) const; void apply_generic_arguments (HIR::GenericArgs *generic_args, - bool has_associated_self); + bool has_associated_self, bool is_super_trait); - void apply_argument_mappings (SubstitutionArgumentMappings &arguments); + void apply_argument_mappings (SubstitutionArgumentMappings &arguments, + bool is_super_trait); bool contains_item (const std::string &search) const; diff --git a/gcc/testsuite/rust/compile/derive_partial_ord1.rs b/gcc/testsuite/rust/compile/derive_partial_ord1.rs index 1f74b4dc9031..eeca62da0784 100644 --- a/gcc/testsuite/rust/compile/derive_partial_ord1.rs +++ b/gcc/testsuite/rust/compile/derive_partial_ord1.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-frust-compile-until=typecheck" } +// { dg-additional-options "-w" } #![feature(intrinsics)] diff --git a/gcc/testsuite/rust/compile/issue-3836.rs b/gcc/testsuite/rust/compile/issue-3836.rs new file mode 100644 index 000000000000..a2287957ad14 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3836.rs @@ -0,0 +1,67 @@ +// { dg-options "-w" } +mod core { + mod option { + pub enum Option { + #[lang = "None"] + None, + #[lang = "Some"] + Some(T), + } + } + + mod marker { + #[lang = "sized"] + pub trait Sized {} + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + pub enum Ordering { + Less = -1, + Equal = 0, + Greater = 1, + } + + #[lang = "eq"] + pub trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + #[lang = "partial_ord"] + pub trait PartialOrd: PartialEq { + fn partial_cmp(&self, other: &Rhs) -> Option; + } + } +} + +use core::cmp::{Ordering, PartialEq, PartialOrd}; +use core::marker::Sized; +use core::option::Option; + +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + false + } +} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + Option::Some(Ordering::Equal) + } +} + +struct Foo { + a: i32, +} + +impl PartialEq for Foo { + fn eq(&self, other: &'_ Self) -> bool { + ::core::cmp::PartialEq::eq(&self.a, &other.a) + } +} diff --git a/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs b/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs index efb825bc908c..0431629e9ea6 100644 --- a/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs +++ b/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs @@ -103,6 +103,19 @@ impl PartialOrd for i32 { Option::Some(Ordering::Equal) } } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } } impl Eq for i32 {} diff --git a/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs b/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs index b8c367255fa1..b6a96953d4a9 100644 --- a/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs +++ b/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs @@ -104,6 +104,19 @@ impl PartialOrd for i32 { Option::Some(Ordering::Equal) } } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } } impl Eq for i32 {} diff --git a/gcc/testsuite/rust/execute/torture/issue-3836.rs b/gcc/testsuite/rust/execute/torture/issue-3836.rs new file mode 100644 index 000000000000..61ad42492e74 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-3836.rs @@ -0,0 +1,454 @@ +// { dg-options "-w" } +// { dg-output "less\r*\n" } + +#![feature(intrinsics)] + +mod core { + mod option { + // #[rustc_diagnostic_item = "option_type"] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Option { + /// No value + #[lang = "None"] + #[stable(feature = "rust1", since = "1.0.0")] + None, + /// Some value `T` + #[lang = "Some"] + #[stable(feature = "rust1", since = "1.0.0")] + Some(#[stable(feature = "rust1", since = "1.0.0")] T), + } + } + + mod marker { + #[lang = "phantom_data"] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct PhantomData; + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] + #[lang = "structural_peq"] + pub trait StructuralPartialEq { + // Empty. + } + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] + #[lang = "structural_teq"] + pub trait StructuralEq { + // Empty. + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[lang = "sized"] + // #[rustc_on_unimplemented( + // message = "the size for values of type `{Self}` cannot be known at compilation time", + // label = "doesn't have a size known at compile-time" + // )] + // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable + // #[rustc_specialization_trait] + pub trait Sized { + // Empty. + } + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + // #[derive(Clone, Copy, PartialEq, Debug, Hash)] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Ordering { + /// An ordering where a compared value is less than another. + #[stable(feature = "rust1", since = "1.0.0")] + Less = -1, + /// An ordering where a compared value is equal to another. + #[stable(feature = "rust1", since = "1.0.0")] + Equal = 0, + /// An ordering where a compared value is greater than another. + #[stable(feature = "rust1", since = "1.0.0")] + Greater = 1, + } + + #[lang = "eq"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = "==")] + #[doc(alias = "!=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} == {Rhs}`" + // )] + pub trait PartialEq { + /// This method tests for `self` and `other` values to be equal, and is used + /// by `==`. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + #[doc(alias = "==")] + #[doc(alias = "!=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Eq: PartialEq { + // this method is used solely by #[deriving] to assert + // that every component of a type implements #[deriving] + // itself, the current deriving infrastructure means doing this + // assertion without using a method on this trait is nearly + // impossible. + // + // This should never be implemented by hand. + #[doc(hidden)] + #[stable(feature = "rust1", since = "1.0.0")] + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = ">")] + #[doc(alias = "<")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`" + // )] + pub trait PartialOrd: PartialEq { + /// This method returns an ordering between `self` and `other` values if one exists. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = 1.0.partial_cmp(&2.0); + /// assert_eq!(result, Some(Ordering::Less)); + /// + /// let result = 1.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Equal)); + /// + /// let result = 2.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Greater)); + /// ``` + /// + /// When comparison is impossible: + /// + /// ``` + /// let result = f64::NAN.partial_cmp(&1.0); + /// assert_eq!(result, None); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn partial_cmp(&self, other: &Rhs) -> Option; + + /// This method tests less than (for `self` and `other`) and is used by the `<` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 < 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 < 1.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 <= 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 <= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less | Ordering::Equal) => true, + _ => false, + } + } + + /// This method tests greater than (for `self` and `other`) and is used by the `>` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 > 2.0; + /// assert_eq!(result, false); + /// + /// let result = 2.0 > 2.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 2.0 >= 1.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 >= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater | Ordering::Equal) => true, + _ => false, + } + } + } + + #[doc(alias = "<")] + #[doc(alias = ">")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Ord: Eq + PartialOrd { + /// This method returns an [`Ordering`] between `self` and `other`. + /// + /// By convention, `self.cmp(&other)` returns the ordering matching the expression + /// `self other` if true. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(5.cmp(&10), Ordering::Less); + /// assert_eq!(10.cmp(&5), Ordering::Greater); + /// assert_eq!(5.cmp(&5), Ordering::Equal); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(2, 1.max(2)); + /// assert_eq!(2, 2.max(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn max(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1, 1.min(2)); + /// assert_eq!(2, 2.min(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn min(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Restrict a value to a certain interval. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// # Panics + /// + /// Panics if `min > max`. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp)] + /// + /// assert!((-3).clamp(-2, 1) == -2); + /// assert!(0.clamp(-2, 1) == 0); + /// assert!(2.clamp(-2, 1) == 1); + /// ``` + #[must_use] + #[unstable(feature = "clamp", issue = "44095")] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: Sized, + { + if self < min { + min + } else if self > max { + max + } else { + self + } + } + } + } + + pub mod intrinsics { + #[lang = "discriminant_kind"] + pub trait DiscriminantKind { + #[lang = "discriminant_type"] + type Discriminant; + } + + extern "rust-intrinsic" { + pub fn discriminant_value(v: &T) -> ::Discriminant; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::marker::Sized; +use core::option::Option; + +// for comparing discriminant_value +impl PartialEq for isize { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +// for comparing discriminant_value +impl PartialOrd for isize { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} +impl Eq for i32 {} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self > *other { + Ordering::Greater + } else if *self < *other { + Ordering::Less + } else { + Ordering::Equal + } + } +} + +// ------------ + +#[derive(Ord, PartialOrd, PartialEq, Eq)] +struct Bar { + a: i32, + b: i32, +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let x = Bar { a: 1, b: 2 }; + let y = Bar { a: 1, b: 3 }; + + match x.partial_cmp(&y) { + Option::Some(Ordering::Less) => print("less"), + Option::Some(Ordering::Greater) => print("greater"), + Option::Some(Ordering::Equal) => print("equal"), + _ => print("none"), + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-6.rs b/gcc/testsuite/rust/execute/torture/partial-ord-6.rs new file mode 100644 index 000000000000..5d64f8c2f84c --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/partial-ord-6.rs @@ -0,0 +1,518 @@ +// { dg-additional-options "-w" } +/* { dg-output "Foo A < B\r?\nFoo B < C\r?\nFoo C == C\r?\nBar x < y\r?\nBarFull s1 < s2\r?\n" } */ + +#![feature(intrinsics)] + +mod core { + mod option { + // #[rustc_diagnostic_item = "option_type"] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Option { + /// No value + #[lang = "None"] + #[stable(feature = "rust1", since = "1.0.0")] + None, + /// Some value `T` + #[lang = "Some"] + #[stable(feature = "rust1", since = "1.0.0")] + Some(#[stable(feature = "rust1", since = "1.0.0")] T), + } + } + + mod marker { + #[lang = "phantom_data"] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct PhantomData; + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] + #[lang = "structural_peq"] + pub trait StructuralPartialEq { + // Empty. + } + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] + #[lang = "structural_teq"] + pub trait StructuralEq { + // Empty. + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[lang = "sized"] + // #[rustc_on_unimplemented( + // message = "the size for values of type `{Self}` cannot be known at compilation time", + // label = "doesn't have a size known at compile-time" + // )] + // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable + // #[rustc_specialization_trait] + pub trait Sized { + // Empty. + } + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + // #[derive(Clone, Copy, PartialEq, Debug, Hash)] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Ordering { + /// An ordering where a compared value is less than another. + #[stable(feature = "rust1", since = "1.0.0")] + Less = -1, + /// An ordering where a compared value is equal to another. + #[stable(feature = "rust1", since = "1.0.0")] + Equal = 0, + /// An ordering where a compared value is greater than another. + #[stable(feature = "rust1", since = "1.0.0")] + Greater = 1, + } + + #[lang = "eq"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = "==")] + #[doc(alias = "!=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} == {Rhs}`" + // )] + pub trait PartialEq { + /// This method tests for `self` and `other` values to be equal, and is used + /// by `==`. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + #[doc(alias = "==")] + #[doc(alias = "!=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Eq: PartialEq { + // this method is used solely by #[deriving] to assert + // that every component of a type implements #[deriving] + // itself, the current deriving infrastructure means doing this + // assertion without using a method on this trait is nearly + // impossible. + // + // This should never be implemented by hand. + #[doc(hidden)] + #[stable(feature = "rust1", since = "1.0.0")] + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = ">")] + #[doc(alias = "<")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`" + // )] + pub trait PartialOrd: PartialEq { + /// This method returns an ordering between `self` and `other` values if one exists. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = 1.0.partial_cmp(&2.0); + /// assert_eq!(result, Some(Ordering::Less)); + /// + /// let result = 1.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Equal)); + /// + /// let result = 2.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Greater)); + /// ``` + /// + /// When comparison is impossible: + /// + /// ``` + /// let result = f64::NAN.partial_cmp(&1.0); + /// assert_eq!(result, None); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn partial_cmp(&self, other: &Rhs) -> Option; + + /// This method tests less than (for `self` and `other`) and is used by the `<` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 < 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 < 1.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 <= 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 <= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less | Ordering::Equal) => true, + _ => false, + } + } + + /// This method tests greater than (for `self` and `other`) and is used by the `>` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 > 2.0; + /// assert_eq!(result, false); + /// + /// let result = 2.0 > 2.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 2.0 >= 1.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 >= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater | Ordering::Equal) => true, + _ => false, + } + } + } + + #[doc(alias = "<")] + #[doc(alias = ">")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Ord: Eq + PartialOrd { + /// This method returns an [`Ordering`] between `self` and `other`. + /// + /// By convention, `self.cmp(&other)` returns the ordering matching the expression + /// `self other` if true. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(5.cmp(&10), Ordering::Less); + /// assert_eq!(10.cmp(&5), Ordering::Greater); + /// assert_eq!(5.cmp(&5), Ordering::Equal); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(2, 1.max(2)); + /// assert_eq!(2, 2.max(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn max(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1, 1.min(2)); + /// assert_eq!(2, 2.min(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn min(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Restrict a value to a certain interval. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// # Panics + /// + /// Panics if `min > max`. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp)] + /// + /// assert!((-3).clamp(-2, 1) == -2); + /// assert!(0.clamp(-2, 1) == 0); + /// assert!(2.clamp(-2, 1) == 1); + /// ``` + #[must_use] + #[unstable(feature = "clamp", issue = "44095")] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: Sized, + { + if self < min { + min + } else if self > max { + max + } else { + self + } + } + } + } + + pub mod intrinsics { + #[lang = "discriminant_kind"] + pub trait DiscriminantKind { + #[lang = "discriminant_type"] + type Discriminant; + } + + extern "rust-intrinsic" { + pub fn discriminant_value(v: &T) -> ::Discriminant; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::marker::Sized; +use core::option::Option; + +// for comparing discriminant_value +impl PartialEq for isize { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +// for comparing discriminant_value +impl PartialOrd for isize { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self > *other { + Ordering::Greater + } else if *self < *other { + Ordering::Less + } else { + Ordering::Equal + } + } +} + +impl Eq for i32 {} + +#[derive(PartialEq, PartialOrd)] +enum Foo { + A, + B(i32, i32, i32), + C { inner: i32, outer: i32 }, +} + +#[derive(Ord, PartialOrd, PartialEq, Eq)] +struct Bar { + a: i32, +} + +#[derive(Ord, PartialOrd, PartialEq, Eq)] +struct BarFull { + a: i32, + b: i32, + c: i32, + d: i32, +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + // Enum comparison + let a = Foo::A; + let b = Foo::B(15, 14, 13); + let c = Foo::C { + inner: 10, + outer: 20, + }; + + match a.partial_cmp(&b) { + Option::Some(Ordering::Less) => print("Foo A < B"), + Option::Some(Ordering::Greater) => print("Foo A > B"), + Option::Some(Ordering::Equal) => print("Foo A == B"), + _ => print("Foo A ? B"), + } + + match b.partial_cmp(&c) { + Option::Some(Ordering::Less) => print("Foo B < C"), + Option::Some(Ordering::Greater) => print("Foo B > C"), + Option::Some(Ordering::Equal) => print("Foo B == C"), + _ => print("Foo B ? C"), + } + + match c.partial_cmp(&c) { + Option::Some(Ordering::Less) => print("Foo C < C ???"), + Option::Some(Ordering::Greater) => print("Foo C > C ???"), + Option::Some(Ordering::Equal) => print("Foo C == C"), + _ => print("Foo C ? C"), + } + + // Struct comparison: Bar + let x = Bar { a: 10 }; + let y = Bar { a: 20 }; + + if x < y { + print("Bar x < y"); + } else if x > y { + print("Bar x > y"); + } else { + print("Bar x == y"); + } + + // Struct comparison: BarFull + let s1 = BarFull { + a: 1, + b: 2, + c: 3, + d: 4, + }; + let s2 = BarFull { + a: 1, + b: 2, + c: 3, + d: 5, + }; + + match s1.cmp(&s2) { + Ordering::Less => print("BarFull s1 < s2"), + Ordering::Greater => print("BarFull s1 > s2"), + Ordering::Equal => print("BarFull s1 == s2"), + } + + 0 +} From 387ad9eabca4e4e195597c0142b253ba74db6e40 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 9 Jul 2025 11:46:10 +0200 Subject: [PATCH 137/161] nr2.0: Check before visiting a for-loop's label gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Check for a label before visiting it. --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index d33ec3ca39d2..1b560852418e 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -142,7 +142,10 @@ Late::visit (AST::ForLoopExpr &expr) ctx.bindings.exit (); visit (expr.get_iterator_expr ()); - visit (expr.get_loop_label ()); + + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + visit (expr.get_loop_block ()); } From b70fca30c7f1e3a878e9e88792cc0c672711cd55 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 10 Jul 2025 19:24:37 +0100 Subject: [PATCH 138/161] gccrs: Fix cast rules logic to try simple casts then fall back to coercions This case: let i = 1; let j = i as i64; 'i' is meant to default to i32 but the inference was making both of these i64 because the code was prefering coercion logic which can end up with a default unify which causes the ?integer to unify with i64 making them both i64. But all we need to do is allow the simple cast rules to run first then fallback to coercions but special consideration has to be made to ensure that if there are dyn objects needed then this needs a unsize coercion, but also we need to ensure the underlying types are a valid simple cast too otherwise these also need to fallback to the coercion code. Fixes Rust-GCC#2680 gcc/rust/ChangeLog: * typecheck/rust-casts.cc (TypeCastRules::resolve): optional emit_error flag (TypeCastRules::check): try the simple cast rules then fallback to coercions (TypeCastRules::check_ptr_ptr_cast): ensure the underlying's (TypeCastRules::emit_cast_error): make this a static helper * typecheck/rust-casts.h: new emit_error prototype gcc/testsuite/ChangeLog: * rust/compile/issue-2680.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/typecheck/rust-casts.cc | 45 ++++++++++++++++++------ gcc/rust/typecheck/rust-casts.h | 10 +++--- gcc/testsuite/rust/compile/issue-2680.rs | 6 ++++ 3 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/rust/compile/issue-2680.rs diff --git a/gcc/rust/typecheck/rust-casts.cc b/gcc/rust/typecheck/rust-casts.cc index d0a9f5dca015..f06d9ed24e8e 100644 --- a/gcc/rust/typecheck/rust-casts.cc +++ b/gcc/rust/typecheck/rust-casts.cc @@ -17,6 +17,7 @@ // . #include "rust-casts.h" +#include "rust-tyty-util.h" namespace Rust { namespace Resolver { @@ -28,15 +29,20 @@ TypeCastRules::TypeCastRules (location_t locus, TyTy::TyWithLocation from, TypeCoercionRules::CoercionResult TypeCastRules::resolve (location_t locus, TyTy::TyWithLocation from, - TyTy::TyWithLocation to) + TyTy::TyWithLocation to, bool emit_error) { TypeCastRules cast_rules (locus, from, to); - return cast_rules.check (); + return cast_rules.check (emit_error); } TypeCoercionRules::CoercionResult -TypeCastRules::check () +TypeCastRules::check (bool emit_error) { + // try the simple cast rules + auto simple_cast = cast_rules (); + if (!simple_cast.is_error ()) + return simple_cast; + // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/cast.rs#L565-L582 auto possible_coercion = TypeCoercionRules::TryCoerce (from.get_ty (), to.get_ty (), locus, @@ -51,13 +57,9 @@ TypeCastRules::check () true /*is_cast_site*/); } - // try the simple cast rules - auto simple_cast = cast_rules (); - if (!simple_cast.is_error ()) - return simple_cast; + if (emit_error) + TypeCastRules::emit_cast_error (locus, from, to); - // failed to cast - emit_cast_error (); return TypeCoercionRules::CoercionResult::get_error (); } @@ -329,7 +331,27 @@ TypeCastRules::check_ptr_ptr_cast () } else if (from_is_ref && to_is_ref) { - // mutability must be coercedable + const auto &from_ref = *from.get_ty ()->as (); + const auto &to_ref = *to.get_ty ()->as (); + + if (from_ref.is_dyn_object () != to_ref.is_dyn_object ()) + { + // this needs to be handled by coercion logic + return TypeCoercionRules::CoercionResult::get_error (); + } + + // are the underlying types safely simple castable? + const auto to_underly = to_ref.get_base (); + const auto from_underly = from_ref.get_base (); + auto res = resolve (locus, TyTy::TyWithLocation (from_underly), + TyTy::TyWithLocation (to_underly), false); + if (res.is_error ()) + { + // this needs to be handled by coercion logic + return TypeCoercionRules::CoercionResult::get_error (); + } + + // mutability must be coerceable TyTy::ReferenceType &f = static_cast (*from.get_ty ()); TyTy::ReferenceType &t @@ -346,7 +368,8 @@ TypeCastRules::check_ptr_ptr_cast () } void -TypeCastRules::emit_cast_error () const +TypeCastRules::emit_cast_error (location_t locus, TyTy::TyWithLocation from, + TyTy::TyWithLocation to) { rich_location r (line_table, locus); r.add_range (from.get_locus ()); diff --git a/gcc/rust/typecheck/rust-casts.h b/gcc/rust/typecheck/rust-casts.h index 0d6ed689e420..10bb006f0376 100644 --- a/gcc/rust/typecheck/rust-casts.h +++ b/gcc/rust/typecheck/rust-casts.h @@ -30,15 +30,17 @@ class TypeCastRules public: static TypeCoercionRules::CoercionResult resolve (location_t locus, TyTy::TyWithLocation from, - TyTy::TyWithLocation to); + TyTy::TyWithLocation to, + bool emit_error = true); + + static void emit_cast_error (location_t locus, TyTy::TyWithLocation from, + TyTy::TyWithLocation to); protected: - TypeCoercionRules::CoercionResult check (); + TypeCoercionRules::CoercionResult check (bool emit_error); TypeCoercionRules::CoercionResult cast_rules (); TypeCoercionRules::CoercionResult check_ptr_ptr_cast (); - void emit_cast_error () const; - protected: TypeCastRules (location_t locus, TyTy::TyWithLocation from, TyTy::TyWithLocation to); diff --git a/gcc/testsuite/rust/compile/issue-2680.rs b/gcc/testsuite/rust/compile/issue-2680.rs new file mode 100644 index 000000000000..d5ae2ff4450b --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2680.rs @@ -0,0 +1,6 @@ +// { dg-additional-options "-fdump-tree-gimple" } +pub fn test_cast() { + let i = 1; + // { dg-final { scan-tree-dump-times {const i32 i;} 1 gimple } } + let _j = i as i64; +} From 89e403c784255a29c6655214d3c26e81ecf4c1ee Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 10 Jul 2025 22:58:21 +0100 Subject: [PATCH 139/161] gccrs: Fix ICE when handling bad constructor We just had a typo returning ok true when it should have been false. Fixes Rust-GCC#3876 gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::visit): fix typo gcc/testsuite/ChangeLog: * rust/compile/issue-3876.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/typecheck/rust-hir-type-check-struct.cc | 2 +- gcc/testsuite/rust/compile/issue-3876.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/rust/compile/issue-3876.rs diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index e3a08e6f044d..4ef83482a536 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -362,7 +362,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) if (!ok) { rust_error_at (field.get_locus (), "unknown field"); - return true; + return false; } auto it = adtFieldIndexToField.find (field_index); diff --git a/gcc/testsuite/rust/compile/issue-3876.rs b/gcc/testsuite/rust/compile/issue-3876.rs new file mode 100644 index 000000000000..17b1590590e0 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3876.rs @@ -0,0 +1,8 @@ +enum test { + A(i32), +} + +fn fun(x: i32) { + test::A { x } + // { dg-error "unknown field" "" { target *-*-* } .-1 } +} From 150c8ac8a41e574635ff4bb5726444c5983274c9 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 11 Jul 2025 10:16:36 +0100 Subject: [PATCH 140/161] gccrs: add test case to show issue is fixed Fixes Rust-GCC#3599 gcc/testsuite/ChangeLog: * rust/compile/issue-3599.rs: New test. Signed-off-by: Philip Herron --- gcc/testsuite/rust/compile/issue-3599.rs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 gcc/testsuite/rust/compile/issue-3599.rs diff --git a/gcc/testsuite/rust/compile/issue-3599.rs b/gcc/testsuite/rust/compile/issue-3599.rs new file mode 100644 index 000000000000..1d29fac84e93 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3599.rs @@ -0,0 +1,8 @@ +#[lang = "sized"] +trait Sized {} + +trait Bar {} + +struct S; // { dg-warning "struct is never constructed" } + +pub fn test(foo: impl Bar) {} From 82203cc75a88eb99779bcc5d929e9791aa4462bb Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 11 Jul 2025 10:35:38 +0100 Subject: [PATCH 141/161] gccrs: Add test case to show we emit better errors now Fixes Rust-GCC#3144 gcc/testsuite/ChangeLog: * rust/compile/issue-3144.rs: New test. Signed-off-by: Philip Herron --- gcc/testsuite/rust/compile/issue-3144.rs | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 gcc/testsuite/rust/compile/issue-3144.rs diff --git a/gcc/testsuite/rust/compile/issue-3144.rs b/gcc/testsuite/rust/compile/issue-3144.rs new file mode 100644 index 000000000000..4e61078a0dcc --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3144.rs @@ -0,0 +1,29 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[lang = "clone"] +pub trait Clone { + fn clone(&self) -> Self; +} + +impl Clone for i32 { + fn clone(&self) -> i32 { + *self + } +} + +struct S {} + +#[derive(Clone, Copy)] +// { dg-error {bounds not satisfied for S .Clone. is not satisfied .E0277.} "" { target *-*-* } .-1 } +struct S2 { + a: i32, + s: S, +} + +fn main() -> i32 { + 0 +} From eedc4ef41a6666ea4e001a06917285381beac768 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 11 Jul 2025 12:20:04 +0100 Subject: [PATCH 142/161] gccrs: Add test case to show issue is fixed Fixes Rust-GCC#1048 gcc/testsuite/ChangeLog: * rust/compile/issue-1048.rs: New test. Signed-off-by: Philip Herron --- gcc/testsuite/rust/compile/issue-1048.rs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 gcc/testsuite/rust/compile/issue-1048.rs diff --git a/gcc/testsuite/rust/compile/issue-1048.rs b/gcc/testsuite/rust/compile/issue-1048.rs new file mode 100644 index 000000000000..8d4053a37a1e --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-1048.rs @@ -0,0 +1,8 @@ +macro_rules! maybe_return { ($e:expr) => ($e); } + +fn frob(x: i32) -> i32{ + maybe_return! {x} + // { dg-error "mismatched types. expected .... but got .i32. .E0308." "" { target *-*-* } .-1 } + // should return -1 + -1 +} From 17dfbdecc95ec12d08bb6660f142c85044f40242 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 4 Jul 2025 16:19:44 +0200 Subject: [PATCH 143/161] attributes: Add #[test] and #[simd_test] gcc/rust/ChangeLog: * util/rust-attribute-values.h: Add declarations for them. * util/rust-attributes.cc: Add definitions. --- gcc/rust/util/rust-attribute-values.h | 4 ++++ gcc/rust/util/rust-attributes.cc | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/gcc/rust/util/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h index 47e6a175396c..09ef56647953 100644 --- a/gcc/rust/util/rust-attribute-values.h +++ b/gcc/rust/util/rust-attribute-values.h @@ -85,6 +85,10 @@ class Attributes static constexpr auto &NON_EXHAUSTIVE = "non_exhaustive"; static constexpr auto &RUSTFMT = "rustfmt"; + + static constexpr auto &TEST = "test"; + + static constexpr auto &SIMD_TEST = "simd_test"; }; } // namespace Values } // namespace Rust diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index 9bf4f7773c68..0c957fb20144 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -95,7 +95,10 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::FUNDAMENTAL, TYPE_CHECK}, {Attrs::NON_EXHAUSTIVE, TYPE_CHECK}, - {Attrs::RUSTFMT, EXTERNAL}}; + {Attrs::RUSTFMT, EXTERNAL}, + + {Attrs::TEST, CODE_GENERATION}, + {Attrs::SIMD_TEST, CODE_GENERATION}}; BuiltinAttributeMappings * BuiltinAttributeMappings::get () From 7fb6b42b4f6185c3b3dfc3e90bfb848f97654cc3 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 11 Jul 2025 13:51:10 +0100 Subject: [PATCH 144/161] gccrs: Add test case showing all derives working on enum We have more complex test cases already but this will close out this issue. Fixes Rust-GCC#2005 gcc/testsuite/ChangeLog: * rust/execute/torture/issue-2005.rs: New test. Signed-off-by: Philip Herron --- .../rust/execute/torture/issue-2005.rs | 465 ++++++++++++++++++ 1 file changed, 465 insertions(+) create mode 100644 gcc/testsuite/rust/execute/torture/issue-2005.rs diff --git a/gcc/testsuite/rust/execute/torture/issue-2005.rs b/gcc/testsuite/rust/execute/torture/issue-2005.rs new file mode 100644 index 000000000000..87edb95988dc --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-2005.rs @@ -0,0 +1,465 @@ +// { dg-additional-options "-w" } +/* { dg-output "WORKS\r?\n" } */ +#![feature(intrinsics)] + +mod core { + mod option { + // #[rustc_diagnostic_item = "option_type"] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Option { + /// No value + #[lang = "None"] + #[stable(feature = "rust1", since = "1.0.0")] + None, + /// Some value `T` + #[lang = "Some"] + #[stable(feature = "rust1", since = "1.0.0")] + Some(#[stable(feature = "rust1", since = "1.0.0")] T), + } + } + + mod marker { + #[lang = "phantom_data"] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct PhantomData; + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] + #[lang = "structural_peq"] + pub trait StructuralPartialEq { + // Empty. + } + + #[unstable(feature = "structural_match", issue = "31434")] + // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] + #[lang = "structural_teq"] + pub trait StructuralEq { + // Empty. + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[lang = "sized"] + // #[rustc_on_unimplemented( + // message = "the size for values of type `{Self}` cannot be known at compilation time", + // label = "doesn't have a size known at compile-time" + // )] + // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable + // #[rustc_specialization_trait] + pub trait Sized { + // Empty. + } + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + // #[derive(Clone, Copy, PartialEq, Debug, Hash)] + #[stable(feature = "rust1", since = "1.0.0")] + pub enum Ordering { + /// An ordering where a compared value is less than another. + #[stable(feature = "rust1", since = "1.0.0")] + Less = -1, + /// An ordering where a compared value is equal to another. + #[stable(feature = "rust1", since = "1.0.0")] + Equal = 0, + /// An ordering where a compared value is greater than another. + #[stable(feature = "rust1", since = "1.0.0")] + Greater = 1, + } + + #[lang = "eq"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = "==")] + #[doc(alias = "!=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} == {Rhs}`" + // )] + pub trait PartialEq { + /// This method tests for `self` and `other` values to be equal, and is used + /// by `==`. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + #[doc(alias = "==")] + #[doc(alias = "!=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Eq: PartialEq { + // this method is used solely by #[deriving] to assert + // that every component of a type implements #[deriving] + // itself, the current deriving infrastructure means doing this + // assertion without using a method on this trait is nearly + // impossible. + // + // This should never be implemented by hand. + #[doc(hidden)] + #[stable(feature = "rust1", since = "1.0.0")] + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = ">")] + #[doc(alias = "<")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + // #[rustc_on_unimplemented( + // message = "can't compare `{Self}` with `{Rhs}`", + // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`" + // )] + pub trait PartialOrd: PartialEq { + /// This method returns an ordering between `self` and `other` values if one exists. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = 1.0.partial_cmp(&2.0); + /// assert_eq!(result, Some(Ordering::Less)); + /// + /// let result = 1.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Equal)); + /// + /// let result = 2.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Greater)); + /// ``` + /// + /// When comparison is impossible: + /// + /// ``` + /// let result = f64::NAN.partial_cmp(&1.0); + /// assert_eq!(result, None); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn partial_cmp(&self, other: &Rhs) -> Option; + + /// This method tests less than (for `self` and `other`) and is used by the `<` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 < 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 < 1.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 <= 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 <= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less | Ordering::Equal) => true, + _ => false, + } + } + + /// This method tests greater than (for `self` and `other`) and is used by the `>` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 > 2.0; + /// assert_eq!(result, false); + /// + /// let result = 2.0 > 2.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 2.0 >= 1.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 >= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater | Ordering::Equal) => true, + _ => false, + } + } + } + + #[doc(alias = "<")] + #[doc(alias = ">")] + #[doc(alias = "<=")] + #[doc(alias = ">=")] + #[stable(feature = "rust1", since = "1.0.0")] + pub trait Ord: Eq + PartialOrd { + /// This method returns an [`Ordering`] between `self` and `other`. + /// + /// By convention, `self.cmp(&other)` returns the ordering matching the expression + /// `self other` if true. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(5.cmp(&10), Ordering::Less); + /// assert_eq!(10.cmp(&5), Ordering::Greater); + /// assert_eq!(5.cmp(&5), Ordering::Equal); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(2, 1.max(2)); + /// assert_eq!(2, 2.max(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn max(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(1, 1.min(2)); + /// assert_eq!(2, 2.min(2)); + /// ``` + #[stable(feature = "ord_max_min", since = "1.21.0")] + #[must_use] + fn min(self, other: Self) -> Self + where + Self: Sized, + { + self + } + + /// Restrict a value to a certain interval. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// # Panics + /// + /// Panics if `min > max`. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp)] + /// + /// assert!((-3).clamp(-2, 1) == -2); + /// assert!(0.clamp(-2, 1) == 0); + /// assert!(2.clamp(-2, 1) == 1); + /// ``` + #[must_use] + #[unstable(feature = "clamp", issue = "44095")] + fn clamp(self, min: Self, max: Self) -> Self + where + Self: Sized, + { + if self < min { + min + } else if self > max { + max + } else { + self + } + } + } + } + + pub mod intrinsics { + #[lang = "discriminant_kind"] + pub trait DiscriminantKind { + #[lang = "discriminant_type"] + type Discriminant; + } + + extern "rust-intrinsic" { + pub fn discriminant_value(v: &T) -> ::Discriminant; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::marker::Sized; +use core::option::Option; + +// -------------- + +impl PartialEq for isize { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +impl PartialOrd for isize { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl Eq for isize {} + +impl Ord for isize { + fn cmp(&self, other: &Self) -> Ordering { + if *self > *other { + Ordering::Greater + } else if *self < *other { + Ordering::Less + } else { + Ordering::Equal + } + } +} + +// ---------------------------------- + +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option { + if *self > *other { + Option::Some(Ordering::Greater) + } else if *self < *other { + Option::Some(Ordering::Less) + } else { + Option::Some(Ordering::Equal) + } + } + + fn lt(&self, other: &Self) -> bool { + *self < *other + } + fn le(&self, other: &Self) -> bool { + *self <= *other + } + fn ge(&self, other: &Self) -> bool { + *self >= *other + } + fn gt(&self, other: &Self) -> bool { + *self > *other + } +} + +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self > *other { + Ordering::Greater + } else if *self < *other { + Ordering::Less + } else { + Ordering::Equal + } + } +} + +impl Eq for i32 {} + +#[derive(Ord, PartialOrd, PartialEq, Eq)] +enum Foo { + A, + B(i32), +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let a = Foo::A; + let b = Foo::B(15); + + if (a != b) { + print("WORKS"); + } + + 0 +} From e396db36d735efb4907fe5ef652c0a9bde912aff Mon Sep 17 00:00:00 2001 From: Yap Zhi Heng Date: Fri, 11 Jul 2025 22:29:31 +0800 Subject: [PATCH 145/161] gccrs: Add size checking to SlicePattern gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-pattern.cc(TypeCheckPattern::visit(SlicePattern)): Implement size checking for SlicePattern when type checking against array parent Signed-off-by: Yap Zhi Heng --- .../typecheck/rust-hir-type-check-pattern.cc | 20 ++++++++++++++++--- .../compile/slicepattern-size-mismatch.rs | 8 ++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/rust/compile/slicepattern-size-mismatch.rs diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index 5608030db72c..bb0e27bb2a6c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -652,11 +652,25 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern) { case TyTy::ARRAY: { - // FIXME: implement compile-time size checks when ArrayType's capacity - // is updated to be evaluated in compile-time - // https://github.com/Rust-GCC/gccrs/issues/3882 auto &array_ty_ty = static_cast (*parent); parent_element_ty = array_ty_ty.get_element_type (); + tree cap = array_ty_ty.get_capacity (); + if (error_operand_p (cap)) + { + rust_error_at (parent->get_locus (), + "capacity of array %qs is not known at compile time", + array_ty_ty.get_name ().c_str ()); + break; + } + auto cap_wi = wi::to_wide (cap).to_uhwi (); + if (cap_wi != pattern.get_items ().size ()) + { + rust_error_at (pattern.get_locus (), ErrorCode::E0527, + "pattern requires %lu elements but array has %lu", + (unsigned long) pattern.get_items ().size (), + (unsigned long) cap_wi); + break; + } break; } case TyTy::SLICE: diff --git a/gcc/testsuite/rust/compile/slicepattern-size-mismatch.rs b/gcc/testsuite/rust/compile/slicepattern-size-mismatch.rs new file mode 100644 index 000000000000..b54b53206044 --- /dev/null +++ b/gcc/testsuite/rust/compile/slicepattern-size-mismatch.rs @@ -0,0 +1,8 @@ +fn main() { + let arr = [0, 1]; + + match arr { + [0, 1, 2] => {} // { dg-error "pattern requires 3 elements but array has 2 .E0527." } + _ => {} + } +} \ No newline at end of file From 94160e043c893bdff6dfa40eb2aa08aca80d3bdb Mon Sep 17 00:00:00 2001 From: Yap Zhi Heng Date: Thu, 17 Jul 2025 22:13:32 +0800 Subject: [PATCH 146/161] gccrs: Implement compilation for SlicePattern matching against ArrayType scrutinee Example GIMPLE output from compiling testsuite/rust/compile/match-pattern-array.rs: ... a[0] = 0; a[1] = 1; RUSTTMP.3 = a; _1 = RUSTTMP.3[0]; _2 = _1 == 0; _3 = RUSTTMP.3[1]; _4 = _3 == 1; _5 = _2 & _4; if (_5 != 0) goto ; else goto ; : { { } } goto ; } : ... gcc/rust/ChangeLog: * rust-backend.h: New size_constant_expression function. * rust-gcc.cc: Implementation of size_constant_expression function to generate tree node for array access. * backend/rust-compile-pattern.h: Remove empty visits for SlicePattern. * backend/rust-compile-pattern.cc: Implement SlicePattern check expression & binding compilation against ArrayType scrutinee. Signed-off-by: Yap Zhi Heng --- gcc/rust/backend/rust-compile-pattern.cc | 85 +++++++++++++++++++ gcc/rust/backend/rust-compile-pattern.h | 4 +- gcc/rust/rust-backend.h | 3 + gcc/rust/rust-gcc.cc | 6 ++ .../rust/compile/match-slicepattern-array.rs | 8 ++ .../torture/match-slicepattern-array-1.rs | 23 +++++ 6 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/rust/compile/match-slicepattern-array.rs create mode 100644 gcc/testsuite/rust/execute/torture/match-slicepattern-array-1.rs diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index 3351becd1d99..6d889baa1992 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -514,6 +514,53 @@ CompilePatternCheckExpr::visit (HIR::IdentifierPattern &pattern) } } +void +CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern) +{ + check_expr = boolean_true_node; + + // lookup the type + TyTy::BaseType *lookup = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (), + &lookup); + rust_assert (ok); + + // pattern must either be ArrayType or SliceType, should be already confirmed + // by type checking + rust_assert (lookup->get_kind () == TyTy::TypeKind::ARRAY + || lookup->get_kind () == TyTy::TypeKind::SLICE); + + size_t array_element_index = 0; + switch (lookup->get_kind ()) + { + case TyTy::TypeKind::ARRAY: + for (auto &pattern_member : pattern.get_items ()) + { + tree array_index_tree + = Backend::size_constant_expression (array_element_index++); + tree element_expr + = Backend::array_index_expression (match_scrutinee_expr, + array_index_tree, + pattern.get_locus ()); + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern_member, element_expr, + ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern.get_locus ()); + } + break; + case TyTy::TypeKind::SLICE: + rust_sorry_at ( + pattern.get_locus (), + "SlicePattern matching against slices are not yet supported"); + break; + default: + rust_unreachable (); + } +} + // setup the bindings void @@ -837,6 +884,44 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) } } +void +CompilePatternBindings::visit (HIR::SlicePattern &pattern) +{ + // lookup the type + TyTy::BaseType *lookup = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (), + &lookup); + rust_assert (ok); + + rust_assert (lookup->get_kind () == TyTy::TypeKind::ARRAY + || lookup->get_kind () == TyTy::TypeKind::SLICE); + + size_t array_element_index = 0; + switch (lookup->get_kind ()) + { + case TyTy::TypeKind::ARRAY: + for (auto &pattern_member : pattern.get_items ()) + { + tree array_index_tree + = Backend::size_constant_expression (array_element_index++); + tree element_expr + = Backend::array_index_expression (match_scrutinee_expr, + array_index_tree, + pattern.get_locus ()); + CompilePatternBindings::Compile (*pattern_member, element_expr, ctx); + } + break; + case TyTy::TypeKind::SLICE: + rust_sorry_at ( + pattern.get_locus (), + "SlicePattern matching against slices are not yet supported"); + break; + default: + rust_unreachable (); + } +} + // void diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h index 4dd7d559e6eb..233799e21da3 100644 --- a/gcc/rust/backend/rust-compile-pattern.h +++ b/gcc/rust/backend/rust-compile-pattern.h @@ -46,6 +46,7 @@ class CompilePatternCheckExpr : public HIRCompileBase, void visit (HIR::TupleStructPattern &) override; void visit (HIR::TuplePattern &) override; void visit (HIR::IdentifierPattern &) override; + void visit (HIR::SlicePattern &) override; // Always succeeds void visit (HIR::WildcardPattern &) override @@ -55,7 +56,6 @@ class CompilePatternCheckExpr : public HIRCompileBase, // Empty visit for unused Pattern HIR nodes. void visit (HIR::QualifiedPathInExpression &) override {} - void visit (HIR::SlicePattern &) override {} CompilePatternCheckExpr (Context *ctx, tree match_scrutinee_expr) : HIRCompileBase (ctx), match_scrutinee_expr (match_scrutinee_expr), @@ -95,6 +95,7 @@ class CompilePatternBindings : public HIRCompileBase, void visit (HIR::ReferencePattern &pattern) override; void visit (HIR::IdentifierPattern &) override; void visit (HIR::TuplePattern &pattern) override; + void visit (HIR::SlicePattern &) override; // Empty visit for unused Pattern HIR nodes. void visit (HIR::AltPattern &) override {} @@ -102,7 +103,6 @@ class CompilePatternBindings : public HIRCompileBase, void visit (HIR::PathInExpression &) override {} void visit (HIR::QualifiedPathInExpression &) override {} void visit (HIR::RangePattern &) override {} - void visit (HIR::SlicePattern &) override {} void visit (HIR::WildcardPattern &) override {} protected: diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 2d813d91efd6..8a77d96de835 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -176,6 +176,9 @@ tree char_constant_expression (char c); // Get a char literal tree wchar_constant_expression (wchar_t c); +// Get a size literal +tree size_constant_expression (size_t val); + // Return an expression for the boolean value VAL. tree boolean_constant_expression (bool val); diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 42cdc6ca7f1c..c5fda5c7a9ca 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -818,6 +818,12 @@ char_constant_expression (char c) return build_int_cst (char_type_node, c); } +tree +size_constant_expression (size_t val) +{ + return size_int (val); +} + // Make a constant boolean expression. tree diff --git a/gcc/testsuite/rust/compile/match-slicepattern-array.rs b/gcc/testsuite/rust/compile/match-slicepattern-array.rs new file mode 100644 index 000000000000..e48ca757f5e0 --- /dev/null +++ b/gcc/testsuite/rust/compile/match-slicepattern-array.rs @@ -0,0 +1,8 @@ +fn main() { + let a = [0, 1]; + + match a { + [0, 1] => {}, + _ => {} + } +} diff --git a/gcc/testsuite/rust/execute/torture/match-slicepattern-array-1.rs b/gcc/testsuite/rust/execute/torture/match-slicepattern-array-1.rs new file mode 100644 index 000000000000..95c55d8f9d5e --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/match-slicepattern-array-1.rs @@ -0,0 +1,23 @@ +// { dg-output "correct\r*" } +extern "C" { + fn puts(s: *const i8); +} + +fn main() -> i32 { + let a = [0, 1]; + let mut ret = 1; + + match a { + [0, 0] => { + /* should not take this path */ + unsafe { puts("wrong\0" as *const str as *const i8) } + }, + [0, b] => { + ret -= b; + unsafe { puts("correct\0" as *const str as *const i8) } + }, + _ => {} + } + + ret +} From cddffae5697611ef038a07f196db7f05175abf3b Mon Sep 17 00:00:00 2001 From: lishin Date: Wed, 16 Jul 2025 01:39:48 +0100 Subject: [PATCH 147/161] gccrs: Reject loop in const/static context gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (CompileExpr::visit): Add a catch for const/static. gcc/testsuite/ChangeLog: * rust/compile/loop_constant_context.rs: New test. * rust/compile/issue-3618.rs: Signed-off-by: lishin --- gcc/rust/backend/rust-compile-expr.cc | 10 +++++++++- gcc/testsuite/rust/compile/issue-3618.rs | 3 ++- gcc/testsuite/rust/compile/loop_constant_context.rs | 5 +++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/rust/compile/loop_constant_context.rs diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index a93e848304e6..25da59d982d2 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -682,6 +682,15 @@ void CompileExpr::visit (HIR::LoopExpr &expr) { TyTy::BaseType *block_tyty = nullptr; + fncontext fnctx = ctx->peek_fn (); + if (ctx->const_context_p () && !DECL_DECLARED_CONSTEXPR_P (fnctx.fndecl)) + { + rich_location r (line_table, expr.get_locus ()); + rust_error_at (r, ErrorCode::E0658, + "% is not allowed in const context"); + return; + } + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &block_tyty)) { @@ -689,7 +698,6 @@ CompileExpr::visit (HIR::LoopExpr &expr) return; } - fncontext fnctx = ctx->peek_fn (); tree enclosing_scope = ctx->peek_enclosing_scope (); tree block_type = TyTyResolveCompile::compile (ctx, block_tyty); diff --git a/gcc/testsuite/rust/compile/issue-3618.rs b/gcc/testsuite/rust/compile/issue-3618.rs index 97286135e3a5..3bf2c7efd94d 100644 --- a/gcc/testsuite/rust/compile/issue-3618.rs +++ b/gcc/testsuite/rust/compile/issue-3618.rs @@ -1 +1,2 @@ -static _X: () = loop {}; // { dg-error "loop iteration count exceeds limit" } +static _X : () + = loop{}; // { dg-error "'loop' is not allowed in const context" } diff --git a/gcc/testsuite/rust/compile/loop_constant_context.rs b/gcc/testsuite/rust/compile/loop_constant_context.rs new file mode 100644 index 000000000000..ed0782b91a6f --- /dev/null +++ b/gcc/testsuite/rust/compile/loop_constant_context.rs @@ -0,0 +1,5 @@ +// { dg-error "'loop' is not allowed in const context" "" { target *-*-* } .+1 } +const CONST_LOOP : () = loop{}; + +// { dg-error "'loop' is not allowed in const context" "" { target *-*-* } .+1 } +static STATIC_LOOP : () = loop{}; \ No newline at end of file From d9387e5525c2e15c91fccb767f7cfdfd78d5a3ca Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 18 Jul 2025 16:11:59 +0100 Subject: [PATCH 148/161] gccrs: Add test case to show issue is fixed Fixes Rust-GCC#3524 gcc/testsuite/ChangeLog: * rust/compile/issue-3524.rs: New test. Signed-off-by: Philip Herron --- gcc/testsuite/rust/compile/issue-3524.rs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 gcc/testsuite/rust/compile/issue-3524.rs diff --git a/gcc/testsuite/rust/compile/issue-3524.rs b/gcc/testsuite/rust/compile/issue-3524.rs new file mode 100644 index 000000000000..62c8c3512747 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3524.rs @@ -0,0 +1,9 @@ +struct A {} +// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 } + +impl A { + fn main() {} + // { dg-warning "associated function is never used: .main." "" { target *-*-* } .-1 } +} + +fn main() {} From f67302f4d372989ab6da0827c5585f236118bdaa Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Mon, 14 Jul 2025 22:47:07 -0400 Subject: [PATCH 149/161] Improve parsing of simple paths gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_simple_path): Be more careful about skipping SCOPE_RESOLUTION tokens. (Parser::parse_simple_path_segment): Allow parsing from a starting offset. (Parser::parse_use_tree): Handle a non-skipped SCOPE_RESOLUTION token. * parse/rust-parse.h (Parser::parse_simple_path_segment): Add parameter for parsing from a starting offset. gcc/testsuite/ChangeLog: * rust/compile/parse_simple_path_fail_1.rs: New test. * rust/compile/parse_simple_path_fail_2.rs: New test. Signed-off-by: Owen Avery --- gcc/rust/parse/rust-parse-impl.h | 138 +++++++++--------- gcc/rust/parse/rust-parse.h | 2 +- .../rust/compile/parse_simple_path_fail_1.rs | 3 + .../rust/compile/parse_simple_path_fail_2.rs | 9 ++ 4 files changed, 85 insertions(+), 67 deletions(-) create mode 100644 gcc/testsuite/rust/compile/parse_simple_path_fail_1.rs create mode 100644 gcc/testsuite/rust/compile/parse_simple_path_fail_2.rs diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 9608cd885f4a..8233af2b0a32 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -654,10 +654,7 @@ Parser::parse_simple_path () // Parse all other simple path segments while (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION) { - // Skip scope resolution operator - lexer.skip_token (); - - AST::SimplePathSegment new_segment = parse_simple_path_segment (); + AST::SimplePathSegment new_segment = parse_simple_path_segment (1); // Return path as currently constructed if segment in error state. if (new_segment.is_error ()) @@ -685,35 +682,36 @@ Parser::parse_simple_path () } /* Parses a single SimplePathSegment (does not handle the scope resolution - * operators) */ + * operators) + * Starts parsing at an offset of base_peek */ template AST::SimplePathSegment -Parser::parse_simple_path_segment () +Parser::parse_simple_path_segment (int base_peek) { using namespace Values; - const_TokenPtr t = lexer.peek_token (); + const_TokenPtr t = lexer.peek_token (base_peek); switch (t->get_id ()) { case IDENTIFIER: - lexer.skip_token (); + lexer.skip_token (base_peek); return AST::SimplePathSegment (t->get_str (), t->get_locus ()); case SUPER: - lexer.skip_token (); + lexer.skip_token (base_peek); return AST::SimplePathSegment (Keywords::SUPER, t->get_locus ()); case SELF: - lexer.skip_token (); + lexer.skip_token (base_peek); return AST::SimplePathSegment (Keywords::SELF, t->get_locus ()); case CRATE: - lexer.skip_token (); + lexer.skip_token (base_peek); return AST::SimplePathSegment (Keywords::CRATE, t->get_locus ()); case DOLLAR_SIGN: - if (lexer.peek_token (1)->get_id () == CRATE) + if (lexer.peek_token (base_peek + 1)->get_id () == CRATE) { - lexer.skip_token (1); + lexer.skip_token (base_peek + 1); return AST::SimplePathSegment ("$crate", t->get_locus ()); } @@ -2807,58 +2805,10 @@ Parser::parse_use_tree () } else { - /* Due to aforementioned implementation issues, the trailing :: token is - * consumed by the path, so it can not be used as a disambiguator. - * NOPE, not true anymore - TODO what are the consequences of this? */ - const_TokenPtr t = lexer.peek_token (); + switch (t->get_id ()) { - case ASTERISK: - // glob UseTree type - lexer.skip_token (); - - return std::unique_ptr ( - new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED, - std::move (path), locus)); - case LEFT_CURLY: - { - // nested tree UseTree type - lexer.skip_token (); - - std::vector> use_trees; - - // TODO: think of better control structure - const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_CURLY) - { - std::unique_ptr use_tree = parse_use_tree (); - if (use_tree == nullptr) - { - break; - } - - use_trees.push_back (std::move (use_tree)); - - if (lexer.peek_token ()->get_id () != COMMA) - break; - - lexer.skip_token (); - t = lexer.peek_token (); - } - - // skip end curly delimiter - if (!skip_token (RIGHT_CURLY)) - { - // skip after somewhere? - return nullptr; - } - - return std::unique_ptr ( - new AST::UseTreeList (AST::UseTreeList::PATH_PREFIXED, - std::move (path), std::move (use_trees), - locus)); - } case AS: { // rebind UseTree type @@ -2899,16 +2849,72 @@ Parser::parse_use_tree () // don't skip semicolon - handled in parse_use_tree // lexer.skip_token(); - - return std::unique_ptr ( - new AST::UseTreeRebind (AST::UseTreeRebind::NONE, std::move (path), - locus)); case COMMA: case RIGHT_CURLY: // this may occur in recursive calls - assume it is ok and ignore it return std::unique_ptr ( new AST::UseTreeRebind (AST::UseTreeRebind::NONE, std::move (path), locus)); + case SCOPE_RESOLUTION: + // keep going + break; + default: + add_error (Error (t->get_locus (), + "unexpected token %qs in use tree with valid path", + t->get_token_description ())); + return nullptr; + } + + skip_token (); + t = lexer.peek_token (); + + switch (t->get_id ()) + { + case ASTERISK: + // glob UseTree type + lexer.skip_token (); + + return std::unique_ptr ( + new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED, + std::move (path), locus)); + case LEFT_CURLY: + { + // nested tree UseTree type + lexer.skip_token (); + + std::vector> use_trees; + + // TODO: think of better control structure + const_TokenPtr t = lexer.peek_token (); + while (t->get_id () != RIGHT_CURLY) + { + std::unique_ptr use_tree = parse_use_tree (); + if (use_tree == nullptr) + { + break; + } + + use_trees.push_back (std::move (use_tree)); + + if (lexer.peek_token ()->get_id () != COMMA) + break; + + lexer.skip_token (); + t = lexer.peek_token (); + } + + // skip end curly delimiter + if (!skip_token (RIGHT_CURLY)) + { + // skip after somewhere? + return nullptr; + } + + return std::unique_ptr ( + new AST::UseTreeList (AST::UseTreeList::PATH_PREFIXED, + std::move (path), std::move (use_trees), + locus)); + } default: add_error (Error (t->get_locus (), "unexpected token %qs in use tree with valid path", diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 36426d56f8d7..7983beb69bc2 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -227,7 +227,7 @@ template class Parser // Path-related AST::SimplePath parse_simple_path (); - AST::SimplePathSegment parse_simple_path_segment (); + AST::SimplePathSegment parse_simple_path_segment (int base_peek = 0); AST::TypePath parse_type_path (); std::unique_ptr parse_type_path_segment (); AST::PathIdentSegment parse_path_ident_segment (); diff --git a/gcc/testsuite/rust/compile/parse_simple_path_fail_1.rs b/gcc/testsuite/rust/compile/parse_simple_path_fail_1.rs new file mode 100644 index 000000000000..c112e4048ed0 --- /dev/null +++ b/gcc/testsuite/rust/compile/parse_simple_path_fail_1.rs @@ -0,0 +1,3 @@ +pub(in crate::) struct S; +// { dg-error "expecting ... but .::. found" "" { target *-*-* } .-1 } +// { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 } diff --git a/gcc/testsuite/rust/compile/parse_simple_path_fail_2.rs b/gcc/testsuite/rust/compile/parse_simple_path_fail_2.rs new file mode 100644 index 000000000000..94c49c381b25 --- /dev/null +++ b/gcc/testsuite/rust/compile/parse_simple_path_fail_2.rs @@ -0,0 +1,9 @@ +mod A { + struct B; +} + +use A{B}; +// { dg-error "unexpected token" "" { target *-*-* } .-1 } +// { dg-error "could not parse use tree" "" { target *-*-* } .-2 } +// { dg-error "failed to parse item in crate" "" { target *-*-* } 10 } +// ^^^ TODO: should the above error happen at line 10? From 66e979473cf312474d091c4ab028fd27483bd484 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 18 Jul 2025 16:22:44 +0100 Subject: [PATCH 150/161] gccrs: Fix ICE with duplicate root item main function Rust seems to allow duplicate HIR::Item 'main' functions but it needs to be a root item to be the true main entry point. This means we can use the canonical path to determine if this is a root one where its CrateName::main or CrateName::Module::main. Fixes Rust-GCC#3978 gcc/rust/ChangeLog: * backend/rust-compile-base.cc: check the canonical path gcc/testsuite/ChangeLog: * rust/compile/issue-3978.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/backend/rust-compile-base.cc | 3 ++- gcc/testsuite/rust/compile/issue-3978.rs | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/rust/compile/issue-3978.rs diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index b2913ad3c381..8994520f16d5 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -697,7 +697,8 @@ HIRCompileBase::compile_function ( = canonical_path.get () + fntype->subst_as_string (); // we don't mangle the main fn since we haven't implemented the main shim - bool is_main_fn = fn_name.compare ("main") == 0 && is_root_item; + bool is_main_fn = fn_name.compare ("main") == 0 && is_root_item + && canonical_path.size () <= 2; if (is_main_fn) { rust_assert (!main_identifier_node); diff --git a/gcc/testsuite/rust/compile/issue-3978.rs b/gcc/testsuite/rust/compile/issue-3978.rs new file mode 100644 index 000000000000..4f17d3d4d04a --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3978.rs @@ -0,0 +1,8 @@ +type Dimension = usize; + +pub fn main() {} + +mod m2 { + fn main() {} + // { dg-warning "function is never used" "" { target *-*-* } .-1 } +} From ec6a6d5e067a17d189377fc8ee230d850fc373b6 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 18 Jul 2025 15:46:59 +0100 Subject: [PATCH 151/161] gccrs: Add initial support for deffered operator overload resolution In the test case: fn test (len: usize) -> u64 { let mut i = 0; let mut out = 0; if i + 3 < len { out = 123; } out } The issue is to determine the correct type of 'i', out is simple because it hits a coercion site in the resturn position for u64. But 'i + 3', 'i' is an integer infer variable and the same for the literal '3'. So when it comes to resolving the type for the Add expression we hit the resolve the operator overload code and because of this: macro_rules! add_impl { ($($t:ty)*) => ($( impl Add for $t { type Output = $t; #[inline] #[rustc_inherit_overflow_checks] fn add(self, other: $t) -> $t { self + other } } )*) } add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } This means the resolution for 'i + 3' is ambigious because it could be any of these Add implementations. But because we unify against the '< len' where len is defined as usize later in the resolution we determine 'i' is actually a usize. Which means if we defer the resolution of this operator overload in the ambigious case we can simply resolve it at the end. Fixes Rust-GCC#3916 gcc/rust/ChangeLog: * hir/tree/rust-hir-expr.cc (OperatorExprMeta::OperatorExprMeta): track the rhs * hir/tree/rust-hir-expr.h: likewise * hir/tree/rust-hir-path.h: get rid of old comments * typecheck/rust-hir-trait-reference.cc (TraitReference::get_trait_substs): return references instead of copy * typecheck/rust-hir-trait-reference.h: update header * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::ResolveOpOverload): write ambigious operator overloads to a table and try to resolve it at the end * typecheck/rust-hir-type-check-expr.h: new static helper * typecheck/rust-hir-type-check.h (struct DeferredOpOverload): new model to defer resolution * typecheck/rust-typecheck-context.cc (TypeCheckContext::lookup_operator_overload): new (TypeCheckContext::compute_ambigious_op_overload): likewise (TypeCheckContext::compute_inference_variables): likewise gcc/testsuite/ChangeLog: * rust/compile/issue-3916.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/hir/tree/rust-hir-expr.cc | 10 ++- gcc/rust/hir/tree/rust-hir-expr.h | 32 ++++++++- gcc/rust/hir/tree/rust-hir-path.h | 12 ++-- .../typecheck/rust-hir-trait-reference.cc | 8 ++- gcc/rust/typecheck/rust-hir-trait-reference.h | 4 +- .../typecheck/rust-hir-type-check-expr.cc | 71 +++++++++++++++++-- gcc/rust/typecheck/rust-hir-type-check-expr.h | 5 ++ gcc/rust/typecheck/rust-hir-type-check.h | 45 ++++++++++++ gcc/rust/typecheck/rust-typecheck-context.cc | 63 +++++++++++++++- gcc/testsuite/rust/compile/issue-3916.rs | 36 ++++++++++ 10 files changed, 267 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/rust/compile/issue-3916.rs diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc b/gcc/rust/hir/tree/rust-hir-expr.cc index 93dcec2c8d79..038bfc77f94a 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.cc +++ b/gcc/rust/hir/tree/rust-hir-expr.cc @@ -17,6 +17,7 @@ // . #include "rust-hir-expr.h" +#include "rust-hir-map.h" #include "rust-operators.h" #include "rust-hir-stmt.h" @@ -1321,37 +1322,40 @@ AsyncBlockExpr::operator= (AsyncBlockExpr const &other) OperatorExprMeta::OperatorExprMeta (HIR::CompoundAssignmentExpr &expr) : node_mappings (expr.get_mappings ()), lvalue_mappings (expr.get_expr ().get_mappings ()), - locus (expr.get_locus ()) + rvalue_mappings (expr.get_rhs ().get_mappings ()), locus (expr.get_locus ()) {} OperatorExprMeta::OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr) : node_mappings (expr.get_mappings ()), lvalue_mappings (expr.get_expr ().get_mappings ()), - locus (expr.get_locus ()) + rvalue_mappings (expr.get_rhs ().get_mappings ()), locus (expr.get_locus ()) {} OperatorExprMeta::OperatorExprMeta (HIR::NegationExpr &expr) : node_mappings (expr.get_mappings ()), lvalue_mappings (expr.get_expr ().get_mappings ()), + rvalue_mappings (Analysis::NodeMapping::get_error ()), locus (expr.get_locus ()) {} OperatorExprMeta::OperatorExprMeta (HIR::DereferenceExpr &expr) : node_mappings (expr.get_mappings ()), lvalue_mappings (expr.get_expr ().get_mappings ()), + rvalue_mappings (Analysis::NodeMapping::get_error ()), locus (expr.get_locus ()) {} OperatorExprMeta::OperatorExprMeta (HIR::ArrayIndexExpr &expr) : node_mappings (expr.get_mappings ()), lvalue_mappings (expr.get_array_expr ().get_mappings ()), + rvalue_mappings (expr.get_index_expr ().get_mappings ()), locus (expr.get_locus ()) {} OperatorExprMeta::OperatorExprMeta (HIR::ComparisonExpr &expr) : node_mappings (expr.get_mappings ()), lvalue_mappings (expr.get_expr ().get_mappings ()), - locus (expr.get_locus ()) + rvalue_mappings (expr.get_rhs ().get_mappings ()), locus (expr.get_locus ()) {} InlineAsmOperand::In::In ( diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index fcb4744fef4c..028455b98702 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -27,6 +27,7 @@ #include "rust-hir-attrs.h" #include "rust-expr.h" #include "rust-hir-map.h" +#include "rust-mapping-common.h" namespace Rust { namespace HIR { @@ -2892,6 +2893,22 @@ class OperatorExprMeta OperatorExprMeta (HIR::ComparisonExpr &expr); + OperatorExprMeta (const OperatorExprMeta &other) + : node_mappings (other.node_mappings), + lvalue_mappings (other.lvalue_mappings), + rvalue_mappings (other.rvalue_mappings), locus (other.locus) + {} + + OperatorExprMeta &operator= (const OperatorExprMeta &other) + { + node_mappings = other.node_mappings; + lvalue_mappings = other.lvalue_mappings; + rvalue_mappings = other.rvalue_mappings; + locus = other.locus; + + return *this; + } + const Analysis::NodeMapping &get_mappings () const { return node_mappings; } const Analysis::NodeMapping &get_lvalue_mappings () const @@ -2899,11 +2916,22 @@ class OperatorExprMeta return lvalue_mappings; } + const Analysis::NodeMapping &get_rvalue_mappings () const + { + return rvalue_mappings; + } + + bool has_rvalue_mappings () const + { + return rvalue_mappings.get_hirid () != UNKNOWN_HIRID; + } + location_t get_locus () const { return locus; } private: - const Analysis::NodeMapping node_mappings; - const Analysis::NodeMapping lvalue_mappings; + Analysis::NodeMapping node_mappings; + Analysis::NodeMapping lvalue_mappings; + Analysis::NodeMapping rvalue_mappings; location_t locus; }; diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index 3ce2662c8024..5f88c6827bb1 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -41,11 +41,15 @@ class PathIdentSegment : segment_name (std::move (segment_name)) {} - /* TODO: insert check in constructor for this? Or is this a semantic error - * best handled then? */ + PathIdentSegment (const PathIdentSegment &other) + : segment_name (other.segment_name) + {} - /* TODO: does this require visitor? pretty sure this isn't polymorphic, but - * not entirely sure */ + PathIdentSegment &operator= (PathIdentSegment const &other) + { + segment_name = other.segment_name; + return *this; + } // Creates an error PathIdentSegment. static PathIdentSegment create_error () { return PathIdentSegment (""); } diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.cc b/gcc/rust/typecheck/rust-hir-trait-reference.cc index 88e270d510d2..74856f098fa0 100644 --- a/gcc/rust/typecheck/rust-hir-trait-reference.cc +++ b/gcc/rust/typecheck/rust-hir-trait-reference.cc @@ -432,7 +432,13 @@ TraitReference::trait_has_generics () const return !trait_substs.empty (); } -std::vector +std::vector & +TraitReference::get_trait_substs () +{ + return trait_substs; +} + +const std::vector & TraitReference::get_trait_substs () const { return trait_substs; diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h index 8b1ac7daf7f1..473513ea75ff 100644 --- a/gcc/rust/typecheck/rust-hir-trait-reference.h +++ b/gcc/rust/typecheck/rust-hir-trait-reference.h @@ -224,7 +224,9 @@ class TraitReference bool trait_has_generics () const; - std::vector get_trait_substs () const; + std::vector &get_trait_substs (); + + const std::vector &get_trait_substs () const; bool satisfies_bound (const TraitReference &reference) const; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index c1404561f4d0..5db0e5690c97 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -17,6 +17,7 @@ // . #include "optional.h" +#include "rust-common.h" #include "rust-hir-expr.h" #include "rust-system.h" #include "rust-tyty-call.h" @@ -59,6 +60,19 @@ TypeCheckExpr::Resolve (HIR::Expr &expr) return resolver.infered; } +TyTy::BaseType * +TypeCheckExpr::ResolveOpOverload (LangItem::Kind lang_item_type, + HIR::OperatorExprMeta expr, + TyTy::BaseType *lhs, TyTy::BaseType *rhs, + HIR::PathIdentSegment specified_segment) +{ + TypeCheckExpr resolver; + + resolver.resolve_operator_overload (lang_item_type, expr, lhs, rhs, + specified_segment); + return resolver.infered; +} + void TypeCheckExpr::visit (HIR::TupleIndexExpr &expr) { @@ -1885,7 +1899,16 @@ TypeCheckExpr::resolve_operator_overload ( // probe for the lang-item if (!lang_item_defined) return false; + DefId &respective_lang_item_id = lang_item_defined.value (); + auto def_lookup = mappings.lookup_defid (respective_lang_item_id); + rust_assert (def_lookup.has_value ()); + + HIR::Item *def_item = def_lookup.value (); + rust_assert (def_item->get_item_kind () == HIR::Item::ItemKind::Trait); + HIR::Trait &trait = *static_cast (def_item); + TraitReference *defid_trait_reference = TraitResolver::Resolve (trait); + rust_assert (!defid_trait_reference->is_error ()); // we might be in a static or const context and unknown is fine TypeCheckContextItem current_context = TypeCheckContextItem::get_error (); @@ -1929,15 +1952,49 @@ TypeCheckExpr::resolve_operator_overload ( if (selected_candidates.size () > 1) { - // mutliple candidates - rich_location r (line_table, expr.get_locus ()); - for (auto &c : resolved_candidates) - r.add_range (c.candidate.locus); + auto infer + = TyTy::TyVar::get_implicit_infer_var (expr.get_locus ()).get_tyty (); + auto trait_subst = defid_trait_reference->get_trait_substs (); + rust_assert (trait_subst.size () > 0); - rust_error_at ( - r, "multiple candidates found for possible operator overload"); + TyTy::TypeBoundPredicate pred (respective_lang_item_id, trait_subst, + BoundPolarity::RegularBound, + expr.get_locus ()); - return false; + std::vector mappings; + auto &self_param_mapping = trait_subst[0]; + mappings.push_back (TyTy::SubstitutionArg (&self_param_mapping, lhs)); + + if (rhs != nullptr) + { + rust_assert (trait_subst.size () == 2); + auto &rhs_param_mapping = trait_subst[1]; + mappings.push_back (TyTy::SubstitutionArg (&rhs_param_mapping, lhs)); + } + + std::map binding_args; + binding_args["Output"] = infer; + + TyTy::SubstitutionArgumentMappings arg_mappings (mappings, binding_args, + TyTy::RegionParamList ( + trait_subst.size ()), + expr.get_locus ()); + pred.apply_argument_mappings (arg_mappings, false); + + infer->inherit_bounds ({pred}); + DeferredOpOverload defer (expr.get_mappings ().get_hirid (), + lang_item_type, specified_segment, pred, expr); + context->insert_deferred_operator_overload (std::move (defer)); + + if (rhs != nullptr) + lhs = unify_site (expr.get_mappings ().get_hirid (), + TyTy::TyWithLocation (lhs), + TyTy::TyWithLocation (rhs), expr.get_locus ()); + + infered = unify_site (expr.get_mappings ().get_hirid (), + TyTy::TyWithLocation (lhs), + TyTy::TyWithLocation (infer), expr.get_locus ()); + return true; } // Get the adjusted self diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 531197436853..48f28c700795 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -31,6 +31,11 @@ class TypeCheckExpr : private TypeCheckBase, private HIR::HIRExpressionVisitor public: static TyTy::BaseType *Resolve (HIR::Expr &expr); + static TyTy::BaseType * + ResolveOpOverload (LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr, + TyTy::BaseType *lhs, TyTy::BaseType *rhs, + HIR::PathIdentSegment specified_segment); + void visit (HIR::TupleIndexExpr &expr) override; void visit (HIR::TupleExpr &expr) override; void visit (HIR::ReturnExpr &expr) override; diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 356c55803ed6..80e403448359 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -20,6 +20,7 @@ #define RUST_HIR_TYPE_CHECK #include "rust-hir-map.h" +#include "rust-mapping-common.h" #include "rust-tyty.h" #include "rust-hir-trait-reference.h" #include "rust-stacked-contexts.h" @@ -157,6 +158,39 @@ class Lifetime WARN_UNUSED_RESULT Lifetime next () { return Lifetime (interner_index++); } }; +struct DeferredOpOverload +{ + HirId expr_id; + LangItem::Kind lang_item_type; + HIR::PathIdentSegment specified_segment; + TyTy::TypeBoundPredicate predicate; + HIR::OperatorExprMeta op; + + DeferredOpOverload (HirId expr_id, LangItem::Kind lang_item_type, + HIR::PathIdentSegment specified_segment, + TyTy::TypeBoundPredicate &predicate, + HIR::OperatorExprMeta op) + : expr_id (expr_id), lang_item_type (lang_item_type), + specified_segment (specified_segment), predicate (predicate), op (op) + {} + + DeferredOpOverload (const struct DeferredOpOverload &other) + : expr_id (other.expr_id), lang_item_type (other.lang_item_type), + specified_segment (other.specified_segment), predicate (other.predicate), + op (other.op) + {} + + DeferredOpOverload &operator= (struct DeferredOpOverload const &other) + { + expr_id = other.expr_id; + lang_item_type = other.lang_item_type; + specified_segment = other.specified_segment; + op = other.op; + + return *this; + } +}; + class TypeCheckContext { public: @@ -237,6 +271,13 @@ class TypeCheckContext void insert_operator_overload (HirId id, TyTy::FnType *call_site); bool lookup_operator_overload (HirId id, TyTy::FnType **call); + void insert_deferred_operator_overload (DeferredOpOverload deferred); + bool lookup_deferred_operator_overload (HirId id, + DeferredOpOverload *deferred); + + void iterate_deferred_operator_overloads ( + std::function cb); + void insert_unconstrained_check_marker (HirId id, bool status); bool have_checked_for_unconstrained (HirId id, bool *result); @@ -271,6 +312,7 @@ class TypeCheckContext TypeCheckContext (); bool compute_infer_var (HirId id, TyTy::BaseType *ty, bool emit_error); + bool compute_ambigious_op_overload (HirId id, DeferredOpOverload &op); std::map node_id_refs; std::map resolved; @@ -308,6 +350,9 @@ class TypeCheckContext std::set querys_in_progress; std::set trait_queries_in_progress; + // deferred operator overload + std::map deferred_operator_overloads; + // variance analysis TyTy::VarianceAnalysis::CrateCtx variance_analysis_ctx; diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc index 7b3584823e44..83b17612d5e3 100644 --- a/gcc/rust/typecheck/rust-typecheck-context.cc +++ b/gcc/rust/typecheck/rust-typecheck-context.cc @@ -18,6 +18,7 @@ #include "rust-hir-type-check.h" #include "rust-type-util.h" +#include "rust-hir-type-check-expr.h" namespace Rust { namespace Resolver { @@ -408,6 +409,38 @@ TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call) return true; } +void +TypeCheckContext::insert_deferred_operator_overload ( + DeferredOpOverload deferred) +{ + HirId expr_id = deferred.expr_id; + deferred_operator_overloads.emplace (std::make_pair (expr_id, deferred)); +} + +bool +TypeCheckContext::lookup_deferred_operator_overload ( + HirId id, DeferredOpOverload *deferred) +{ + auto it = deferred_operator_overloads.find (id); + if (it == deferred_operator_overloads.end ()) + return false; + + *deferred = it->second; + return true; +} + +void +TypeCheckContext::iterate_deferred_operator_overloads ( + std::function cb) +{ + for (auto it = deferred_operator_overloads.begin (); + it != deferred_operator_overloads.end (); it++) + { + if (!cb (it->first, it->second)) + return; + } +} + void TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status) { @@ -574,10 +607,38 @@ TypeCheckContext::regions_from_generic_args (const HIR::GenericArgs &args) const return regions; } +bool +TypeCheckContext::compute_ambigious_op_overload (HirId id, + DeferredOpOverload &op) +{ + rust_debug ("attempting resolution of op overload: %s", + op.predicate.as_string ().c_str ()); + + TyTy::BaseType *lhs = nullptr; + bool ok = lookup_type (op.op.get_lvalue_mappings ().get_hirid (), &lhs); + rust_assert (ok); + + TyTy::BaseType *rhs = nullptr; + if (op.op.has_rvalue_mappings ()) + { + bool ok = lookup_type (op.op.get_rvalue_mappings ().get_hirid (), &rhs); + rust_assert (ok); + } + + TypeCheckExpr::ResolveOpOverload (op.lang_item_type, op.op, lhs, rhs, + op.specified_segment); + + return true; +} + void TypeCheckContext::compute_inference_variables (bool emit_error) { - // default inference variables if possible + iterate_deferred_operator_overloads ( + [&] (HirId id, DeferredOpOverload &op) mutable -> bool { + return compute_ambigious_op_overload (id, op); + }); + iterate ([&] (HirId id, TyTy::BaseType *ty) mutable -> bool { return compute_infer_var (id, ty, emit_error); }); diff --git a/gcc/testsuite/rust/compile/issue-3916.rs b/gcc/testsuite/rust/compile/issue-3916.rs new file mode 100644 index 000000000000..59b522b4ed5c --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3916.rs @@ -0,0 +1,36 @@ +#![feature(rustc_attrs)] + +#[lang = "sized"] +trait Sized {} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! add_impl { + ($($t:ty)*) => ($( + impl Add for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn add(self, other: $t) -> $t { self + other } + } + )*) +} + +add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +pub fn test(len: usize) -> u64 { + let mut i = 0; + let mut out = 0; + if i + 3 < len { + out = 123; + } else { + out = 456; + } + out +} From aef720dceff4f514a56db3b3f441559616f34f21 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 18 Jul 2025 16:44:36 +0100 Subject: [PATCH 152/161] gccrs: return error node when this fails during constexpr case Not adding the test case here we emit more errors than rustc for the error type node so its just noisy and dejagnu is being a pain. Fixes Rust-GCC#3933 gcc/rust/ChangeLog: * backend/rust-compile-resolve-path.cc (ResolvePathRef::resolve): return error_mark_node Signed-off-by: Philip Herron --- gcc/rust/backend/rust-compile-resolve-path.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index a80484acf097..6d92c0cd1021 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -214,7 +214,8 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, { TyTy::BaseType *lookup = nullptr; bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup); - rust_assert (ok); + if (!ok) + return error_mark_node; // need to look up the reference for this identifier From 1b6483e77613f20b8da09de0d9de01680f894bf0 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Tue, 8 Jul 2025 17:03:49 -0400 Subject: [PATCH 153/161] Use MacroInvocLexer in AttributeParser This should make it easier for us to handle attribute meta items of the form '=' where the expression isn't a literal. Some low hanging fruit remains here, but I think I should keep this patch small as I had some trouble debugging it as-is (see: Rust::Token::as_string vs Rust::Token::get_str vs Rust::AST::Token::as_string). gcc/rust/ChangeLog: * ast/rust-ast.cc: Include "rust-macro-invoc-lexer.h". (AttributeParser::~AttributeParser): Move function definition here. (AttributeParser::AttributeParser): Likewise and adjust member initialization. (AttributeParser::parse_meta_item_inner): Handle changes to peek_token. (AttributeParser::parse_literal): Likewise. (AttributeParser::parse_simple_path_segment): Likewise. (AttributeParser::parse_meta_item_seq): Handle changes to AttributeParser fields. (AttributeParser::peek_token): Move function definition here and wrap MacroInvocLexer. (AttributeParser::skip_token): Likewise. * ast/rust-macro.h (class MacroInvocLexer): Forward declare. (class Parser): Likewise. (AttributeParser::token_stream): Remove field. (AttributeParser::stream_pos): Likewise. (AttributeParser::lexer): New field. (AttributeParser::parser): Likewise. (AttributeParser::AttributeParser): Move definition to "rust-ast.cc". (AttributeParser::~AttributeParser): Likewise. (AttributeParser::peek_token): Likewise. (AttributeParser::skip_token): Likewise. Signed-off-by: Owen Avery --- gcc/rust/ast/rust-ast.cc | 60 ++++++++++++++++++++++++++------------- gcc/rust/ast/rust-macro.h | 22 +++++++------- 2 files changed, 51 insertions(+), 31 deletions(-) diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 4d928ca7a2d5..3d230ce55c32 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "rust-operators.h" #include "rust-dir-owner.h" #include "rust-attribute-values.h" +#include "rust-macro-invoc-lexer.h" /* Compilation unit used for various AST-related functions that would make * the headers too long if they were defined inline and don't receive any @@ -3508,6 +3509,17 @@ DelimTokenTree::parse_to_meta_item () const return new AttrInputMetaItemContainer (std::move (meta_items)); } +AttributeParser::AttributeParser ( + std::vector> token_stream, int stream_start_pos) + : lexer (new MacroInvocLexer (std::move (token_stream))), + parser (new Parser (*lexer)) +{ + if (stream_start_pos) + lexer->skip_token (stream_start_pos - 1); +} + +AttributeParser::~AttributeParser () {} + std::unique_ptr AttributeParser::parse_meta_item_inner () { @@ -3549,7 +3561,7 @@ AttributeParser::parse_meta_item_inner () return parse_path_meta_item (); } - auto ident = peek_token ()->as_string (); + auto ident = peek_token ()->get_str (); auto ident_locus = peek_token ()->get_locus (); if (is_end_meta_item_tok (peek_token (1)->get_id ())) @@ -3566,17 +3578,14 @@ AttributeParser::parse_meta_item_inner () && is_end_meta_item_tok (peek_token (3)->get_id ())) { // meta name value str syntax - auto &value_tok = peek_token (2); - auto value = value_tok->as_string (); + const_TokenPtr value_tok = peek_token (2); + auto value = value_tok->get_str (); auto locus = value_tok->get_locus (); skip_token (2); - // remove the quotes from the string value - std::string raw_value = unquote_string (std::move (value)); - return std::unique_ptr ( - new MetaNameValueStr (ident, ident_locus, std::move (raw_value), + new MetaNameValueStr (ident, ident_locus, std::move (value), locus)); } else @@ -3728,7 +3737,6 @@ AttributeParser::parse_path_meta_item () std::vector> AttributeParser::parse_meta_item_seq () { - int vec_length = token_stream.size (); std::vector> meta_items; if (peek_token ()->get_id () != LEFT_PAREN) @@ -3739,7 +3747,8 @@ AttributeParser::parse_meta_item_seq () } skip_token (); - while (stream_pos < vec_length && peek_token ()->get_id () != RIGHT_PAREN) + while (peek_token ()->get_id () != END_OF_FILE + && peek_token ()->get_id () != RIGHT_PAREN) { std::unique_ptr inner = parse_meta_item_inner (); if (inner == nullptr) @@ -3788,33 +3797,32 @@ DelimTokenTree::to_token_stream () const Literal AttributeParser::parse_literal () { - const std::unique_ptr &tok = peek_token (); + const_TokenPtr tok = peek_token (); switch (tok->get_id ()) { case CHAR_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::CHAR, tok->get_type_hint ()); + return Literal (tok->get_str (), Literal::CHAR, tok->get_type_hint ()); case STRING_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::STRING, - tok->get_type_hint ()); + return Literal (tok->get_str (), Literal::STRING, tok->get_type_hint ()); case BYTE_CHAR_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::BYTE, tok->get_type_hint ()); + return Literal (tok->get_str (), Literal::BYTE, tok->get_type_hint ()); case BYTE_STRING_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::BYTE_STRING, + return Literal (tok->get_str (), Literal::BYTE_STRING, tok->get_type_hint ()); case RAW_STRING_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::RAW_STRING, + return Literal (tok->get_str (), Literal::RAW_STRING, tok->get_type_hint ()); case INT_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::INT, tok->get_type_hint ()); + return Literal (tok->get_str (), Literal::INT, tok->get_type_hint ()); case FLOAT_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::FLOAT, tok->get_type_hint ()); + return Literal (tok->get_str (), Literal::FLOAT, tok->get_type_hint ()); case TRUE_LITERAL: skip_token (); return Literal ("true", Literal::BOOL, tok->get_type_hint ()); @@ -3872,12 +3880,12 @@ AttributeParser::parse_simple_path () SimplePathSegment AttributeParser::parse_simple_path_segment () { - const std::unique_ptr &tok = peek_token (); + const_TokenPtr tok = peek_token (); switch (tok->get_id ()) { case IDENTIFIER: skip_token (); - return SimplePathSegment (tok->as_string (), tok->get_locus ()); + return SimplePathSegment (tok->get_str (), tok->get_locus ()); case SUPER: skip_token (); return SimplePathSegment ("super", tok->get_locus ()); @@ -3911,6 +3919,18 @@ AttributeParser::parse_meta_item_lit () new MetaItemLitExpr (std::move (lit_expr))); } +const_TokenPtr +AttributeParser::peek_token (int i) +{ + return lexer->peek_token (i); +} + +void +AttributeParser::skip_token (int i) +{ + lexer->skip_token (i); +} + bool AttrInputMetaItemContainer::check_cfg_predicate (const Session &session) const { diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index e8f377c001ec..d32acf30669b 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -27,6 +27,11 @@ #include "rust-macro-builtins.h" namespace Rust { + +// forward declarations for AttributeParser +class MacroInvocLexer; +template class Parser; + namespace AST { class MacroFragSpec @@ -1116,16 +1121,14 @@ struct AttributeParser { private: // TODO: might as well rewrite to use lexer tokens - std::vector> token_stream; - int stream_pos; + std::unique_ptr lexer; + std::unique_ptr> parser; public: AttributeParser (std::vector> token_stream, - int stream_start_pos = 0) - : token_stream (std::move (token_stream)), stream_pos (stream_start_pos) - {} + int stream_start_pos = 0); - ~AttributeParser () = default; + ~AttributeParser (); std::vector> parse_meta_item_seq (); @@ -1146,12 +1149,9 @@ struct AttributeParser std::unique_ptr parse_path_meta_item (); // TODO: should this be const? - std::unique_ptr &peek_token (int i = 0) - { - return token_stream[stream_pos + i]; - } + const_TokenPtr peek_token (int i = 0); - void skip_token (int i = 0) { stream_pos += 1 + i; } + void skip_token (int i = 0); }; } // namespace AST } // namespace Rust From 5bfe856cc4bf66dce058171166bae16793b5a87c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sun, 20 Jul 2025 21:48:18 +0100 Subject: [PATCH 154/161] gccrs: fix bad monomophization of generic paths When we have generic paths like T::foobar during codegen sometimes we need to enforce an extra lookup for this generic parameter type to the mono morphized underlying type. Fixes Rust-GCC#3915 Fixes Rust-GCC#1247 gcc/rust/ChangeLog: * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): do another lookup gcc/testsuite/ChangeLog: * rust/compile/issue-3915.rs: New test. * rust/execute/torture/sip-hasher.rs: New test. Signed-off-by: Philip Herron --- gcc/rust/backend/rust-compile-resolve-path.cc | 15 +- gcc/testsuite/rust/compile/issue-3915.rs | 28 ++ .../rust/execute/torture/sip-hasher.rs | 438 ++++++++++++++++++ 3 files changed, 477 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/rust/compile/issue-3915.rs create mode 100644 gcc/testsuite/rust/execute/torture/sip-hasher.rs diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 6d92c0cd1021..be2af64fc38a 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -329,11 +329,18 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup, rust_assert (lookup->is ()); auto fn = lookup->as (); rust_assert (fn->get_num_type_params () > 0); - auto &self = fn->get_substs ().at (0); - auto receiver = self.get_param_ty (); + TyTy::SubstitutionParamMapping &self = fn->get_substs ().at (0); + TyTy::ParamType *receiver = self.get_param_ty (); + TyTy::BaseType *r = receiver; + if (!receiver->can_resolve ()) + { + bool ok + = ctx->get_tyctx ()->lookup_type (receiver->get_ref (), &r); + rust_assert (ok); + } + auto candidates - = Resolver::PathProbeImplTrait::Probe (receiver, final_segment, - trait_ref); + = Resolver::PathProbeImplTrait::Probe (r, final_segment, trait_ref); if (candidates.size () == 0) { // this means we are defaulting back to the trait_item if diff --git a/gcc/testsuite/rust/compile/issue-3915.rs b/gcc/testsuite/rust/compile/issue-3915.rs new file mode 100644 index 000000000000..7132036f92ff --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3915.rs @@ -0,0 +1,28 @@ +// { dg-options "-w" } +#[lang = "sized"] +trait Sized {} + +trait Trait { + fn do_thing(); +} + +struct MyType; + +impl Trait for MyType { + fn do_thing() {} +} + +struct Wrapper { + value: T, +} + +impl Wrapper { + fn call_it() { + T::do_thing(); + } +} + +fn main() { + let _ = Wrapper:: { value: MyType }; + Wrapper::::call_it(); +} diff --git a/gcc/testsuite/rust/execute/torture/sip-hasher.rs b/gcc/testsuite/rust/execute/torture/sip-hasher.rs new file mode 100644 index 000000000000..60826a3ed012 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/sip-hasher.rs @@ -0,0 +1,438 @@ +// { dg-skip-if "" { *-*-* } { "-m32" } { "" } } +// { dg-options "-w" } +// { dg-output "Hash: 0x63d53fd2170bbb8c\r*\n" } +#![feature(intrinsics)] +#![feature(rustc_attrs)] + +#[lang = "sized"] +trait Sized {} + +mod intrinsics { + extern "rust-intrinsic" { + pub fn wrapping_add(a: T, b: T) -> T; + pub fn rotate_left(a: T, b: T) -> T; + pub fn offset(ptr: *const T, count: isize) -> *const T; + } +} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! add_impl { + ($($t:ty)*) => ($( + impl Add for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn add(self, other: $t) -> $t { self + other } + } + + + )*) +} + +add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +impl *const T { + pub unsafe fn add(self, count: usize) -> Self { + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { self.offset(count as isize) } + } + + pub unsafe fn offset(self, count: isize) -> *const T { + // SAFETY: the caller must uphold the safety contract for `offset`. + unsafe { intrinsics::offset(self, count) } + } +} + +macro_rules! impl_uint { + ($($ty:ident = $lang:literal),*) => { + $( + #[lang = $lang] + impl $ty { + pub fn wrapping_add(self, rhs: Self) -> Self { + intrinsics::wrapping_add(self, rhs) + } + + pub fn rotate_left(self, n: u32) -> Self { + intrinsics::rotate_left(self, n as Self) + } + + pub fn to_le(self) -> Self { + #[cfg(target_endian = "little")] + { + self + } + #[cfg(not(target_endian = "little"))] + { + self.swap_bytes() + } + } + } + )* + } +} + +impl_uint!( + u8 = "u8", + u16 = "u16", + u32 = "u32", + u64 = "u64", + u128 = "u128", + usize = "usize" +); + +#[repr(C)] +pub(crate) struct SliceComponents { + pub(crate) data_address: *const (), + pub(crate) metadata: usize, +} + +#[repr(C)] +pub(crate) union SliceRepr { + pub(crate) const_ptr: *const [T], + pub(crate) mut_ptr: *mut [T], + pub(crate) components: SliceComponents, +} + +impl [T] { + pub const fn as_ptr(&self) -> *const T { + self as *const [T] as *const T + } + + pub unsafe fn get_unchecked(&self, index: usize) -> &T { + unsafe { &*self.as_ptr().add(index) } + } + + pub fn len(&self) -> usize { + unsafe { + SliceRepr { + const_ptr: self as *const _, + } + .components + .metadata + } + } +} + +trait HasherTrait { + fn write(&mut self, msg: &[u8]); + fn finish(&self) -> u64; +} + +mod cmp { + pub fn min(a: usize, b: usize) -> usize { + if a < b { + a + } else { + b + } + } +} + +struct PhantomData; + +mod mem { + extern "rust-intrinsic" { + fn transmute(_: T) -> U; + fn size_of() -> usize; + } +} + +mod ptr { + extern "rust-intrinsic" { + fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); + } +} + +#[repr(C)] +struct State { + v0: u64, + v2: u64, + v1: u64, + v3: u64, +} + +struct Hasher { + k0: u64, + k1: u64, + length: usize, // how many bytes we've processed + state: State, // hash State + tail: u64, // unprocessed bytes le + ntail: usize, // how many bytes in tail are valid + _marker: PhantomData, +} + +macro_rules! compress { + ($state:expr) => {{ + compress!($state.v0, $state.v1, $state.v2, $state.v3) + }}; + ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {{ + $v0 = $v0.wrapping_add($v1); + $v1 = $v1.rotate_left(13); + $v1 ^= $v0; + $v0 = $v0.rotate_left(32); + $v2 = $v2.wrapping_add($v3); + $v3 = $v3.rotate_left(16); + $v3 ^= $v2; + $v0 = $v0.wrapping_add($v3); + $v3 = $v3.rotate_left(21); + $v3 ^= $v0; + $v2 = $v2.wrapping_add($v1); + $v1 = $v1.rotate_left(17); + $v1 ^= $v2; + $v2 = $v2.rotate_left(32); + }}; +} + +#[doc(hidden)] +trait Sip { + fn c_rounds(_: &mut State); + fn d_rounds(_: &mut State); +} + +struct Sip13Rounds; + +impl Sip for Sip13Rounds { + #[inline] + fn c_rounds(state: &mut State) { + compress!(state); + } + + #[inline] + fn d_rounds(state: &mut State) { + compress!(state); + compress!(state); + compress!(state); + } +} + +struct Sip24Rounds; + +impl Sip for Sip24Rounds { + #[inline] + fn c_rounds(state: &mut State) { + compress!(state); + compress!(state); + } + + #[inline] + fn d_rounds(state: &mut State) { + compress!(state); + compress!(state); + compress!(state); + compress!(state); + } +} + +pub struct SipHasher13 { + hasher: Hasher, +} + +struct SipHasher24 { + hasher: Hasher, +} + +pub struct SipHasher(SipHasher24); + +macro_rules! load_int_le { + ($buf:expr, $i:expr, $int_ty:ident) => {{ + let mut data = 0 as $int_ty; + ptr::copy_nonoverlapping( + $buf.as_ptr().add($i), + &mut data as *mut _ as *mut u8, + mem::size_of::<$int_ty>(), + ); + data.to_le() + }}; +} + +#[inline] +unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { + let mut i = 0; // current byte index (from LSB) in the output u64 + let mut out = 0; + if i + 3 < len { + // SAFETY: `i` cannot be greater than `len`, and the caller must guarantee + // that the index start..start+len is in bounds. + out = unsafe { load_int_le!(buf, start + i, u32) } as u64; + i += 4; + } + if i + 1 < len { + // SAFETY: same as above. + out |= (unsafe { load_int_le!(buf, start + i, u16) } as u64) << ((i * 8) as u64); + i += 2 + } + if i < len { + // SAFETY: same as above. + out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << ((i * 8) as u64); + i += 1; + } + out +} + +impl SipHasher { + #[inline] + #[must_use] + pub fn new() -> SipHasher { + SipHasher::new_with_keys(0, 0) + } + + #[inline] + #[must_use] + pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { + SipHasher(SipHasher24 { + hasher: Hasher::new_with_keys(key0, key1), + }) + } +} + +impl SipHasher13 { + #[inline] + pub fn new() -> SipHasher13 { + SipHasher13::new_with_keys(0, 0) + } + + #[inline] + pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { + SipHasher13 { + hasher: Hasher::new_with_keys(key0, key1), + } + } +} + +impl Hasher { + #[inline] + fn new_with_keys(key0: u64, key1: u64) -> Hasher { + let mut state = Hasher { + k0: key0, + k1: key1, + length: 0, + state: State { + v0: 0, + v1: 0, + v2: 0, + v3: 0, + }, + tail: 0, + ntail: 0, + _marker: PhantomData, + }; + state.reset(); + state + } + + #[inline] + fn reset(&mut self) { + self.length = 0; + self.state.v0 = self.k0 ^ 0x736f6d6570736575; + self.state.v1 = self.k1 ^ 0x646f72616e646f6d; + self.state.v2 = self.k0 ^ 0x6c7967656e657261; + self.state.v3 = self.k1 ^ 0x7465646279746573; + self.ntail = 0; + } +} + +impl HasherTrait for SipHasher { + #[inline] + fn write(&mut self, msg: &[u8]) { + self.0.hasher.write(msg) + } + + #[inline] + fn finish(&self) -> u64 { + self.0.hasher.finish() + } +} + +impl HasherTrait for SipHasher13 { + #[inline] + fn write(&mut self, msg: &[u8]) { + self.hasher.write(msg) + } + + #[inline] + fn finish(&self) -> u64 { + self.hasher.finish() + } +} + +impl HasherTrait for Hasher { + #[inline] + fn write(&mut self, msg: &[u8]) { + let length = msg.len(); + self.length += length; + + let mut needed = 0; + + if self.ntail != 0 { + needed = 8 - self.ntail; + // SAFETY: `cmp::min(length, needed)` is guaranteed to not be over `length` + self.tail |= + unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << ((8 * self.ntail) as u64); + if length < needed { + self.ntail += length; + return; + } else { + self.state.v3 ^= self.tail; + S::c_rounds(&mut self.state); + self.state.v0 ^= self.tail; + self.ntail = 0; + } + } + + // Buffered tail is now flushed, process new input. + let len = length - needed; + let left = len & 0x7; // len % 8 + + let mut i = needed; + while i < len - left { + let mi = unsafe { load_int_le!(msg, i, u64) }; + + self.state.v3 ^= mi; + S::c_rounds(&mut self.state); + self.state.v0 ^= mi; + + i += 8; + } + + self.tail = unsafe { u8to64_le(msg, i, left) }; + self.ntail = left; + } + + #[inline] + fn finish(&self) -> u64 { + let mut state = self.state; + + let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail; + + state.v3 ^= b; + S::c_rounds(&mut state); + state.v0 ^= b; + + state.v2 ^= 0xff; + S::d_rounds(&mut state); + + state.v0 ^ state.v1 ^ state.v2 ^ state.v3 + } +} + +extern "C" { + fn printf(fmt: *const u8, ...) -> i32; +} + +fn main() -> i32 { + let mut hasher = SipHasher::new_with_keys(0x0706050403020100, 0x0f0e0d0c0b0a0908); + hasher.write(b"Hello"); + let result = hasher.finish(); + + unsafe { + printf("Hash: 0x%016llx\n\0" as *const str as *const u8, result); + } + + 0 +} From 09a8d9d95da9cfdf69eb32d76874b4bff639c328 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 18 Jul 2025 21:44:09 -0400 Subject: [PATCH 155/161] Specialize ExpandVisitor::expand_macro_children gcc/rust/ChangeLog: * expand/rust-expand-visitor.cc (ExpandVisitor::expand_inner_items): Adjust call to expand_macro_children. (ExpandVisitor::expand_inner_stmts): Likewise. (ExpandVisitor::visit): Likewise. * expand/rust-expand-visitor.h (ExpandVisitor::expand_macro_children): Take a pointer to member function instead of a std::function. Signed-off-by: Owen Avery --- gcc/rust/expand/rust-expand-visitor.cc | 37 +++++++------------------- gcc/rust/expand/rust-expand-visitor.h | 6 ++--- 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index ba7bac12ddf4..69959b541c7f 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -233,10 +233,7 @@ ExpandVisitor::expand_inner_items ( } } - std::function (AST::SingleASTNode)> extractor - = [] (AST::SingleASTNode node) { return node.take_item (); }; - - expand_macro_children (items, extractor); + expand_macro_children (items, &AST::SingleASTNode::take_item); expander.pop_context (); } @@ -324,10 +321,7 @@ ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr) if (!expr.has_tail_expr ()) expr.normalize_tail_expr (); - std::function (AST::SingleASTNode)> extractor - = [] (AST::SingleASTNode node) { return node.take_stmt (); }; - - expand_macro_children (stmts, extractor); + expand_macro_children (stmts, &AST::SingleASTNode::take_stmt); expander.pop_context (); } @@ -866,12 +860,9 @@ ExpandVisitor::visit (AST::Trait &trait) expander.push_context (MacroExpander::ContextType::TRAIT); - std::function (AST::SingleASTNode)> - extractor - = [] (AST::SingleASTNode node) { return node.take_assoc_item (); }; - expand_macro_children (MacroExpander::ContextType::TRAIT, - trait.get_trait_items (), extractor); + trait.get_trait_items (), + &AST::SingleASTNode::take_assoc_item); expander.pop_context (); } @@ -894,12 +885,9 @@ ExpandVisitor::visit (AST::InherentImpl &impl) if (impl.has_where_clause ()) expand_where_clause (impl.get_where_clause ()); - std::function (AST::SingleASTNode)> - extractor - = [] (AST::SingleASTNode node) { return node.take_assoc_item (); }; - expand_macro_children (MacroExpander::ContextType::IMPL, - impl.get_impl_items (), extractor); + impl.get_impl_items (), + &AST::SingleASTNode::take_assoc_item); } void @@ -922,12 +910,9 @@ ExpandVisitor::visit (AST::TraitImpl &impl) if (impl.has_where_clause ()) expand_where_clause (impl.get_where_clause ()); - std::function (AST::SingleASTNode)> - extractor - = [] (AST::SingleASTNode node) { return node.take_assoc_item (); }; - expand_macro_children (MacroExpander::ContextType::TRAIT_IMPL, - impl.get_impl_items (), extractor); + impl.get_impl_items (), + &AST::SingleASTNode::take_assoc_item); } void @@ -944,12 +929,10 @@ void ExpandVisitor::visit (AST::ExternBlock &block) { visit_inner_attrs (block); - std::function (AST::SingleASTNode)> - extractor - = [] (AST::SingleASTNode node) { return node.take_external_item (); }; expand_macro_children (MacroExpander::ContextType::EXTERN, - block.get_extern_items (), extractor); + block.get_extern_items (), + &AST::SingleASTNode::take_external_item); } void diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h index b82040c0878a..ef78404ae6bc 100644 --- a/gcc/rust/expand/rust-expand-visitor.h +++ b/gcc/rust/expand/rust-expand-visitor.h @@ -105,7 +105,7 @@ class ExpandVisitor : public AST::DefaultASTVisitor */ template void expand_macro_children (MacroExpander::ContextType ctx, T &values, - std::function extractor) + U (AST::SingleASTNode::*extractor) (void)) { expander.push_context (ctx); @@ -121,7 +121,7 @@ class ExpandVisitor : public AST::DefaultASTVisitor */ template void expand_macro_children (T &values, - std::function extractor) + U (AST::SingleASTNode::*extractor) (void)) { for (auto it = values.begin (); it != values.end ();) { @@ -138,7 +138,7 @@ class ExpandVisitor : public AST::DefaultASTVisitor it = values.erase (it); for (auto &node : final_fragment.get_nodes ()) { - U new_node = extractor (node); + U new_node = (node.*extractor) (); if (new_node != nullptr) { it = values.insert (it, std::move (new_node)); From 5a629ea6eb85a32ab87dac581e7dc8effa2d7d81 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Wed, 2 Jul 2025 21:38:56 -0400 Subject: [PATCH 156/161] Load modules during CfgStrip phase TopLevel would ignore just-loaded modules but Early and ExpandVisitor wouldn't. The latter would produce errors when it hit attributes which should have been indirectly CfgStrip'd away. gcc/rust/ChangeLog: * expand/rust-cfg-strip.cc (CfgStrip::visit): Load unloaded modules. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Assume modules have been loaded by CfgStrip. Signed-off-by: Owen Avery --- gcc/rust/expand/rust-cfg-strip.cc | 19 +++++++++-------- .../rust-toplevel-name-resolver-2.0.cc | 21 ------------------- 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index 774e2b46b947..ac795f7259d7 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -1765,16 +1765,17 @@ CfgStrip::visit (AST::Module &module) return; } - // A loaded module might have inner attributes - if (module.get_kind () == AST::Module::ModuleKind::LOADED) + if (module.get_kind () == AST::Module::UNLOADED) { - // strip test based on inner attrs - expand_cfg_attrs (module.get_inner_attrs ()); - if (fails_cfg_with_expand (module.get_inner_attrs ())) - { - module.mark_for_strip (); - return; - } + module.load_items (); + } + + // strip test based on inner attrs + expand_cfg_attrs (module.get_inner_attrs ()); + if (fails_cfg_with_expand (module.get_inner_attrs ())) + { + module.mark_for_strip (); + return; } // strip items if required diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index a7b442d5b440..713dce6b95a9 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -101,27 +101,6 @@ TopLevel::go (AST::Crate &crate) void TopLevel::visit (AST::Module &module) { - // Parse the module's items if they haven't been expanded and the file - // should be parsed (i.e isn't hidden behind an untrue or impossible cfg - // directive - // TODO: make sure this is right - // TODO: avoid loading items if cfg attributes are present? - // might not be needed if this runs after early resolution? - // This was copied from the old early resolver method - // 'accumulate_escaped_macros' - if (module.get_kind () == AST::Module::UNLOADED) - { - module.load_items (); - - // If the module was previously unloaded, then we don't want to visit it - // this time around as the CfgStrip hasn't run on its inner items yet. - // Skip it for now, mark the visitor as dirty and try again - - dirty = true; - - return; - } - DefaultResolver::visit (module); if (Analysis::Mappings::get ().lookup_ast_module (module.get_node_id ()) From 41e2a376b310b806ed54e0e0ded46c1da98e4231 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 9 Jul 2025 15:50:01 +0200 Subject: [PATCH 157/161] mappings: Change mappings to allow other items as item containers. This is important for importing enum variants as items. gcc/rust/ChangeLog: * util/rust-hir-map.cc (Mappings::insert_ast_module): Rename to... (Mappings::insert_glob_container): ...this. (Mappings::lookup_ast_module): Rename to... (Mappings::lookup_glob_container): ...this. * util/rust-hir-map.h: Change declarations. --- gcc/rust/util/rust-hir-map.cc | 16 +++++++++------- gcc/rust/util/rust-hir-map.h | 6 +++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index eaa640c06121..4629e6a57026 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -1148,17 +1148,19 @@ Mappings::lookup_module_children (NodeId module) } void -Mappings::insert_ast_module (AST::Module *module) +Mappings::insert_glob_container (AST::Item *container) { - rust_assert (modules.find (module->get_node_id ()) == modules.end ()); - modules[module->get_node_id ()] = module; + rust_assert (glob_containers.find (container->get_node_id ()) + == glob_containers.end ()); + + glob_containers[container->get_node_id ()] = container; } -tl::optional -Mappings::lookup_ast_module (NodeId id) +tl::optional +Mappings::lookup_glob_container (NodeId id) { - auto it = modules.find (id); - if (it == modules.end ()) + auto it = glob_containers.find (id); + if (it == glob_containers.end ()) return tl::nullopt; return {it->second}; diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index b523a36eb0b4..c8fafa4a35f0 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -321,8 +321,8 @@ class Mappings void insert_visibility (NodeId id, Privacy::ModuleVisibility visibility); tl::optional lookup_visibility (NodeId id); - void insert_ast_module (AST::Module *); - tl::optional lookup_ast_module (NodeId id); + void insert_glob_container (AST::Item *); + tl::optional lookup_glob_container (NodeId id); void insert_module_child (NodeId module, NodeId child); tl::optional &> lookup_module_children (NodeId module); @@ -436,7 +436,7 @@ class Mappings std::map> module_child_map; std::map> module_child_items; std::map child_to_parent_module_map; - std::map modules; + std::map glob_containers; // AST mappings std::map ast_item_mappings; From 2dea0a9e9b72ddf2019c6a7fd8974a499fb99ecc Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 9 Jul 2025 15:52:04 +0200 Subject: [PATCH 158/161] nr2.0: Handle glob imports of enum variants. gcc/rust/ChangeLog: * resolve/rust-early-name-resolver-2.0.cc (Early::resolve_glob_import): Adapt for enums. (Early::finalize_glob_import): Likewise. * resolve/rust-early-name-resolver-2.0.h: Likewise. * resolve/rust-finalize-imports-2.0.cc (GlobbingVisitor::go): Likewise. (GlobbingVisitor::visit_module_container): New function. (GlobbingVisitor::visit_enum_container): New function. * resolve/rust-finalize-imports-2.0.h: Declare them. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Insert enums as potential containers. gcc/testsuite/ChangeLog: * rust/compile/glob_import_enum.rs: New test. --- .../resolve/rust-early-name-resolver-2.0.cc | 18 +++++++----- .../resolve/rust-early-name-resolver-2.0.h | 14 ++++----- gcc/rust/resolve/rust-finalize-imports-2.0.cc | 29 +++++++++++++++++-- gcc/rust/resolve/rust-finalize-imports-2.0.h | 7 ++++- .../rust-toplevel-name-resolver-2.0.cc | 11 +++++-- .../rust/compile/glob_import_enum.rs | 16 ++++++++++ 6 files changed, 76 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/rust/compile/glob_import_enum.rs diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index c10379a65eb4..fa746d770fba 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -17,8 +17,11 @@ // . #include "rust-early-name-resolver-2.0.h" +#include "optional.h" #include "rust-ast-full.h" #include "rust-diagnostics.h" +#include "rust-hir-map.h" +#include "rust-item.h" #include "rust-toplevel-name-resolver-2.0.h" #include "rust-attributes.h" #include "rust-finalize-imports-2.0.h" @@ -75,8 +78,9 @@ Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob) if (!resolved.has_value ()) return false; - auto result - = Analysis::Mappings::get ().lookup_ast_module (resolved->get_node_id ()); + auto result = Analysis::Mappings::get ().lookup_glob_container ( + resolved->get_node_id ()); + if (!result) return false; @@ -394,12 +398,12 @@ void Early::finalize_glob_import (NameResolutionContext &ctx, const Early::ImportPair &mapping) { - auto module = Analysis::Mappings::get ().lookup_ast_module ( - mapping.data.module ().get_node_id ()); - rust_assert (module); + auto container = Analysis::Mappings::get ().lookup_glob_container ( + mapping.data.container ().get_node_id ()); + + rust_assert (container); - GlobbingVisitor glob_visitor (ctx); - glob_visitor.go (module.value ()); + GlobbingVisitor (ctx).go (container.value ()); } void diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h index e78bec0199a8..960de0e4c791 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h @@ -83,15 +83,15 @@ class Early : public DefaultResolver return ImportData (Kind::Rebind, std::move (definitions)); } - static ImportData Glob (Rib::Definition module) + static ImportData Glob (Rib::Definition container) { - return ImportData (Kind::Glob, module); + return ImportData (Kind::Glob, container); } - Rib::Definition module () const + Rib::Definition container () const { rust_assert (kind == Kind::Glob); - return glob_module; + return glob_container; } std::vector> definitions () const @@ -107,8 +107,8 @@ class Early : public DefaultResolver : kind (kind), resolved_definitions (std::move (definitions)) {} - ImportData (Kind kind, Rib::Definition module) - : kind (kind), glob_module (module) + ImportData (Kind kind, Rib::Definition container) + : kind (kind), glob_container (container) {} // TODO: Should this be a union? @@ -117,7 +117,7 @@ class Early : public DefaultResolver std::vector> resolved_definitions; // For Glob - Rib::Definition glob_module; + Rib::Definition glob_container; }; struct ImportPair diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.cc b/gcc/rust/resolve/rust-finalize-imports-2.0.cc index b0e86512ac20..317acb0c3123 100644 --- a/gcc/rust/resolve/rust-finalize-imports-2.0.cc +++ b/gcc/rust/resolve/rust-finalize-imports-2.0.cc @@ -21,18 +21,43 @@ #include "rust-hir-map.h" #include "rust-name-resolution-context.h" #include "rust-rib.h" +#include "rust-system.h" #include "rust-toplevel-name-resolver-2.0.h" namespace Rust { namespace Resolver2_0 { void -GlobbingVisitor::go (AST::Module *module) +GlobbingVisitor::go (AST::Item *container) { - for (auto &i : module->get_items ()) + switch (container->get_item_kind ()) + { + case AST::Item::Kind::Module: + visit_module_container (static_cast (*container)); + break; + case AST::Item::Kind::Enum: + visit_enum_container (static_cast (*container)); + break; + default: + rust_unreachable (); + } +} + +void +GlobbingVisitor::visit_module_container (AST::Module &module) +{ + for (auto &i : module.get_items ()) visit (i); } +void +GlobbingVisitor::visit_enum_container (AST::Enum &item) +{ + for (auto &variant : item.get_variants ()) + ctx.insert_globbed (variant->get_identifier (), variant->get_node_id (), + Namespace::Types); +} + void GlobbingVisitor::visit (AST::Module &module) { diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.h b/gcc/rust/resolve/rust-finalize-imports-2.0.h index d587a5e5c46e..4ae1d6d4d904 100644 --- a/gcc/rust/resolve/rust-finalize-imports-2.0.h +++ b/gcc/rust/resolve/rust-finalize-imports-2.0.h @@ -18,6 +18,7 @@ #include "rust-ast.h" #include "rust-expr.h" +#include "rust-item.h" #include "rust-name-resolution-context.h" #include "rust-toplevel-name-resolver-2.0.h" #include "rust-early-name-resolver-2.0.h" @@ -32,7 +33,11 @@ class GlobbingVisitor : public AST::DefaultASTVisitor public: GlobbingVisitor (NameResolutionContext &ctx) : ctx (ctx) {} - void go (AST::Module *module); + void go (AST::Item *container); + + void visit_module_container (AST::Module &module); + void visit_enum_container (AST::Enum &item); + void visit (AST::Module &module) override; void visit (AST::MacroRulesDefinition ¯o) override; void visit (AST::Function &function) override; diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index 713dce6b95a9..0930f966e202 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -103,9 +103,9 @@ TopLevel::visit (AST::Module &module) { DefaultResolver::visit (module); - if (Analysis::Mappings::get ().lookup_ast_module (module.get_node_id ()) + if (Analysis::Mappings::get ().lookup_glob_container (module.get_node_id ()) == tl::nullopt) - Analysis::Mappings::get ().insert_ast_module (&module); + Analysis::Mappings::get ().insert_glob_container (&module); } void @@ -339,6 +339,13 @@ TopLevel::visit (AST::Enum &enum_item) Namespace::Types); DefaultResolver::visit (enum_item); + + // Since enums can be containers for imports, we need to insert them like we + // do for modules + if (Analysis::Mappings::get ().lookup_glob_container ( + enum_item.get_node_id ()) + == tl::nullopt) + Analysis::Mappings::get ().insert_glob_container (&enum_item); } void diff --git a/gcc/testsuite/rust/compile/glob_import_enum.rs b/gcc/testsuite/rust/compile/glob_import_enum.rs new file mode 100644 index 000000000000..032a1db4ea84 --- /dev/null +++ b/gcc/testsuite/rust/compile/glob_import_enum.rs @@ -0,0 +1,16 @@ +use self::Ordering::*; +use Ordering::*; + +enum Ordering { + A, + B, +} + +fn foo(_: Ordering) {} + +fn main() { + let a = A; + + foo(a); + foo(B); +} From d7f4a923917ca51303d26c0e5cfe9dd380e93cb6 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 21 Jul 2025 09:36:16 +0200 Subject: [PATCH 159/161] ast: Use AnonConst for array type sizes gcc/rust/ChangeLog: * ast/rust-expr.h: Add handling for deferred consts. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. * ast/rust-ast.cc (AnonConst::as_string): Likewise. (ArrayType::as_string): Likewise. * ast/rust-type.h (class ArrayType): Use AnonConst for sizes. * parse/rust-parse-impl.h (Parser::parse_anon_const): New function. (Parser::parse_slice_or_array_type): Call it. * parse/rust-parse.h: Declare it. --- gcc/rust/ast/rust-ast-visitor.cc | 3 ++- gcc/rust/ast/rust-ast.cc | 11 +++++++-- gcc/rust/ast/rust-expr.h | 40 +++++++++++++++++++++++++++----- gcc/rust/ast/rust-type.h | 29 +++++++++++------------ gcc/rust/parse/rust-parse-impl.h | 32 ++++++++++++++++++++++--- gcc/rust/parse/rust-parse.h | 9 +++++++ 6 files changed, 96 insertions(+), 28 deletions(-) diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index ca7b3e495d0f..32d5d32e43fe 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -464,7 +464,8 @@ DefaultASTVisitor::visit (AST::ConstBlock &expr) void DefaultASTVisitor::visit (AST::AnonConst &expr) { - visit (expr.get_inner_expr ()); + if (!expr.is_deferred ()) + visit (expr.get_inner_expr ()); } void diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 3d230ce55c32..2b7ee5cb8bf0 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -1281,7 +1281,14 @@ BlockExpr::as_string () const std::string AnonConst::as_string () const { - return "AnonConst: " + expr->as_string (); + std::string str = "AnonConst: "; + + if (kind == AnonConst::Kind::DeferredInference) + str += "_"; + else + str += expr.value ()->as_string (); + + return str; } std::string @@ -2768,7 +2775,7 @@ std::string ArrayType::as_string () const { // TODO: rewrite to work with non-linearisable types and exprs - return "[" + elem_type->as_string () + "; " + size->as_string () + "]"; + return "[" + elem_type->as_string () + "; " + size.as_string () + "]"; } std::string diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 296821131b1e..c875d6914b3d 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1,6 +1,7 @@ #ifndef RUST_AST_EXPR_H #define RUST_AST_EXPR_H +#include "optional.h" #include "rust-ast.h" #include "rust-common.h" #include "rust-path.h" @@ -2759,24 +2760,42 @@ class BlockExpr : public ExprWithBlock class AnonConst : public ExprWithBlock { public: + enum class Kind + { + Explicit, + DeferredInference, + }; + AnonConst (std::unique_ptr &&expr, location_t locus = UNKNOWN_LOCATION) - : ExprWithBlock (), locus (locus), expr (std::move (expr)) + : ExprWithBlock (), locus (locus), kind (Kind::Explicit), + expr (std::move (expr)) { - rust_assert (this->expr); + rust_assert (this->expr.value ()); } + AnonConst (location_t locus = UNKNOWN_LOCATION) + : ExprWithBlock (), locus (locus), kind (Kind::DeferredInference), + expr (tl::nullopt) + {} + AnonConst (const AnonConst &other) { node_id = other.node_id; locus = other.locus; - expr = other.expr->clone_expr (); + kind = other.kind; + + if (other.expr) + expr = other.expr.value ()->clone_expr (); } AnonConst operator= (const AnonConst &other) { node_id = other.node_id; locus = other.locus; - expr = other.expr->clone_expr (); + kind = other.kind; + + if (other.expr) + expr = other.expr.value ()->clone_expr (); return *this; } @@ -2786,7 +2805,13 @@ class AnonConst : public ExprWithBlock Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstExpr; } location_t get_locus () const override { return locus; } - Expr &get_inner_expr () { return *expr; } + + Expr &get_inner_expr () + { + rust_assert (expr.has_value ()); + return *expr.value (); + } + NodeId get_node_id () const override { return node_id; } /* FIXME: AnonConst are always "internal" and should not have outer attributes @@ -2807,9 +2832,12 @@ class AnonConst : public ExprWithBlock void accept_vis (ASTVisitor &vis) override; + bool is_deferred () const { return kind == Kind::DeferredInference; } + private: location_t locus; - std::unique_ptr expr; + Kind kind; + tl::optional> expr; AnonConst *clone_expr_with_block_impl () const override { diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index abbfd36a6f57..2a3496b11c62 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -21,6 +21,7 @@ #include "optional.h" #include "rust-ast.h" +#include "rust-expr.h" #include "rust-path.h" namespace Rust { @@ -678,27 +679,26 @@ class ReferenceType : public TypeNoBounds class ArrayType : public TypeNoBounds { std::unique_ptr elem_type; - std::unique_ptr size; + AnonConst size; location_t locus; public: // Constructor requires pointers for polymorphism - ArrayType (std::unique_ptr type, std::unique_ptr array_size, - location_t locus) + ArrayType (std::unique_ptr type, AnonConst array_size, location_t locus) : elem_type (std::move (type)), size (std::move (array_size)), locus (locus) {} // Copy constructor requires deep copies of both unique pointers ArrayType (ArrayType const &other) - : elem_type (other.elem_type->clone_type ()), - size (other.size->clone_expr ()), locus (other.locus) + : elem_type (other.elem_type->clone_type ()), size (other.size), + locus (other.locus) {} // Overload assignment operator to deep copy pointers ArrayType &operator= (ArrayType const &other) { elem_type = other.elem_type->clone_type (); - size = other.size->clone_expr (); + size = other.size; locus = other.locus; return *this; } @@ -721,17 +721,15 @@ class ArrayType : public TypeNoBounds } // TODO: would a "vis_expr" be better? - Expr &get_size_expr () + AnonConst &get_size_expr () { - rust_assert (size != nullptr); - return *size; + // rust_assert (size != nullptr); + + return size; } std::unique_ptr &get_element_type () { return elem_type; } - // Additional getter for direct access to the size expr unique_ptr - std::unique_ptr &get_size_ptr () { return size; } - protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -741,10 +739,9 @@ class ArrayType : public TypeNoBounds } ArrayType *reconstruct_impl () const override { - return new ArrayType ( - elem_type->reconstruct (), - size->clone_expr () /* FIXME: This should be `reconstruct_expr()` */, - locus); + return new ArrayType (elem_type->reconstruct (), + size /* FIXME: This should be `reconstruct_expr()` */, + locus); } }; diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 8233af2b0a32..6d996ca60263 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -22,10 +22,13 @@ /* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h * This is also the reason why there are no include guards. */ +#include "expected.h" +#include "rust-ast.h" #include "rust-common.h" #include "rust-expr.h" #include "rust-item.h" #include "rust-common.h" +#include "rust-parse.h" #include "rust-token.h" #define INCLUDE_ALGORITHM #include "rust-diagnostics.h" @@ -7272,6 +7275,27 @@ Parser::parse_block_expr ( std::move (label), locus, end_locus)); } +/* Parse an anonymous const expression. This can be a regular const expression + * or an underscore for deferred const inference */ +template +tl::expected +Parser::parse_anon_const () +{ + auto current = lexer.peek_token (); + auto locus = current->get_locus (); + + // Special case deferred inference constants + if (maybe_skip_token (UNDERSCORE)) + return AST::AnonConst (locus); + + auto expr = parse_expr (); + + if (!expr) + return tl::make_unexpected (AnonConstError::InvalidSizeExpr); + + return AST::AnonConst (std::move (expr), locus); +} + /* Parse a "const block", a block preceded by the `const` keyword whose * statements can be const evaluated and used in constant contexts */ template @@ -9848,8 +9872,9 @@ Parser::parse_slice_or_array_type () lexer.skip_token (); // parse required array size expression - std::unique_ptr size = parse_expr (); - if (size == nullptr) + auto size = parse_anon_const (); + + if (!size) { Error error (lexer.peek_token ()->get_locus (), "failed to parse size expression in array type"); @@ -9864,7 +9889,8 @@ Parser::parse_slice_or_array_type () } return std::unique_ptr ( - new AST::ArrayType (std::move (inner_type), std::move (size), locus)); + new AST::ArrayType (std::move (inner_type), std::move (*size), + locus)); } default: // error diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 7983beb69bc2..63bbf8ebf0fb 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -34,11 +34,18 @@ class ParseLifetimeParamError class ParseLifetimeError { }; + +enum class AnonConstError +{ + InvalidSizeExpr, +}; + enum class ParseLoopLabelError { NOT_LOOP_LABEL, MISSING_COLON, }; + enum class ParseSelfError { SELF_PTR, @@ -166,6 +173,8 @@ template class Parser tl::optional = tl::nullopt, location_t pratt_parsed_loc = UNKNOWN_LOCATION); + tl::expected parse_anon_const (); + std::unique_ptr parse_const_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t loc = UNKNOWN_LOCATION); From 260e91eafed0b78edc34543b77130b91f526b10e Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 8 Jul 2025 14:34:04 +0200 Subject: [PATCH 160/161] hir: Handle deferred const inference variables gcc/rust/ChangeLog: * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Handle defered consts. * hir/tree/rust-hir-expr.cc (AnonConst::AnonConst): Likewise. (AnonConst::operator=): Likewise. * hir/tree/rust-hir-expr.h: Likewise. * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): Likewise. * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise. gcc/testsuite/ChangeLog: * rust/compile/deferred_const_inference.rs: New test. --- gcc/rust/hir/rust-ast-lower-expr.cc | 17 ++++++++---- gcc/rust/hir/tree/rust-hir-expr.cc | 22 +++++++++++---- gcc/rust/hir/tree/rust-hir-expr.h | 27 ++++++++++++++++--- gcc/rust/hir/tree/rust-hir-visitor.cc | 5 ++-- .../typecheck/rust-hir-type-check-expr.cc | 4 +++ .../rust/compile/deferred_const_inference.rs | 7 +++++ 6 files changed, 67 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/rust/compile/deferred_const_inference.rs diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc index 3f3d6007e461..96820fd8c18d 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.cc +++ b/gcc/rust/hir/rust-ast-lower-expr.cc @@ -130,17 +130,24 @@ ASTLoweringExpr::visit (AST::BlockExpr &expr) void ASTLoweringExpr::visit (AST::AnonConst &expr) { - auto inner_expr = ASTLoweringExpr::translate (expr.get_inner_expr ()); - auto &mappings = Analysis::Mappings::get (); auto crate_num = mappings.get_current_crate (); auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (), mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - translated = new HIR::AnonConst (std::move (mapping), - std::unique_ptr (inner_expr), - expr.get_locus ()); + if (expr.is_deferred ()) + { + translated = new HIR::AnonConst (std::move (mapping), expr.get_locus ()); + } + else + { + auto inner_expr = ASTLoweringExpr::translate (expr.get_inner_expr ()); + + translated = new HIR::AnonConst (std::move (mapping), + std::unique_ptr (inner_expr), + expr.get_locus ()); + } } void diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc b/gcc/rust/hir/tree/rust-hir-expr.cc index 038bfc77f94a..8544ed6708b7 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.cc +++ b/gcc/rust/hir/tree/rust-hir-expr.cc @@ -18,6 +18,7 @@ #include "rust-hir-expr.h" #include "rust-hir-map.h" +#include "optional.h" #include "rust-operators.h" #include "rust-hir-stmt.h" @@ -794,22 +795,33 @@ BlockExpr::operator= (BlockExpr const &other) AnonConst::AnonConst (Analysis::NodeMapping mappings, std::unique_ptr &&expr, location_t locus) : ExprWithBlock (std::move (mappings), {}), locus (locus), - expr (std::move (expr)) + kind (Kind::Explicit), expr (std::move (expr)) { - rust_assert (this->expr); + rust_assert (this->expr.value ()); } -AnonConst::AnonConst (const AnonConst &other) - : ExprWithBlock (other), locus (other.locus), expr (other.expr->clone_expr ()) +AnonConst::AnonConst (Analysis::NodeMapping mappings, location_t locus) + : ExprWithBlock (std::move (mappings), {}), locus (locus), + kind (Kind::DeferredInference), expr (tl::nullopt) {} +AnonConst::AnonConst (const AnonConst &other) + : ExprWithBlock (other), locus (other.locus), kind (other.kind) +{ + if (other.expr) + expr = other.expr.value ()->clone_expr (); +} + AnonConst AnonConst::operator= (const AnonConst &other) { ExprWithBlock::operator= (other); locus = other.locus; - expr = other.expr->clone_expr (); + kind = other.kind; + + if (other.expr) + expr = other.expr.value ()->clone_expr (); return *this; } diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 028455b98702..8e14a7b29125 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -1806,8 +1806,16 @@ class BlockExpr : public ExprWithBlock, public WithInnerAttrs class AnonConst : public ExprWithBlock { public: + enum class Kind + { + Explicit, + DeferredInference + }; + AnonConst (Analysis::NodeMapping mappings, std::unique_ptr &&expr, location_t locus = UNKNOWN_LOCATION); + AnonConst (Analysis::NodeMapping mappings, + location_t locus = UNKNOWN_LOCATION); AnonConst (const AnonConst &other); AnonConst operator= (const AnonConst &other); @@ -1822,12 +1830,25 @@ class AnonConst : public ExprWithBlock } location_t get_locus () const override { return locus; } - Expr &get_inner_expr () { return *expr; } - const Expr &get_inner_expr () const { return *expr; } + + Expr &get_inner_expr () + { + rust_assert (kind == Kind::Explicit); + return *expr.value (); + } + + const Expr &get_inner_expr () const + { + rust_assert (kind == Kind::Explicit); + return *expr.value (); + } + + bool is_deferred () const { return kind == Kind::DeferredInference; } private: location_t locus; - std::unique_ptr expr; + Kind kind; + tl::optional> expr; AnonConst *clone_expr_with_block_impl () const override { diff --git a/gcc/rust/hir/tree/rust-hir-visitor.cc b/gcc/rust/hir/tree/rust-hir-visitor.cc index 447606ebc8c4..ece47eba8519 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.cc +++ b/gcc/rust/hir/tree/rust-hir-visitor.cc @@ -370,7 +370,8 @@ DefaultHIRVisitor::walk (BlockExpr &expr) void DefaultHIRVisitor::walk (AnonConst &expr) { - expr.get_inner_expr ().accept_vis (*this); + if (!expr.is_deferred ()) + expr.get_inner_expr ().accept_vis (*this); } void @@ -1176,4 +1177,4 @@ DefaultHIRVisitor::walk (BareFunctionType &type) } } // namespace HIR -} // namespace Rust \ No newline at end of file +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 5db0e5690c97..9f8d31109b15 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -664,6 +664,10 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) void TypeCheckExpr::visit (HIR::AnonConst &expr) { + // FIXME: How do we typecheck a deferred inference const? + + rust_assert (!expr.is_deferred ()); + infered = TypeCheckExpr::Resolve (expr.get_inner_expr ()); } diff --git a/gcc/testsuite/rust/compile/deferred_const_inference.rs b/gcc/testsuite/rust/compile/deferred_const_inference.rs new file mode 100644 index 000000000000..25a3b17096aa --- /dev/null +++ b/gcc/testsuite/rust/compile/deferred_const_inference.rs @@ -0,0 +1,7 @@ +// { dg-additional-options "-frust-compile-until=typecheck" } + +// #![feature(generic_arg_infer)] + +fn main() { + let a: [u32; _] = [15u32]; +} From e0227b8346c30c1a5c6ff30c3dab83cc6b797423 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 21 Jul 2025 09:38:44 +0200 Subject: [PATCH 161/161] chore: ast: Fix formatting in rust-expr.h gcc/rust/ChangeLog: * ast/rust-expr.h: Fix formatting. --- gcc/rust/ast/rust-expr.h | 89 +++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index c875d6914b3d..8d650b2ded1f 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1163,11 +1163,11 @@ class ArrayElems // Value array elements class ArrayElemsValues : public ArrayElems { - std::vector > values; + std::vector> values; location_t locus; public: - ArrayElemsValues (std::vector > elems, location_t locus) + ArrayElemsValues (std::vector> elems, location_t locus) : ArrayElems (), values (std::move (elems)), locus (locus) {} @@ -1200,11 +1200,11 @@ class ArrayElemsValues : public ArrayElems void accept_vis (ASTVisitor &vis) override; // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_values () const + const std::vector> &get_values () const { return values; } - std::vector > &get_values () { return values; } + std::vector> &get_values () { return values; } size_t get_num_values () const { return values.size (); } @@ -1481,7 +1481,7 @@ class TupleExpr : public ExprWithoutBlock { std::vector outer_attrs; std::vector inner_attrs; - std::vector > tuple_elems; + std::vector> tuple_elems; location_t locus; // TODO: find another way to store this to save memory? @@ -1501,7 +1501,7 @@ class TupleExpr : public ExprWithoutBlock outer_attrs = std::move (new_attrs); } - TupleExpr (std::vector > tuple_elements, + TupleExpr (std::vector> tuple_elements, std::vector inner_attribs, std::vector outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), @@ -1552,14 +1552,11 @@ class TupleExpr : public ExprWithoutBlock bool is_marked_for_strip () const override { return marked_for_strip; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_tuple_elems () const - { - return tuple_elems; - } - std::vector > &get_tuple_elems () + const std::vector> &get_tuple_elems () const { return tuple_elems; } + std::vector> &get_tuple_elems () { return tuple_elems; } bool is_unit () const { return tuple_elems.size () == 0; } @@ -1983,7 +1980,7 @@ class StructExprFieldIndexValue : public StructExprFieldWithVal class StructExprStructFields : public StructExprStruct { // std::vector fields; - std::vector > fields; + std::vector> fields; // bool has_struct_base; StructBase struct_base; @@ -1996,8 +1993,8 @@ class StructExprStructFields : public StructExprStruct // Constructor for StructExprStructFields when no struct base is used StructExprStructFields ( PathInExpression struct_path, - std::vector > expr_fields, - location_t locus, StructBase base_struct = StructBase::error (), + std::vector> expr_fields, location_t locus, + StructBase base_struct = StructBase::error (), std::vector inner_attribs = std::vector (), std::vector outer_attribs = std::vector ()) : StructExprStruct (std::move (struct_path), std::move (inner_attribs), @@ -2034,11 +2031,11 @@ class StructExprStructFields : public StructExprStruct void accept_vis (ASTVisitor &vis) override; // TODO: this mutable getter seems really dodgy. Think up better way. - std::vector > &get_fields () + std::vector> &get_fields () { return fields; } - const std::vector > &get_fields () const + const std::vector> &get_fields () const { return fields; } @@ -2095,7 +2092,7 @@ class CallExpr : public ExprWithoutBlock { std::vector outer_attrs; std::unique_ptr function; - std::vector > params; + std::vector> params; location_t locus; public: @@ -2104,7 +2101,7 @@ class CallExpr : public ExprWithoutBlock std::string as_string () const override; CallExpr (std::unique_ptr function_expr, - std::vector > function_params, + std::vector> function_params, std::vector outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), function (std::move (function_expr)), @@ -2161,11 +2158,11 @@ class CallExpr : public ExprWithoutBlock bool is_marked_for_strip () const override { return function == nullptr; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_params () const + const std::vector> &get_params () const { return params; } - std::vector > &get_params () { return params; } + std::vector> &get_params () { return params; } // TODO: is this better? Or is a "vis_block" better? Expr &get_function_expr () @@ -2201,7 +2198,7 @@ class MethodCallExpr : public ExprWithoutBlock std::vector outer_attrs; std::unique_ptr receiver; PathExprSegment method_name; - std::vector > params; + std::vector> params; location_t locus; public: @@ -2209,7 +2206,7 @@ class MethodCallExpr : public ExprWithoutBlock MethodCallExpr (std::unique_ptr call_receiver, PathExprSegment method_path, - std::vector > method_params, + std::vector> method_params, std::vector outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), receiver (std::move (call_receiver)), @@ -2265,11 +2262,11 @@ class MethodCallExpr : public ExprWithoutBlock bool is_marked_for_strip () const override { return receiver == nullptr; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_params () const + const std::vector> &get_params () const { return params; } - std::vector > &get_params () { return params; } + std::vector> &get_params () { return params; } // TODO: is this better? Or is a "vis_block" better? Expr &get_receiver_expr () @@ -2596,7 +2593,7 @@ class BlockExpr : public ExprWithBlock { std::vector outer_attrs; std::vector inner_attrs; - std::vector > statements; + std::vector> statements; std::unique_ptr expr; tl::optional label; location_t start_locus; @@ -2612,7 +2609,7 @@ class BlockExpr : public ExprWithBlock // Returns whether the block contains a final expression. bool has_tail_expr () const { return expr != nullptr; } - BlockExpr (std::vector > block_statements, + BlockExpr (std::vector> block_statements, std::unique_ptr block_expr, std::vector inner_attribs, std::vector outer_attribs, @@ -2691,11 +2688,11 @@ class BlockExpr : public ExprWithBlock const std::vector &get_inner_attrs () const { return inner_attrs; } std::vector &get_inner_attrs () { return inner_attrs; } - const std::vector > &get_statements () const + const std::vector> &get_statements () const { return statements; } - std::vector > &get_statements () { return statements; } + std::vector> &get_statements () { return statements; } // TODO: is this better? Or is a "vis_block" better? Expr &get_tail_expr () @@ -4081,14 +4078,14 @@ class WhileLoopExpr : public BaseLoopExpr class WhileLetLoopExpr : public BaseLoopExpr { // MatchArmPatterns patterns; - std::vector > match_arm_patterns; // inlined + std::vector> match_arm_patterns; // inlined std::unique_ptr scrutinee; public: std::string as_string () const override; // Constructor with a loop label - WhileLetLoopExpr (std::vector > match_arm_patterns, + WhileLetLoopExpr (std::vector> match_arm_patterns, std::unique_ptr scrutinee, std::unique_ptr loop_block, location_t locus, tl::optional loop_label = tl::nullopt, @@ -4142,11 +4139,11 @@ class WhileLetLoopExpr : public BaseLoopExpr } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_patterns () const + const std::vector> &get_patterns () const { return match_arm_patterns; } - std::vector > &get_patterns () + std::vector> &get_patterns () { return match_arm_patterns; } @@ -4429,7 +4426,7 @@ class IfExprConseqElse : public IfExpr class IfLetExpr : public ExprWithBlock { std::vector outer_attrs; - std::vector > match_arm_patterns; // inlined + std::vector> match_arm_patterns; // inlined std::unique_ptr value; std::unique_ptr if_block; location_t locus; @@ -4437,7 +4434,7 @@ class IfLetExpr : public ExprWithBlock public: std::string as_string () const override; - IfLetExpr (std::vector > match_arm_patterns, + IfLetExpr (std::vector> match_arm_patterns, std::unique_ptr value, std::unique_ptr if_block, std::vector outer_attrs, location_t locus) : outer_attrs (std::move (outer_attrs)), @@ -4531,11 +4528,11 @@ class IfLetExpr : public ExprWithBlock } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_patterns () const + const std::vector> &get_patterns () const { return match_arm_patterns; } - std::vector > &get_patterns () + std::vector> &get_patterns () { return match_arm_patterns; } @@ -4575,11 +4572,11 @@ class IfLetExprConseqElse : public IfLetExpr public: std::string as_string () const override; - IfLetExprConseqElse ( - std::vector > match_arm_patterns, - std::unique_ptr value, std::unique_ptr if_block, - std::unique_ptr else_block, - std::vector outer_attrs, location_t locus) + IfLetExprConseqElse (std::vector> match_arm_patterns, + std::unique_ptr value, + std::unique_ptr if_block, + std::unique_ptr else_block, + std::vector outer_attrs, location_t locus) : IfLetExpr (std::move (match_arm_patterns), std::move (value), std::move (if_block), std::move (outer_attrs), locus), else_block (std::move (else_block)) @@ -4632,7 +4629,7 @@ struct MatchArm private: std::vector outer_attrs; // MatchArmPatterns patterns; - std::vector > match_arm_patterns; // inlined + std::vector> match_arm_patterns; // inlined // bool has_match_arm_guard; // inlined from MatchArmGuard @@ -4645,7 +4642,7 @@ struct MatchArm bool has_match_arm_guard () const { return guard_expr != nullptr; } // Constructor for match arm with a guard expression - MatchArm (std::vector > match_arm_patterns, + MatchArm (std::vector> match_arm_patterns, location_t locus, std::unique_ptr guard_expr = nullptr, std::vector outer_attrs = std::vector ()) : outer_attrs (std::move (outer_attrs)), @@ -4697,7 +4694,7 @@ struct MatchArm static MatchArm create_error () { location_t locus = UNDEF_LOCATION; - return MatchArm (std::vector > (), locus); + return MatchArm (std::vector> (), locus); } std::string as_string () const; @@ -4719,11 +4716,11 @@ struct MatchArm const std::vector &get_outer_attrs () const { return outer_attrs; } std::vector &get_outer_attrs () { return outer_attrs; } - const std::vector > &get_patterns () const + const std::vector> &get_patterns () const { return match_arm_patterns; } - std::vector > &get_patterns () + std::vector> &get_patterns () { return match_arm_patterns; }