aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2023-06-21 11:04:04 -0700
committerIan Lance Taylor <iant@golang.org>2023-06-21 11:04:04 -0700
commit97e31a0a2a2d2273687fcdb4e5416aab1a2186e1 (patch)
treed5c1cae4de436a0fe54a5f0a2a197d309f3d654c /gcc/rust
parent6612f4f8cb9b0d5af18ec69ad04e56debc3e6ced (diff)
parent577223aebc7acdd31e62b33c1682fe54a622ae27 (diff)
downloadgcc-97e31a0a2a2d2273687fcdb4e5416aab1a2186e1.zip
gcc-97e31a0a2a2d2273687fcdb4e5416aab1a2186e1.tar.gz
gcc-97e31a0a2a2d2273687fcdb4e5416aab1a2186e1.tar.bz2
Merge from trunk revision 577223aebc7acdd31e62b33c1682fe54a622ae27.
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/ChangeLog950
-rw-r--r--gcc/rust/Make-lang.in14
-rw-r--r--gcc/rust/ast/rust-ast-dump.cc11
-rw-r--r--gcc/rust/ast/rust-ast-dump.h1
-rw-r--r--gcc/rust/ast/rust-ast-fragment.cc44
-rw-r--r--gcc/rust/ast/rust-ast-fragment.h25
-rw-r--r--gcc/rust/ast/rust-ast-full-decls.h3
-rw-r--r--gcc/rust/ast/rust-ast-visitor.h1
-rw-r--r--gcc/rust/ast/rust-ast.cc (renamed from gcc/rust/ast/rust-ast-full-test.cc)38
-rw-r--r--gcc/rust/ast/rust-ast.h18
-rw-r--r--gcc/rust/ast/rust-expr.h148
-rw-r--r--gcc/rust/ast/rust-item.h48
-rw-r--r--gcc/rust/ast/rust-macro.cc64
-rw-r--r--gcc/rust/ast/rust-macro.h266
-rw-r--r--gcc/rust/ast/rust-pattern.h140
-rw-r--r--gcc/rust/backend/rust-compile-base.cc4
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc30
-rw-r--r--gcc/rust/backend/rust-compile-fnparam.h1
-rw-r--r--gcc/rust/backend/rust-compile-pattern.cc129
-rw-r--r--gcc/rust/backend/rust-compile-pattern.h78
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.h1
-rw-r--r--gcc/rust/backend/rust-compile-stmt.cc31
-rw-r--r--gcc/rust/backend/rust-compile-var-decl.h33
-rw-r--r--gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc4
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.cc12
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.h1
-rw-r--r--gcc/rust/checks/errors/rust-feature-gate.cc108
-rw-r--r--gcc/rust/checks/errors/rust-feature-gate.h197
-rw-r--r--gcc/rust/checks/errors/rust-feature.cc66
-rw-r--r--gcc/rust/checks/errors/rust-feature.h77
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.cc33
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.h6
-rw-r--r--gcc/rust/expand/rust-attribute-visitor.cc20
-rw-r--r--gcc/rust/expand/rust-attribute-visitor.h37
-rw-r--r--gcc/rust/expand/rust-macro-builtins.cc320
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc152
-rw-r--r--gcc/rust/expand/rust-macro-expand.h63
-rw-r--r--gcc/rust/expand/rust-macro-invoc-lexer.cc14
-rw-r--r--gcc/rust/expand/rust-macro-invoc-lexer.h3
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.cc3
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h1
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.cc2
-rw-r--r--gcc/rust/hir/rust-ast-lower-pattern.cc35
-rw-r--r--gcc/rust/hir/rust-ast-lower-pattern.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.cc2
-rw-r--r--gcc/rust/hir/rust-hir-dump.cc3
-rw-r--r--gcc/rust/hir/rust-hir-dump.h1
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h2
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-decls.h1
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h17
-rw-r--r--gcc/rust/hir/tree/rust-hir-path.h4
-rw-r--r--gcc/rust/hir/tree/rust-hir-pattern.h94
-rw-r--r--gcc/rust/hir/tree/rust-hir-visitor.h3
-rw-r--r--gcc/rust/hir/tree/rust-hir.cc (renamed from gcc/rust/hir/tree/rust-hir-full-test.cc)17
-rw-r--r--gcc/rust/hir/tree/rust-hir.h2
-rw-r--r--gcc/rust/lex/rust-lex.cc57
-rw-r--r--gcc/rust/lex/rust-lex.h28
-rw-r--r--gcc/rust/lex/rust-token.h2
-rw-r--r--gcc/rust/parse/rust-parse-impl.h397
-rw-r--r--gcc/rust/parse/rust-parse.h9
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.cc4
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.h1
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.h6
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.cc5
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver.cc136
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver.h68
-rw-r--r--gcc/rust/rust-backend.h2
-rw-r--r--gcc/rust/rust-diagnostics.cc43
-rw-r--r--gcc/rust/rust-diagnostics.h56
-rw-r--r--gcc/rust/rust-gcc.h2
-rw-r--r--gcc/rust/rust-session-manager.cc49
-rw-r--r--gcc/rust/typecheck/rust-coercion.cc6
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.cc455
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.h381
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-ref.h515
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-reference.cc475
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-reference.h268
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.cc78
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.h9
-rw-r--r--gcc/rust/typecheck/rust-hir-type-bounds.h34
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.cc88
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc18
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc36
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-pattern.cc7
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-pattern.h1
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.cc14
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h335
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.cc343
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h286
-rw-r--r--gcc/rust/typecheck/rust-tyctx.cc190
-rw-r--r--gcc/rust/typecheck/rust-type-util.cc108
-rw-r--r--gcc/rust/typecheck/rust-type-util.h38
-rw-r--r--gcc/rust/typecheck/rust-typecheck-context.cc569
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc222
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.h88
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.cc62
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h1406
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.cc1048
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.h327
-rw-r--r--gcc/rust/typecheck/rust-tyty-util.cc116
-rw-r--r--gcc/rust/typecheck/rust-tyty-util.h69
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc1812
-rw-r--r--gcc/rust/typecheck/rust-tyty.h1356
-rw-r--r--gcc/rust/typecheck/rust-unify.cc1651
-rw-r--r--gcc/rust/typecheck/rust-unify.h91
-rw-r--r--gcc/rust/util/rust-attributes.cc7
-rw-r--r--gcc/rust/util/rust-attributes.h1
-rw-r--r--gcc/rust/util/rust-buffered-queue.h (renamed from gcc/rust/rust-buffered-queue.h)0
-rw-r--r--gcc/rust/util/rust-hir-map.cc17
-rw-r--r--gcc/rust/util/rust-hir-map.h3
-rw-r--r--gcc/rust/util/rust-inline-visitor.h2
-rw-r--r--gcc/rust/util/rust-lang-item.h26
-rw-r--r--gcc/rust/util/rust-operators.h (renamed from gcc/rust/operator.h)0
114 files changed, 11138 insertions, 5667 deletions
diff --git a/gcc/rust/ChangeLog b/gcc/rust/ChangeLog
index 72c172e..25b8ddf 100644
--- a/gcc/rust/ChangeLog
+++ b/gcc/rust/ChangeLog
@@ -1,3 +1,953 @@
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h
+ (Parser::parse_stmt): Handle unsafe expression statements.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h
+ (Parser::parse_expr_stmt): Remove hypothetical unsafe + expr_stmt_without_block handling.
+
+2023-04-06 M V V S Manoj Kumar <mvvsmanojkumar@gmail.com>
+
+ * ast/rust-ast-full-decls.h (class InlineAsm):Added class declaration.
+ * ast/rust-expr.h (class InlineAsm):Added class definition.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust-diagnostics.h (struct Error): Add new Kind enum and various new
+ static constructors to allow for hints as well.
+ * rust-diagnostics.cc (Error::Error): Use new `kind` field properly.
+ * checks/errors/privacy/rust-visibility-resolver.cc
+ (VisibilityResolver::resolve_module_path): Use new Error API.
+ * expand/rust-macro-builtins.cc (MacroBuiltin::include_handler): Likewise.
+ * expand/rust-macro-expand.cc (parse_many): Likewise.
+ (transcribe_type): Likewise.
+ * parse/rust-parse-impl.h (Parser::parse_crate): Likewise.
+ * rust-session-manager.cc (Session::handle_crate_name): Likewise.
+ * ast/rust-ast.cc (Module::load_items): Likewise.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h: Keep location in TraitItem base class
+ * ast/rust-item.h (class TraitItemFunc): Use base class location instead.
+ (class TraitItemMethod): Likewise.
+ (class TraitItemConst): Likewise.
+ (class TraitItemType): Likewise.
+ * ast/rust-macro.h: Likewise.
+
+2023-04-06 SainiAditya1 <Adityasaini10012001@outlook.com>
+
+ * hir/tree/rust-hir-full-test.cc: Moved to...
+ * hir/tree/rust-hir.cc: ...here.
+ * Make-lang.in: Rename rust-hir-full-test.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-dump.cc
+ (Dump::visit): Add AltPattern visitor.
+ * ast/rust-ast-dump.h:
+ (Dump::visit): Add AltPattern visitor.
+ * ast/rust-ast-full-decls.h
+ (class AltPattern): Add declaration.
+ * ast/rust-ast-visitor.h:
+ (ASTVisitor::visit): Add AltPattern visitor.
+ * ast/rust-ast.cc
+ (AltPattern::as_string): Add definition.
+ (AltPattern::accept_vis): Add definition.
+ * ast/rust-pattern.h
+ (class AltPattern): Add declaration.
+ * checks/errors/rust-feature-gate.h:
+ (FeatureGate::visit) Add AltPattern visitor
+ * expand/rust-attribute-visitor.cc
+ (AttrVisitor::visit): Add AltPattern visitor.
+ * expand/rust-attribute-visitor.h:
+ (AttrVisitor::visit): Add AltPattern visitor.
+ * hir/rust-ast-lower-base.cc
+ (ASTLoweringBase::visit): Add AltPattern visitor.
+ * hir/rust-ast-lower-base.h:
+ (ASTLoweringBase::visit): Add AltPattern visitor.
+ * resolve/rust-ast-resolve-base.cc
+ (ResolverBase::visit): Add AltPattern visitor.
+ * resolve/rust-ast-resolve-base.h:
+ (ResolverBase::visit): Add AltPattern visitor.
+ * resolve/rust-early-name-resolver.cc
+ (EarlyNameResolver::visit): Add AltPattern visitor.
+ * resolve/rust-early-name-resolver.h:
+ (EarlyNameResolver::visit): Add AltPattern visitor.
+ * util/rust-attributes.cc
+ (AttributeChecker::visit): Add AltPattern visitor.
+ * util/rust-attributes.h:
+ (AttributeChecker::visit): Add AltPattern visitor.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-pattern.h: Fix formatting.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-macro-builtins.cc (MacroBuiltin::include_handler): Do not
+ return nullptr token in expansion of `include!()`
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * checks/errors/rust-feature-gate.h: Add trailing newline before EOF.
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-reference.cc (TraitReference::clear_associated_types): make const
+ (TraitReference::clear_associated_type_projections): new interface
+ * typecheck/rust-hir-trait-reference.h:
+ * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): refactor
+ (TraitItemReference::associated_type_reset): reset projections
+ * typecheck/rust-hir-type-bounds.h:
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): fix bounds
+ * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::TypeBoundsProbe): refactor into cc file
+ (TypeBoundsProbe::Probe): refactor
+ (TypeBoundsProbe::is_bound_satisfied_for_type): likewise
+ (TypeBoundsProbe::assemble_sized_builtin): add builtin for Sized
+ (TypeCheckBase::get_predicate_from_bound): refactor
+ (TypeBoundPredicate::lookup_associated_type): refactor
+ * typecheck/rust-tyty-subst.cc (SubstitutionRef::lookup_associated_impl)
+ (SubstitutionRef::prepare_higher_ranked_bounds): new interface to clear hanging bounds
+ (SubstitutionRef::monomorphize): refactor
+ * typecheck/rust-tyty-subst.h:
+ * typecheck/rust-tyty.cc (BaseType::get_locus): helper
+ (BaseType::satisfies_bound): ensure bounds are satisfied and assoicated types
+ (ParamType::ParamType): new field in constructor
+ (ParamType::clone): update clone
+ (ParamType::set_implicit_self_trait): new interface
+ (ParamType::is_implicit_self_trait): likewise
+ * typecheck/rust-tyty.h: cleanup
+ * util/rust-hir-map.cc (Mappings::Mappings): builtin marker
+ (Mappings::~Mappings): delete marker
+ (Mappings::lookup_builtin_marker): lookup
+ * util/rust-hir-map.h: update header
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/tree/rust-hir-item.h: implement virtual function
+ * hir/tree/rust-hir.h: add virtual function
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * Make-lang.in: add new dependancy
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::query_type): refactor
+ * typecheck/rust-hir-type-check-base.h: refactor
+ * typecheck/rust-hir-type-check.h (RUST_HIR_TYPE_CHECK): refactor
+ * typecheck/rust-type-util.cc: New file.
+ * typecheck/rust-type-util.h: New file.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-macro-builtins.cc
+ (MacroBuiltin::include_str_handler): Add check for valid UTF-8.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h
+ (Parser::parse_grouped_or_tuple_pattern): Add support for empty tuple patterns.
+
+2023-04-06 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * lex/rust-lex.h: Add file type check.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-pattern.cc
+ (CompilePatternLet::visit): Simplify WildcardPattern compilation for let statements.
+ * backend/rust-compile-var-decl.h:
+ (CompileVarDecl::visit): Remove variable declaration for WildcardPattern.
+ * resolve/rust-ast-resolve-pattern.h:
+ (PatternDeclaration::visit): Remove name resolution for WildcardPattern.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * typecheck/rust-tyty-call.cc
+ (TypeCheckCallExpr::visit): Add variadic argument type checking.
+ (TypeCheckCallExpr::visit): Fix comment spelling ("varadic").
+
+2023-04-06 mxlol233 <mxlol233@outlook.com>
+
+ * checks/errors/rust-feature-gate.cc: Add implementation for
+ `void FeatureGate::visit (AST::ExternBlock &block)`. Add `valid_feature`
+ construction process in `FeatureGate::check`.
+ * checks/errors/rust-feature-gate.h: Add declaration for
+ `void FeatureGate::visit (AST::ExternBlock &block)`. Add private
+ variable `valid_feature`.
+ * checks/errors/rust-feature.h: Change `issue` to `m_issue`.
+
+2023-04-06 Thomas Schwinge <thomas@codesourcery.com>
+
+ * ast/rust-ast-fragment.cc: Update copyright years.
+ * ast/rust-ast-fragment.h: Likewise.
+ * ast/rust-macro.cc: Likewise.
+ * checks/errors/rust-feature-gate.cc: Likewise.
+ * checks/errors/rust-feature-gate.h: Likewise.
+ * checks/errors/rust-feature.cc: Likewise.
+ * checks/errors/rust-feature.h: Likewise.
+ * hir/rust-ast-lower-expr.cc: Likewise.
+ * hir/rust-ast-lower-type.cc: Likewise.
+ * resolve/rust-early-name-resolver.cc: Likewise.
+ * resolve/rust-early-name-resolver.h: Likewise.
+ * rust-gcc.h: Likewise.
+ * typecheck/rust-hir-path-probe.cc: Likewise.
+ * typecheck/rust-hir-trait-reference.cc: Likewise.
+ * typecheck/rust-tyty-bounds.h: Likewise.
+ * typecheck/rust-tyty-subst.cc: Likewise.
+ * typecheck/rust-tyty-subst.h: Likewise.
+ * typecheck/rust-tyty-util.cc: Likewise.
+ * typecheck/rust-tyty-util.h: Likewise.
+ * typecheck/rust-unify.cc: Likewise.
+ * typecheck/rust-unify.h: Likewise.
+ * util/rust-inline-visitor.h: Likewise.
+
+2023-04-06 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * rust-session-manager.cc (Session::compile_crate): Update the
+ environment variable name.
+
+2023-04-06 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * Make-lang.in: Add `rust-hir-trait-reference.o`.
+ * typecheck/rust-hir-trait-reference.h: Remove multiple function body.
+ * typecheck/rust-hir-trait-reference.cc: Add multiple function body.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-macro-expand.cc (MacroExpander::expand_eager_invocations):
+ Add documentation explaining the algorithm.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-macro.cc: New file.
+ * Make-lang.in: Add `rust-macro.o` object
+ * ast/rust-ast-fragment.cc (Fragment::Fragment): Change API around
+ the construction of AST fragments.
+ (Fragment::operator=): Correct `Fragment::operator=` to take into
+ account the fragment tokens.
+ (Fragment::create_error): Use new constructor.
+ (Fragment::complete): Remove in favor of new constructor.
+ (Fragment::unexpanded): Remove as that Fragment type is no longer used
+ or possible.
+ (Fragment::get_tokens): Add helper to access a fragment's tokens.
+ * ast/rust-ast-fragment.h (enum class): Remove `FragmentKind::Unused`
+ * ast/rust-ast.cc (MacroInvocation::as_string): Display
+ builtin macro invocations properly.
+ * ast/rust-ast.h: Fix `DelimTokenTree` class copy constructors and
+ handling of its token vector.
+ * ast/rust-macro.h (class MacroMatcher): Format.
+ (class MetaItemSeq): Likewise.
+ (builtin_macro_from_string): Get a `BuiltinMacroKind` from a given
+ string, i.e the name of the macro (`assert!`, `cfg!` and so on).
+ * expand/rust-attribute-visitor.cc (AttrVisitor::visit): Do not expand
+ macros recursively anymore.
+ (AttrVisitor::maybe_expand_expr): Likewise.
+ (AttrVisitor::maybe_expand_type): Likewise.
+ * expand/rust-attribute-visitor.h: Likewise, and remove
+ `expand_macro_fragment_recursively` function.
+ * expand/rust-macro-builtins.cc (make_token): Add shorthand for
+ returning `std::unique_ptr<AST::Token>`s.
+ (make_macro_invocation): Add shorthand for returning fragments
+ containing builtin macro invocations.
+ (try_expand_macro_expression): Do not expand macros recursively.
+ (try_expand_single_string_literal): Likewise.
+ (try_expand_many_expr): Likewise.
+ (parse_single_string_literal): Error out more appropriately.
+ (MacroBuiltin::compile_error_handler): Add explanation for eager
+ invocation
+ (MacroBuiltin::file_handler): Return the proper tokens associated with
+ macro invocation, and builtin macros in the case of necessary eager
+ expansion.
+ (MacroBuiltin::column_handler): Likewise.
+ (MacroBuiltin::include_bytes_handler): Likewise.
+ (MacroBuiltin::include_str_handler): Likewise.
+ (MacroBuiltin::concat_handler): Likewise.
+ (MacroBuiltin::env_handler): Likewise.
+ (MacroBuiltin::cfg_handler): Likewise.
+ (MacroBuiltin::include_handler): Likewise.
+ (MacroBuiltin::line_handler): Likewise.
+ * expand/rust-macro-expand.cc (MacroExpander::expand_eager_invocations):
+ Add function to expand eager invocations *once* in the fixed point
+ pipeline.
+ (MacroExpander::expand_invoc): Call into `expand_eager_invocations` for
+ builtin macro invocations.
+ (MacroExpander::expand_crate): Use new `AttrVisitor` API.
+ (parse_many): Return tokens in `AST::Fragment`.
+ (transcribe_expression): Likewise.
+ (transcribe_type): Likewise.
+ * expand/rust-macro-expand.h (struct MacroExpander): Add `has_changed`
+ flag for fixed point checking.
+ * resolve/rust-early-name-resolver.cc (EarlyNameResolver::EarlyNameResolver):
+ Keep track of the current macro scope.
+ (EarlyNameResolver::go): Use `scoped` API.
+ (EarlyNameResolver::visit): Likewise.
+ * resolve/rust-early-name-resolver.h: Add `scoped` API.
+ * rust-session-manager.cc (Session::expansion): Perform macro expansion
+ in a fixed-point fashion.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-macro-invoc-lexer.cc (MacroInvocLexer::get_token_slice):
+ Add API to retrieve token slices when lexing macro expansions.
+ * expand/rust-macro-invoc-lexer.h: Declare `get_token_slice`.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * parse/rust-parse.h: Move `parse_macro_invocation` to public API.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-item.h (class BlockExpr): Remove forward declaration of
+ class `BlockExpr`.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * hir/tree/rust-hir-pattern.h
+ (TuplePatternItemsRanged::get_lower_patterns): Add method.
+ (TuplePatternItemsRanged::get_upper_patterns): Add method.
+ * backend/rust-compile-pattern.cc
+ (CompilePatternLet::visit): Implement TuplePattern visitor.
+ * backend/rust-compile-pattern.h
+ (CompilePatternLet::visit): Move TuplePattern visitor out of header file.
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-unify.cc (UnifyRules::go): ensure the bounds are checked
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): remove error message
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-reference.h: add const infterface
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_generic_param): make const
+ (SubstitutionRef::monomorphize): fix issue
+ * typecheck/rust-tyty-subst.h: constify interface
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * util/rust-lang-item.h:
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-subst.cc (SubstitutionArg::is_conrete): fix check
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * Make-lang.in: update names
+ * backend/rust-compile-expr.cc (CompileExpr::resolve_method_address):
+ update to use new interface
+ * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_borrowed_pointer): likewise
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::unify_site): likewise
+ * typecheck/rust-tyty.cc (BaseType::destructure): likewise
+ (InferType::unify): removed old unify interface
+ (ErrorType::unify): likewise
+ (ADTType::unify): likewise
+ (TupleType::unify): likewise
+ (FnType::unify): likewise
+ (FnPtr::unify): likewise
+ (ClosureType::unify): likewise
+ (ArrayType::unify): likewise
+ (SliceType::unify): likewise
+ (BoolType::unify): likewise
+ (IntType::unify): likewise
+ (UintType::unify): likewise
+ (FloatType::unify): likewise
+ (USizeType::unify): likewise
+ (ISizeType::unify): likewise
+ (CharType::unify): likewise
+ (ReferenceType::unify): likewise
+ (PointerType::unify): likewise
+ (ParamType::unify): likewise
+ (StrType::unify): likewise
+ (NeverType::unify): likewise
+ (PlaceholderType::unify): likewise
+ (ProjectionType::unify): likewise
+ (DynamicObjectType::unify): likewise
+ * typecheck/rust-tyty.h: update destructure interface
+ * typecheck/rust-tyty-rules.h: Removed.
+ * typecheck/rust-unify.cc: New file.
+ * typecheck/rust-unify.h: New file.
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-reference.h: change interface to return self
+ * typecheck/rust-hir-trait-resolve.cc: likewise
+ * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_segments): likewise
+ * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): remove monomorphization hack
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-subst.cc: add missing callback
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-subst.cc: update copy constructors
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-bounds.cc: refactor to take a reference
+ * typecheck/rust-tyty-subst.cc: likewise
+ (SubstitutionRef::get_substitution_arguments): likewise
+ (SubstitutionRef::infer_substitions): likewise
+ * typecheck/rust-tyty-subst.h: likewise
+ * typecheck/rust-tyty.cc (ADTType::handle_substitions): likewise
+ (TupleType::handle_substitions): likewise
+ (FnType::handle_substitions): likewise
+ (ClosureType::handle_substitions): likewise
+ (ArrayType::handle_substitions): likewise
+ (SliceType::handle_substitions): likewise
+ (ReferenceType::handle_substitions): likewise
+ (PointerType::handle_substitions): likewise
+ (ParamType::handle_substitions): likewise
+ (ProjectionType::handle_substitions): likewise
+ * typecheck/rust-tyty.h: likewise
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-ref.h: Moved to...
+ * typecheck/rust-hir-trait-reference.h: ...here.
+ * typecheck/rust-hir-trait-resolve.cc: refactor
+ * typecheck/rust-hir-trait-resolve.h (RUST_HIR_TRAIT_RESOLVE_H): likewise
+ * typecheck/rust-hir-type-check.h: likewise
+ * typecheck/rust-tyty.cc: likewise
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * Make-lang.in: update name
+ * typecheck/rust-tyctx.cc: Moved to...
+ * typecheck/rust-typecheck-context.cc: ...here.
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check.h: refactor
+ * typecheck/rust-tyctx.cc (TypeCheckContext::iterate): refactor
+ (TypeCheckContext::have_loop_context): likewise
+ (TypeCheckContext::push_new_loop_context): likewise
+ (TypeCheckContext::push_new_while_loop_context): likewise
+ (TypeCheckContext::peek_loop_context): likewise
+ (TypeCheckContext::pop_loop_context): likewise
+ (TypeCheckContext::swap_head_loop_context): likewise
+ (TypeCheckContext::insert_trait_reference): likewise
+ (TypeCheckContext::lookup_trait_reference): likewise
+ (TypeCheckContext::insert_receiver): likewise
+ (TypeCheckContext::lookup_receiver): likewise
+ (TypeCheckContext::insert_associated_type_mapping): likewise
+ (TypeCheckContext::clear_associated_type_mapping): likewise
+ (TypeCheckContext::lookup_associated_type_mapping): likewise
+ (TypeCheckContext::insert_variant_definition): likewise
+ (TypeCheckContext::lookup_variant_definition): likewise
+ (TypeCheckContext::insert_operator_overload): likewise
+ (TypeCheckContext::lookup_operator_overload): likewise
+ (TypeCheckContext::insert_unconstrained_check_marker): likewise
+ (TypeCheckContext::have_checked_for_unconstrained): likewise
+ (TypeCheckContext::insert_resolved_predicate): likewise
+ (TypeCheckContext::lookup_predicate): likewise
+ (TypeCheckContext::insert_query): likewise
+ (TypeCheckContext::query_completed): likewise
+ (TypeCheckContext::query_in_progress): likewise
+ (TypeCheckContext::insert_trait_query): likewise
+ (TypeCheckContext::trait_query_completed): likewise
+ (TypeCheckContext::trait_query_in_progress): likewise
+ (TypeCheckContextItem::Item::Item): likewise
+ (TypeCheckContextItem::TypeCheckContextItem): likewise
+ (TypeCheckContextItem::get_item): likewise
+ (TypeCheckContextItem::get_impl_item): likewise
+ (TypeCheckContextItem::get_trait_item): likewise
+ (TypeCheckContextItem::get_type): likewise
+ * typecheck/rust-tyty.cc (StructFieldType::StructFieldType): likewise
+ (StructFieldType::get_ref): likewise
+ (StructFieldType::get_name): likewise
+ (StructFieldType::get_field_type): likewise
+ (StructFieldType::set_field_type): likewise
+ (StructFieldType::is_concrete): likewise
+ (StructFieldType::debug): likewise
+ (StructFieldType::get_locus): likewise
+ (VariantDef::variant_type_string): likewise
+ (VariantDef::VariantDef): likewise
+ (VariantDef::operator=): likewise
+ (VariantDef::get_error_node): likewise
+ (VariantDef::is_error): likewise
+ (VariantDef::get_id): likewise
+ (VariantDef::get_defid): likewise
+ (VariantDef::get_variant_type): likewise
+ (VariantDef::is_data_variant): likewise
+ (VariantDef::is_dataless_variant): likewise
+ (VariantDef::get_identifier): likewise
+ (VariantDef::num_fields): likewise
+ (VariantDef::get_field_at_index): likewise
+ (VariantDef::get_fields): likewise
+ (VariantDef::lookup_field): likewise
+ (VariantDef::get_discriminant): likewise
+ (VariantDef::as_string): likewise
+ (VariantDef::is_equal): likewise
+ (VariantDef::clone): likewise
+ (VariantDef::monomorphized_clone): likewise
+ (VariantDef::get_ident): likewise
+ (TupleType::TupleType): likewise
+ (TupleType::get_unit_type): likewise
+ (TupleType::is_unit): likewise
+ (TupleType::num_fields): likewise
+ (TupleType::is_concrete): likewise
+ (TupleType::get_fields): likewise
+ (BoolType::BoolType): likewise
+ (BoolType::get_name): likewise
+ (BoolType::is_concrete): likewise
+ (IntType::IntType): likewise
+ (IntType::get_name): likewise
+ (IntType::get_int_kind): likewise
+ (IntType::is_concrete): likewise
+ (UintType::UintType): likewise
+ (UintType::get_name): likewise
+ (UintType::get_uint_kind): likewise
+ (UintType::is_concrete): likewise
+ (FloatType::FloatType): likewise
+ (FloatType::get_name): likewise
+ (FloatType::get_float_kind): likewise
+ (FloatType::is_concrete): likewise
+ (USizeType::USizeType): likewise
+ (USizeType::get_name): likewise
+ (USizeType::is_concrete): likewise
+ (ISizeType::ISizeType): likewise
+ (ISizeType::get_name): likewise
+ (ISizeType::is_concrete): likewise
+ (CharType::CharType): likewise
+ (CharType::is_concrete): likewise
+ (CharType::get_name): likewise
+ (ReferenceType::ReferenceType): likewise
+ (ReferenceType::is_concrete): likewise
+ (ReferenceType::mutability): likewise
+ (ReferenceType::is_mutable): likewise
+ (ReferenceType::is_dyn_object): likewise
+ (ReferenceType::is_dyn_slice_type): likewise
+ (ReferenceType::is_dyn_str_type): likewise
+ (PointerType::PointerType): likewise
+ (PointerType::is_concrete): likewise
+ (PointerType::mutability): likewise
+ (PointerType::is_mutable): likewise
+ (PointerType::is_const): likewise
+ (PointerType::is_dyn_object): likewise
+ (PointerType::is_dyn_slice_type): likewise
+ (PointerType::is_dyn_str_type): likewise
+ (ParamType::ParamType): likewise
+ (ParamType::get_generic_param): likewise
+ (ParamType::can_resolve): likewise
+ (ParamType::is_concrete): likewise
+ (StrType::StrType): likewise
+ (StrType::get_name): likewise
+ (StrType::is_concrete): likewise
+ (NeverType::NeverType): likewise
+ (NeverType::get_name): likewise
+ (NeverType::is_unit): likewise
+ (NeverType::is_concrete): likewise
+ (PlaceholderType::PlaceholderType): likewise
+ (PlaceholderType::get_name): likewise
+ (PlaceholderType::is_unit): likewise
+ (PlaceholderType::get_symbol): likewise
+ (PlaceholderType::is_concrete): likewise
+ (ProjectionType::is_unit): likewise
+ (ProjectionType::get_name): likewise
+ (ProjectionType::needs_generic_substitutions): likewise
+ (ProjectionType::supports_substitutions): likewise
+ (ProjectionType::has_subsititions_defined): likewise
+ (ProjectionType::get): likewise
+ (ProjectionType::is_concrete): likewise
+ (DynamicObjectType::is_concrete): likewise
+ * typecheck/rust-tyty.h: likewise
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-path-probe.cc (PathProbeCandidate::Candidate::Candidate): refactor
+ (PathProbeCandidate::PathProbeCandidate): likewise
+ (PathProbeCandidate::as_string): likewise
+ (PathProbeCandidate::is_enum_candidate): likewise
+ (PathProbeCandidate::is_impl_candidate): likewise
+ (PathProbeCandidate::is_trait_candidate): likewise
+ (PathProbeCandidate::is_full_trait_item_candidate): likewise
+ (PathProbeCandidate::get_error): likewise
+ (PathProbeCandidate::is_error): likewise
+ (PathProbeCandidate::get_defid): likewise
+ (PathProbeCandidate::operator<): likewise
+ * typecheck/rust-hir-path-probe.h (struct PathProbeCandidate): likewise
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-path-probe.cc (PathProbeType::PathProbeType): refactor
+ (PathProbeType::Probe): likewise
+ (PathProbeType::visit): likewise
+ (PathProbeType::process_enum_item_for_candiates): likewise
+ (PathProbeType::process_impl_items_for_candidates): likewise
+ (PathProbeType::is_reciever_generic): likewise
+ (PathProbeImplTrait::PathProbeImplTrait): likewise
+ (PathProbeImplTrait::Probe): likewise
+ (PathProbeImplTrait::process_trait_impl_items_for_candidates): likewise
+ * typecheck/rust-hir-path-probe.h (struct PathProbeCandidate): likewise
+ * typecheck/rust-hir-trait-resolve.cc
+ (PathProbeImplTrait::process_trait_impl_items_for_candidates): likewise
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty.cc (BaseType::BaseType): refactor
+ (BaseType::~BaseType): likewise
+ (BaseType::get_ref): likewise
+ (BaseType::set_ref): likewise
+ (BaseType::get_ty_ref): likewise
+ (BaseType::set_ty_ref): likewise
+ (BaseType::is_equal): likewise
+ (BaseType::is_unit): likewise
+ (BaseType::get_kind): likewise
+ (BaseType::get_combined_refs): likewise
+ (BaseType::append_reference): likewise
+ (BaseType::supports_substitutions): likewise
+ (BaseType::has_subsititions_defined): likewise
+ (BaseType::can_substitute): likewise
+ (BaseType::needs_generic_substitutions): likewise
+ (BaseType::contains_type_parameters): likewise
+ (BaseType::get_ident): likewise
+ (BaseType::get_locus): likewise
+ (InferType::InferType): likewise
+ (InferType::get_infer_kind): likewise
+ (InferType::get_name): likewise
+ (InferType::is_concrete): likewise
+ (ErrorType::ErrorType): likewise
+ (ErrorType::is_unit): likewise
+ (ErrorType::is_concrete): likewise
+ (ErrorType::get_name): likewise
+ (ErrorType::monomorphized_clone): likewise
+ * typecheck/rust-tyty.h (class SubstitutionArgumentMappings): likewise
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-substitution-mapper.cc (SubstMapper::SubstMapper): refactor
+ (SubstMapper::Resolve): likewise
+ (SubstMapper::InferSubst): likewise
+ (SubstMapper::have_generic_args): likewise
+ (SubstMapper::visit): likewise
+ (SubstMapperInternal::visit): likewise
+ (SubstMapperFromExisting::SubstMapperFromExisting): likewise
+ (SubstMapperFromExisting::Resolve): likewise
+ (SubstMapperFromExisting::visit): likewise
+ (GetUsedSubstArgs::GetUsedSubstArgs): likewise
+ (GetUsedSubstArgs::From): likewise
+ (GetUsedSubstArgs::visit): likewise
+ * typecheck/rust-substitution-mapper.h: refactor
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_generic_param): likewise
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * Make-lang.in: update the makefile
+ * typecheck/rust-tyty.cc (SubstitutionParamMapping::need_substitution): likewise
+ (SubstitutionParamMapping::override_context): likewise
+ (SubstitutionRef::get_mappings_from_generic_args): likewise
+ (SubstitutionRef::infer_substitions): likewise
+ (SubstitutionRef::are_mappings_bound): likewise
+ (SubstitutionRef::solve_missing_mappings_from_this): likewise
+ (SubstitutionRef::monomorphize): likewise
+ * typecheck/rust-tyty.h (class SubstitutionParamMapping): likewise
+ (class SubstitutionArg): likewise
+ (std::function<void): likewise
+ (class SubstitutionArgumentMappings): likewise
+ (class SubstitutionRef): likewise
+ * typecheck/rust-tyty-subst.cc: New file.
+ * typecheck/rust-tyty-subst.h: New file.
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * Make-lang.in: update makefile
+ * typecheck/rust-tyty.cc (TyVar::TyVar): move to new file
+ (TyVar::get_tyty): likewise
+ (TyVar::get_implicit_infer_var): likewise
+ (TyVar::subst_covariant_var): likewise
+ (TyVar::clone): likewise
+ (TyVar::monomorphized_clone): likewise
+ (TyWithLocation::TyWithLocation): likewise
+ * typecheck/rust-tyty.h (class BaseType): cleanup
+ (class TypeBoundPredicate): move to its own file
+ (class TypeBoundPredicateItem): likewise
+ (class TypeBoundsMappings): likewise
+ (class TyVar): likewise
+ (class TyWithLocation): likewise
+ * typecheck/rust-tyty-bounds.h: New file.
+ * typecheck/rust-tyty-util.cc: New file.
+ * typecheck/rust-tyty-util.h: New file.
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-bounds.cc (TypeBoundPredicateItem::error): refactor
+ (TypeBoundPredicateItem::is_error): likewise
+ (TypeBoundPredicateItem::get_parent): likewise
+ * typecheck/rust-tyty.h: Move the implementation for the above
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Removed copy-pasted comment.
+
+2023-04-06 mxlol233 <mxlol233@outlook.com>
+
+ * Make-lang.in: Add object files: `rust-feature.o` and `rust-feature-gate.o`
+ * checks/errors/rust-feature-gate.cc: New file.
+ * checks/errors/rust-feature-gate.h: New file.
+ * checks/errors/rust-feature.cc: New file.
+ * checks/errors/rust-feature.h: New file.
+ * rust-session-manager.cc: Add FeatureGate check.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_closure_expr): Advance tokens
+ properly when parsing closure param list.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_generic_arg): Handle type
+ paths and nested generics properly.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-pattern.h:
+ (ReferencePattern::is_double_reference): Add method.
+ (ReferencePattern::get_is_mut): Add method.
+ * hir/rust-ast-lower-pattern.cc
+ (ASTLoweringPattern::visit): Add ReferencePattern visitor.
+ * hir/rust-ast-lower-pattern.h:
+ (ASTLoweringPattern::visit): Add ReferencePattern visitor.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * hir/tree/rust-hir-pattern.h
+ (class ReferencePattern): Remove has_two_amps field.
+ * hir/tree/rust-hir-full-test.cc
+ (ReferencePattern::as_string): Remove usage of ReferencePattern::has_two_amps.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-fnparam.h
+ (CompileFnParam::visit): Remove HIR::GroupedPattern visitor.
+ * backend/rust-compile-pattern.cc
+ (CompilePatternCaseLabelExpr::visit): Remove HIR::GroupedPattern visitor.
+ (CompilePatternBindings::visit): Remove HIR::GroupedPattern visitor.
+ * backend/rust-compile-pattern.h
+ (CompilePatternCaseLabelExpr::visit): Remove HIR::GroupedPattern visitor.
+ (CompilePatternBindings::visit): Remove HIR::GroupedPattern visitor.
+ (CompilePatternLet::visit): Remove HIR::GroupedPattern visitor.
+ * backend/rust-compile-resolve-path.h
+ (ResolvePathRef::visit): Remove HIR::GroupedPattern visitor.
+ * backend/rust-compile-var-decl.h
+ (CompileVarDecl::visit): Remove HIR::GroupedPattern visitor.
+ * checks/errors/rust-const-checker.cc
+ (ConstChecker::visit): Remove HIR::GroupedPattern visitor.
+ * checks/errors/rust-const-checker.h
+ (ConstChecker::visit): Remove HIR::GroupedPattern visitor.
+ * checks/errors/rust-unsafe-checker.cc
+ (UnsafeChecker::visit): Remove HIR::GroupedPattern visitor.
+ * checks/errors/rust-unsafe-checker.h
+ (UnsafeChecker::visit): Remove HIR::GroupedPattern visitor.
+ * hir/rust-hir-dump.cc (Dump::visit): Remove HIR::GroupedPattern visitor.
+ * hir/rust-hir-dump.h (Dump::visit): Remove HIR::GroupedPattern visitor.
+ * hir/tree/rust-hir-full-decls.h (class GroupedPattern): Remove class.
+ * hir/tree/rust-hir-full-test.cc (GroupedPattern::accept_vis): Remove method.
+ * hir/tree/rust-hir-pattern.h (class GroupedPattern): Remove class.
+ * hir/tree/rust-hir-visitor.h
+ (HIRFullVisitor::visit): Remove HIR::GroupedPattern visitor.
+ (HIRFullVisitorBase::visit): Remove HIR::GroupedPattern visitor.
+ (HIRPatternVisitor::visit): Remove HIR::GroupedPattern visitor.
+ * typecheck/rust-hir-type-check-pattern.cc
+ (TypeCheckPattern::visit): Remove HIR::GroupedPattern visitor.
+ * typecheck/rust-hir-type-check-pattern.h
+ (TypeCheckPattern::visit): Remove HIR::GroupedPattern visitor.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * hir/rust-ast-lower-pattern.cc
+ (ASTLoweringPattern::visit): Lower AST::GroupedPattern to its inner pattern.
+
+2023-04-06 MAHAD <mahadtxt@gmail.com>
+
+ * rust-buffered-queue.h: Moved to...
+ * util/rust-buffered-queue.h: ...here.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_type): Handle double ampersan
+ properly
+ (Parser::parse_reference_type): Call into `parse_reference_type_inner`
+ and wrap double reference types in another `AST::ReferenceType` node
+ (Parser::parse_reference_type_inner): Add parsing implementation
+ which does not care about the leading token (& or &&)
+ (Parser::parse_type_no_bounds): Handle double ampersand properly
+ * parse/rust-parse.h: Declare `parse_reference_type_inner`
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-pattern.cc (CompilePatternLet::visit): New function.
+ * backend/rust-compile-stmt.cc (CompileStmt::visit): Likewise.
+ * backend/rust-compile-pattern.h (class CompilePatternLet): New visitor.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-macro.h (enum class): Add `BuiltinMacro` enum class.
+ * expand/rust-attribute-visitor.cc (AttrVisitor::visit): Mention
+ switching on `macro.kind` once builtin macro invocations are properly
+ handled.
+ * parse/rust-parse-impl.h (Parser::parse_macro_invocation): Switch to new MacroInvocation
+ API.
+ (Parser::parse_type): Likewise.
+ (Parser::parse_type_no_bounds): Likewise.
+
+2023-04-06 Abdul Rafey <abdulrafeyq@gmail.com>
+
+ * ast/rust-ast-dump.cc (Dump::visit): removed extra indentations in trait ast dump
+
+2023-04-06 Abdul Rafey <abdulrafeyq@gmail.com>
+
+ * parse/rust-parse-impl.h (Parser::null_denotation): Add proper error
+ when seeing wildcard var on right side of assignment.
+
+2023-04-06 Abdul Rafey <abdulrafeyq@gmail.com>
+
+ * ast/rust-ast.cc: Fix include list.
+ * ast/rust-expr.h: Likewise.
+ * hir/tree/rust-hir-expr.h: Likewise.
+ * rust-backend.h: Likewise.
+ * util/rust-lang-item.h: Likewise.
+ * operator.h: Moved to...
+ * util/rust-operators.h: ...here.
+
+2023-04-06 Parthib <parthibdutta02@gmail.com>
+
+ * Make-lang.in: Rename object file.
+ * ast/rust-ast-full-test.cc: Moved to...
+ * ast/rust-ast.cc: ...here.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-pattern.cc (CompilePatternCaseLabelExpr::visit): Add proper
+ visitor.
+ (CompilePatternBindings::visit): Likewise.
+ * backend/rust-compile-pattern.h: Declare them.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): Add proper
+ visitor.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * hir/tree/rust-hir-pattern.h: Add get_item method.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit): Add proper visitor.
+ * hir/rust-ast-lower-pattern.h: Declare it.
+
+2023-04-06 Lyra <teromene@teromene.fr>
+
+ * expand/rust-macro-expand.cc (transcribe_expression): Fix ICE when expanding
+ empty macros.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-ast-resolve-pattern.h: Support GroupedPattern properly.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-base.cc (HIRCompileBase::compile_locals_for_block):
+ Allow patterns to declare zero or multiple variables.
+ * backend/rust-compile-var-decl.h: Change function declaration.
+
+2023-04-06 mxlol233 <mxlol233@outlook.com>
+
+ * lex/rust-lex.cc (Lexer::build_token): Make location enclose entire token.
+ (Lexer::parse_byte_char): Likewise.
+ (Lexer::parse_byte_string): Likewise.
+ (Lexer::parse_raw_byte_string): Likewise.
+ (Lexer::parse_raw_identifier): Likewise.
+ (Lexer::parse_string): Likewise.
+ (Lexer::parse_identifier_or_keyword): Likewise.
+ (Lexer::parse_raw_string): Likewise.
+ (Lexer::parse_non_decimal_int_literal): Likewise.
+ (Lexer::parse_decimal_int_or_float): Likewise.
+ (Lexer::parse_char_or_lifetime): Likewise.
+
+2023-04-06 mxlol233 <mxlol233@outlook.com>
+
+ * ast/rust-ast.h: Add get_locus method.
+ * ast/rust-expr.h: Likewise.
+ * ast/rust-macro.h: Likewise.
+
+2023-04-06 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * typecheck/rust-hir-type-check-stmt.cc (TypeCheckStmt::visit): Cleanup LetStmt
+ type checking.
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/tree/rust-hir-path.h: Add const get_identifier and get_type method.
+ * typecheck/rust-hir-path-probe.h: Use new SubstitutionArgumentMappings constructor.
+ * typecheck/rust-hir-trait-resolve.cc: Likewise.
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
+ * typecheck/rust-tyty-bounds.cc (TypeCheckBase::get_predicate_from_bound):
+ Do not assert failure on size mismatch anymore.
+ (TypeBoundPredicate::TypeBoundPredicate): Use new SubstitutionArgumentMappings constructor.
+ (TypeBoundPredicate::operator=): Likewise.
+ (TypeBoundPredicate::apply_generic_arguments): Likewise.
+ (TypeBoundPredicateItem::get_tyty_for_receiver): Likewise.
+ (TypeBoundPredicate::get_num_associated_bindings): Likewise.
+ (TypeBoundPredicate::lookup_associated_type): Fix implementation for new system.
+ (TypeBoundPredicate::get_associated_type_items): Likewise.
+ * typecheck/rust-tyty.cc (SubstitutionRef::get_mappings_from_generic_args): Add new
+ behavior.
+ (SubstitutionRef::infer_substitions): Use new constructor and add comment.
+ (SubstitutionRef::solve_missing_mappings_from_this): Use new constructor.
+ * typecheck/rust-tyty.h: Define new constructors.
+
+2023-04-06 Philip Herron <herron.philip@googlemail.com>
+
+ * resolve/rust-ast-resolve-type.cc (ResolveGenericArgs::go): Add name resolution to
+ Trait items.
+
+2023-04-06 Raiki Tamura <tamaron1203@gmail.com>
+
+ * ast/rust-ast-full-decls.h (class MacroItem): Remove forward declaration.
+ * ast/rust-ast-full-test.cc (MacroRulesDefinition):
+ Rework MacroRulesDefinition class
+ * ast/rust-ast.h (class MacroItem): Remove abstract class.
+ * ast/rust-item.h (class MacroItem): Remove forward declaration.
+ * ast/rust-macro.h (class MacroItem): Likewise.
+ (class MacroRulesDefinition): Add MacroKind enum.
+ (class MacroInvocation): Fix inheritance.
+ * lex/rust-token.h: Token "macro" is now used.
+ * parse/rust-parse-impl.h (Parser::parse_item): Add handling for MACRO.
+ (Parser::parse_vis_item): Call into parse_decl_macro_def.
+ (Parser::parse_macro_item): Delete function.
+ (Parser::parse_macro_rules_def): Return MBE macros only.
+ (Parser::parse_decl_macro_def): New function.
+ (Parser::parse_stmt): Handle MACRO token.
+ (Parser::parse_stmt_or_expr_without_block): Call into parse_macro_rules_def.
+ * parse/rust-parse.h: Declare new function.
+
+2023-04-06 mxlol233 <mxlol233@outlook.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_generic_arg): Add proper bound parsing.
+
+2023-04-06 Dave <dme2223@gmail.com>
+
+ * checks/errors/rust-const-checker.cc (ConstChecker::visit): Use StackedContext
+ class.
+
+2023-04-06 Prajwal S N <prajwalnadig21@gmail.com>
+
+ * checks/errors/rust-unsafe-checker.cc (check_target_attr): New function.
+ (UnsafeChecker::check_function_attr): Call into `check_target_attr`.
+ (UnsafeChecker::visit): Check for target_feature attributes.
+ * checks/errors/rust-unsafe-checker.h: Add declarations.
+ * util/rust-attributes.cc: Add attribute.
+
+2023-04-06 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust-session-manager.cc (Session::compile_crate): Fix typo.
+
2023-02-22 Thomas Schwinge <thomas@codesourcery.com>
* rust-lang.cc (grs_langhook_type_for_mode): Also consider all
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index dddc70a..3ed0c09 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -73,7 +73,7 @@ GRS_OBJS = \
rust/rust-lex.o \
rust/rust-cfg-parser.o \
rust/rust-parse.o \
- rust/rust-ast-full-test.o \
+ rust/rust-ast.o \
rust/rust-ast-fragment.o \
rust/rust-ast-dump.o \
rust/rust-hir-dump.o \
@@ -86,10 +86,11 @@ GRS_OBJS = \
rust/rust-macro-invoc-lexer.o \
rust/rust-macro-substitute-ctx.o \
rust/rust-macro-builtins.o \
- rust/rust-hir-full-test.o \
+ rust/rust-hir.o \
rust/rust-hir-map.o \
rust/rust-attributes.o \
rust/rust-abi.o \
+ rust/rust-macro.o \
rust/rust-ast-lower.o \
rust/rust-ast-lower-base.o \
rust/rust-ast-lower-pattern.o \
@@ -115,11 +116,14 @@ GRS_OBJS = \
rust/rust-pub-restricted-visitor.o \
rust/rust-privacy-reporter.o \
rust/rust-tyty.o \
+ rust/rust-tyty-util.o \
rust/rust-tyty-call.o \
- rust/rust-tyctx.o \
+ rust/rust-tyty-subst.o \
+ rust/rust-typecheck-context.o \
rust/rust-tyty-bounds.o \
rust/rust-hir-type-check-util.o \
rust/rust-hir-trait-resolve.o \
+ rust/rust-hir-trait-reference.o \
rust/rust-hir-type-check-item.o \
rust/rust-hir-type-check-type.o \
rust/rust-hir-type-check-struct.o \
@@ -130,8 +134,10 @@ GRS_OBJS = \
rust/rust-hir-type-check-implitem.o \
rust/rust-hir-dot-operator.o \
rust/rust-hir-path-probe.o \
+ rust/rust-type-util.o \
rust/rust-coercion.o \
rust/rust-casts.o \
+ rust/rust-unify.o \
rust/rust-hir-type-check-base.o \
rust/rust-autoderef.o \
rust/rust-substitution-mapper.o \
@@ -161,6 +167,8 @@ GRS_OBJS = \
rust/rust-import-archive.o \
rust/rust-extern-crate.o \
rust/rust-builtins.o \
+ rust/rust-feature.o \
+ rust/rust-feature-gate.o \
$(END)
# removed object files from here
diff --git a/gcc/rust/ast/rust-ast-dump.cc b/gcc/rust/ast/rust-ast-dump.cc
index 77e04b9..10fb313 100644
--- a/gcc/rust/ast/rust-ast-dump.cc
+++ b/gcc/rust/ast/rust-ast-dump.cc
@@ -1072,8 +1072,6 @@ Dump::visit (TypeBoundWhereClauseItem &item)
void
Dump::visit (Method &method)
{
- // FIXME: Do we really need to dump the indentation here?
- stream << indentation;
visit (method.get_visibility ());
stream << "fn " << method.get_method_name () << '(';
@@ -1326,7 +1324,7 @@ void
Dump::visit (TraitItemFunc &item)
{
auto func = item.get_trait_function_decl ();
- stream << indentation << "fn " << func.get_identifier () << '(';
+ stream << "fn " << func.get_identifier () << '(';
visit_items_joined_by_separator (func.get_function_params ());
@@ -1340,9 +1338,6 @@ Dump::visit (TraitItemMethod &item)
{
auto method = item.get_trait_method_decl ();
- // FIXME: Do we really need to dump the indentation here?
- stream << indentation;
-
// FIXME: Can we have visibility here?
// emit_visibility (method.get_visibility ());
stream << "fn " << method.get_identifier () << '(';
@@ -1683,6 +1678,10 @@ void
Dump::visit (SlicePattern &)
{}
+void
+Dump::visit (AltPattern &)
+{}
+
// rust-stmt.h
void
Dump::visit (EmptyStmt &)
diff --git a/gcc/rust/ast/rust-ast-dump.h b/gcc/rust/ast/rust-ast-dump.h
index 56918f5..dfe6db0 100644
--- a/gcc/rust/ast/rust-ast-dump.h
+++ b/gcc/rust/ast/rust-ast-dump.h
@@ -293,6 +293,7 @@ private:
void visit (TuplePattern &pattern);
void visit (GroupedPattern &pattern);
void visit (SlicePattern &pattern);
+ void visit (AltPattern &pattern);
// rust-stmt.h
void visit (EmptyStmt &stmt);
diff --git a/gcc/rust/ast/rust-ast-fragment.cc b/gcc/rust/ast/rust-ast-fragment.cc
index c491609..a9dc474 100644
--- a/gcc/rust/ast/rust-ast-fragment.cc
+++ b/gcc/rust/ast/rust-ast-fragment.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -21,8 +21,9 @@
namespace Rust {
namespace AST {
-Fragment::Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes)
- : kind (kind), nodes (std::move (nodes))
+Fragment::Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes,
+ std::vector<std::unique_ptr<AST::Token>> tokens)
+ : kind (kind), nodes (std::move (nodes)), tokens (std::move (tokens))
{}
Fragment::Fragment (Fragment const &other) : kind (other.get_kind ())
@@ -33,13 +34,17 @@ Fragment::Fragment (Fragment const &other) : kind (other.get_kind ())
Fragment &
Fragment::operator= (Fragment const &other)
{
+ kind = other.get_kind ();
+
nodes.clear ();
nodes.reserve (other.nodes.size ());
- kind = other.get_kind ();
for (auto &n : other.nodes)
- {
- nodes.push_back (n);
- }
+ nodes.push_back (n);
+
+ tokens.clear ();
+ tokens.reserve (other.tokens.size ());
+ for (auto &t : other.tokens)
+ tokens.emplace_back (t->clone_token ());
return *this;
}
@@ -47,19 +52,20 @@ Fragment::operator= (Fragment const &other)
Fragment
Fragment::create_error ()
{
- return Fragment (FragmentKind::Error, {});
+ return Fragment (FragmentKind::Error, {}, {});
}
-Fragment
-Fragment::complete (std::vector<AST::SingleASTNode> nodes)
-{
- return Fragment (FragmentKind::Complete, std::move (nodes));
-}
+Fragment::Fragment (std::vector<AST::SingleASTNode> nodes,
+ std::vector<std::unique_ptr<AST::Token>> tokens)
+ : kind (FragmentKind::Complete), nodes (std::move (nodes)),
+ tokens (std::move (tokens))
+{}
-Fragment
-Fragment::unexpanded ()
+Fragment::Fragment (std::vector<AST::SingleASTNode> nodes,
+ std::unique_ptr<AST::Token> token)
+ : kind (FragmentKind::Complete), nodes (std::move (nodes))
{
- return Fragment (FragmentKind::Unexpanded, {});
+ tokens.emplace_back (std::move (token));
}
std::vector<SingleASTNode> &
@@ -68,6 +74,12 @@ Fragment::get_nodes ()
return nodes;
}
+std::vector<std::unique_ptr<AST::Token>> &
+Fragment::get_tokens ()
+{
+ return tokens;
+}
+
FragmentKind
Fragment::get_kind () const
{
diff --git a/gcc/rust/ast/rust-ast-fragment.h b/gcc/rust/ast/rust-ast-fragment.h
index 3ef4ba1..41f5a28 100644
--- a/gcc/rust/ast/rust-ast-fragment.h
+++ b/gcc/rust/ast/rust-ast-fragment.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -28,11 +28,6 @@ namespace AST {
enum class FragmentKind
{
/**
- * If an AST Fragment still contains unexpanded tokens - this should only be
- * used in the case of builtin macros which need to be expanded eagerly.
- */
- Unexpanded,
- /**
* A completely expanded AST Fragment. This signifies that all
* `SingleASTNode`s in the `nodes` vector are valid.
*
@@ -68,15 +63,18 @@ public:
/**
* Create a complete AST fragment
*/
- static Fragment complete (std::vector<AST::SingleASTNode> nodes);
+ Fragment (std::vector<AST::SingleASTNode> nodes,
+ std::vector<std::unique_ptr<AST::Token>> tokens);
/**
- * Create a fragment which contains unexpanded nodes
+ * Create a complete AST fragment made of a single token
*/
- static Fragment unexpanded ();
+ Fragment (std::vector<AST::SingleASTNode> nodes,
+ std::unique_ptr<AST::Token> tok);
FragmentKind get_kind () const;
std::vector<SingleASTNode> &get_nodes ();
+ std::vector<std::unique_ptr<AST::Token>> &get_tokens ();
bool is_error () const;
bool should_expand () const;
@@ -90,7 +88,8 @@ public:
void accept_vis (ASTVisitor &vis);
private:
- Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes);
+ Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes,
+ std::vector<std::unique_ptr<AST::Token>> tokens);
FragmentKind kind;
@@ -105,6 +104,12 @@ private:
std::vector<SingleASTNode> nodes;
/**
+ * The tokens associated with an AST fragment. This vector represents the
+ * actual tokens of the various nodes that are part of the fragment.
+ */
+ std::vector<std::unique_ptr<AST::Token>> tokens;
+
+ /**
* We need to make a special case for Expression and Type fragments as only
* one Node will be extracted from the `nodes` vector
*/
diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
index 136a25a..64341d3 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -51,7 +51,6 @@ class Lifetime;
class GenericParam;
class LifetimeParam;
class ConstGenericParam;
-class MacroItem;
class TraitItem;
class InherentImplItem;
class TraitImplItem;
@@ -150,6 +149,7 @@ struct MatchCase;
class MatchExpr;
class AwaitExpr;
class AsyncBlockExpr;
+class InlineAsm;
// rust-stmt.h
class EmptyStmt;
@@ -250,6 +250,7 @@ class TuplePatternItemsRanged;
class TuplePattern;
class GroupedPattern;
class SlicePattern;
+class AltPattern;
// rust-type.h
class TraitBound;
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index aa59a11..1083e83 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -203,6 +203,7 @@ public:
virtual void visit (TuplePattern &pattern) = 0;
virtual void visit (GroupedPattern &pattern) = 0;
virtual void visit (SlicePattern &pattern) = 0;
+ virtual void visit (AltPattern &pattern) = 0;
// rust-stmt.h
virtual void visit (EmptyStmt &stmt) = 0;
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast.cc
index 4f593dc..68a7dfd 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see
#include "rust-session-manager.h"
#include "rust-lex.h"
#include "rust-parse.h"
-#include "operator.h"
+#include "rust-operators.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
@@ -1284,6 +1284,7 @@ MacroRulesDefinition::as_string () const
// get outer attrs
str += append_attributes (outer_attrs, OUTER);
+ // TODO: deal with macro_2_0
str += "macro_rules!";
str += rule_name;
@@ -1322,6 +1323,12 @@ std::string
MacroInvocation::as_string () const
{
std::string str = "MacroInvocation: ";
+ auto is_builtin = kind == InvocKind::Builtin;
+
+ if (is_builtin)
+ str += "[builtin] ";
+ else
+ str += "[regular] ";
str += append_attributes (outer_attrs, OUTER);
@@ -1330,6 +1337,16 @@ MacroInvocation::as_string () const
str += "\n has semicolon: ";
str += has_semicolon () ? "true" : "false";
+ if (is_builtin)
+ {
+ str += "[PENDING EAGER INVOCATIONS]: ";
+ for (auto &pending : pending_eager_invocs)
+ {
+ str += pending->as_string ();
+ str += "\n";
+ }
+ }
+
return str;
}
@@ -2688,6 +2705,17 @@ SlicePattern::as_string () const
}
std::string
+AltPattern::as_string () const
+{
+ std::string str ("AltPattern: ");
+
+ for (const auto &pattern : alts)
+ str += "\n " + pattern->as_string ();
+
+ return str;
+}
+
+std::string
TuplePatternItemsMultiple::as_string () const
{
std::string str;
@@ -4056,7 +4084,7 @@ Module::load_items ()
inner_attrs = parser.parse_inner_attributes ();
auto parsed_items = parser.parse_items ();
for (const auto &error : parser.get_errors ())
- error.emit_error ();
+ error.emit ();
items = std::move (parsed_items);
kind = ModuleKind::LOADED;
@@ -5633,6 +5661,12 @@ SlicePattern::accept_vis (ASTVisitor &vis)
}
void
+AltPattern::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
EmptyStmt::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index aa86f2f..585bdb0 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -630,6 +630,8 @@ public:
virtual ~MetaItemInner ();
+ virtual Location get_locus () const = 0;
+
virtual std::string as_string () const = 0;
virtual void accept_vis (ASTVisitor &vis) = 0;
@@ -771,6 +773,7 @@ public:
DelimTokenTree (DelimTokenTree const &other)
: delim_type (other.delim_type), locus (other.locus)
{
+ token_trees.clear ();
token_trees.reserve (other.token_trees.size ());
for (const auto &e : other.token_trees)
token_trees.push_back (e->clone_token_tree ());
@@ -782,6 +785,7 @@ public:
delim_type = other.delim_type;
locus = other.locus;
+ token_trees.clear ();
token_trees.reserve (other.token_trees.size ());
for (const auto &e : other.token_trees)
token_trees.push_back (e->clone_token_tree ());
@@ -1350,21 +1354,19 @@ protected:
}
};
-// A macro item AST node - abstract base class
-class MacroItem : public Item
-{
-};
-
// Item used in trait declarations - abstract base class
class TraitItem
{
protected:
- TraitItem () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
+ TraitItem (Location locus)
+ : node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
+ {}
// Clone function implementation as pure virtual method
virtual TraitItem *clone_trait_item_impl () const = 0;
NodeId node_id;
+ Location locus;
public:
virtual ~TraitItem () {}
@@ -1383,6 +1385,7 @@ public:
virtual bool is_marked_for_strip () const = 0;
NodeId get_node_id () const { return node_id; }
+ Location get_locus () const { return locus; }
};
/* Abstract base class for items used within an inherent impl block (the impl
@@ -1526,6 +1529,9 @@ public:
DelimTokenTree &get_delim_tok_tree () { return token_tree; }
const DelimTokenTree &get_delim_tok_tree () const { return token_tree; }
+ // Set the delim token tree of a macro invocation
+ void set_delim_tok_tree (DelimTokenTree tree) { token_tree = tree; }
+
// TODO: this mutable getter seems kinda dodgy
SimplePath &get_path () { return path; }
const SimplePath &get_path () const { return path; }
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index c58fae5..f546184 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -3,7 +3,7 @@
#include "rust-ast.h"
#include "rust-path.h"
-#include "operator.h"
+#include "rust-operators.h"
namespace Rust {
namespace AST {
@@ -150,6 +150,8 @@ public:
std::string as_string () const override { return lit_expr.as_string (); }
+ Location get_locus () const override { return lit_expr.get_locus (); }
+
void accept_vis (ASTVisitor &vis) override;
bool check_cfg_predicate (const Session &session) const override;
@@ -178,6 +180,12 @@ public:
return path.as_string () + " = " + lit.as_string ();
}
+ // There are two Locations in MetaItemPathLit (path and lit_expr),
+ // we have no idea use which of them, just simply return UNKNOWN_LOCATION
+ // now.
+ // Maybe we will figure out when we really need the location in the future.
+ Location get_locus () const override { return Location (UNKNOWN_LOCATION); }
+
void accept_vis (ASTVisitor &vis) override;
bool check_cfg_predicate (const Session &session) const override;
@@ -4626,6 +4634,144 @@ protected:
return new AsyncBlockExpr (*this);
}
};
+
+// Inline Assembly Node
+class InlineAsm : public ExprWithoutBlock
+{
+ // Inline-assembly specific options
+ enum InlineAsmOptions
+ {
+ 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;
+ std::unique_ptr<Expr> value;
+ };
+
+ struct InlineAsmRegOrRegClass
+ {
+ enum Type
+ {
+ Reg,
+ RegClass,
+ };
+
+ struct Reg
+ {
+ std::string Symbol;
+ };
+
+ struct RegClass
+ {
+ std::string Symbol;
+ };
+
+ Identifier name;
+ Location locus;
+ };
+
+ struct InlineAsmOperand
+ {
+ enum RegisterType
+ {
+ In,
+ Out,
+ InOut,
+ SplitInOut,
+ Const,
+ Sym,
+ };
+
+ struct In
+ {
+ InlineAsmRegOrRegClass reg;
+ std::unique_ptr<Expr> expr;
+ };
+
+ struct Out
+ {
+ InlineAsmRegOrRegClass reg;
+ bool late;
+ std::unique_ptr<Expr> expr; // can be null
+ };
+
+ struct InOut
+ {
+ InlineAsmRegOrRegClass reg;
+ bool late;
+ std::unique_ptr<Expr> expr; // this can't be null
+ };
+
+ struct SplitInOut
+ {
+ InlineAsmRegOrRegClass reg;
+ bool late;
+ std::unique_ptr<Expr> in_expr;
+ std::unique_ptr<Expr> out_expr; // could be null
+ };
+
+ struct Const
+ {
+ AnonConst anon_const;
+ };
+
+ struct Sym
+ {
+ std::unique_ptr<Expr> sym;
+ };
+ Location locus;
+ };
+
+ struct InlineAsmPlaceHolder
+ {
+ size_t operand_idx;
+ char modifier; // can be null
+ Location locus;
+ };
+
+ struct InlineAsmTemplatePiece
+ {
+ bool is_placeholder;
+ union
+ {
+ std::string string;
+ InlineAsmPlaceHolder placeholder;
+ };
+ };
+
+ struct TupleClobber
+ {
+ // as gccrs still doesen't contain a symbol class I have put them as strings
+ std::string symbol;
+ Location loc;
+ };
+
+ struct TupleTemplateStr
+ {
+ // as gccrs still doesen't contain a symbol class I have put them as strings
+ std::string symbol;
+ std::string optional_symbol;
+ Location loc;
+ };
+
+public:
+ std::vector<InlineAsmTemplatePiece> template_;
+ std::vector<TupleTemplateStr> template_strs;
+ std::vector<InlineAsmOperand> operands;
+ TupleClobber clobber_abi;
+ InlineAsmOptions options;
+ std::vector<Location> line_spans;
+};
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 7ea7b86..1620961 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -22,11 +22,11 @@
#include "rust-ast.h"
#include "rust-path.h"
#include "rust-common.h"
+#include "rust-expr.h"
namespace Rust {
namespace AST {
// forward decls
-class BlockExpr;
class TypePath;
// TODO: inline?
@@ -2908,7 +2908,6 @@ class TraitItemFunc : public TraitItem
std::vector<Attribute> outer_attrs;
TraitFunctionDecl decl;
std::unique_ptr<BlockExpr> block_expr;
- Location locus;
public:
// Returns whether function has a definition or is just a declaration.
@@ -2916,14 +2915,14 @@ public:
TraitItemFunc (TraitFunctionDecl decl, std::unique_ptr<BlockExpr> block_expr,
std::vector<Attribute> outer_attrs, Location locus)
- : TraitItem (), outer_attrs (std::move (outer_attrs)),
- decl (std::move (decl)), block_expr (std::move (block_expr)),
- locus (locus)
+ : TraitItem (locus), outer_attrs (std::move (outer_attrs)),
+ decl (std::move (decl)), block_expr (std::move (block_expr))
{}
// Copy constructor with clone
TraitItemFunc (TraitItemFunc const &other)
- : outer_attrs (other.outer_attrs), decl (other.decl), locus (other.locus)
+ : TraitItem (other.locus), outer_attrs (other.outer_attrs),
+ decl (other.decl)
{
node_id = other.node_id;
@@ -2956,8 +2955,6 @@ public:
std::string as_string () const override;
- Location get_locus () const { return locus; }
-
void accept_vis (ASTVisitor &vis) override;
// Invalid if trait decl is empty, so base stripping on that.
@@ -3128,7 +3125,6 @@ class TraitItemMethod : public TraitItem
std::vector<Attribute> outer_attrs;
TraitMethodDecl decl;
std::unique_ptr<BlockExpr> block_expr;
- Location locus;
public:
// Returns whether method has a definition or is just a declaration.
@@ -3136,14 +3132,14 @@ public:
TraitItemMethod (TraitMethodDecl decl, std::unique_ptr<BlockExpr> block_expr,
std::vector<Attribute> outer_attrs, Location locus)
- : TraitItem (), outer_attrs (std::move (outer_attrs)),
- decl (std::move (decl)), block_expr (std::move (block_expr)),
- locus (locus)
+ : TraitItem (locus), outer_attrs (std::move (outer_attrs)),
+ decl (std::move (decl)), block_expr (std::move (block_expr))
{}
// Copy constructor with clone
TraitItemMethod (TraitItemMethod const &other)
- : outer_attrs (other.outer_attrs), decl (other.decl), locus (other.locus)
+ : TraitItem (other.locus), outer_attrs (other.outer_attrs),
+ decl (other.decl)
{
node_id = other.node_id;
@@ -3176,8 +3172,6 @@ public:
std::string as_string () const override;
- Location get_locus () const { return locus; }
-
void accept_vis (ASTVisitor &vis) override;
// Invalid if trait decl is empty, so base stripping on that.
@@ -3219,8 +3213,6 @@ class TraitItemConst : public TraitItem
// bool has_expression;
std::unique_ptr<Expr> expr;
- Location locus;
-
public:
// Whether the constant item has an associated expression.
bool has_expression () const { return expr != nullptr; }
@@ -3228,14 +3220,14 @@ public:
TraitItemConst (Identifier name, std::unique_ptr<Type> type,
std::unique_ptr<Expr> expr,
std::vector<Attribute> outer_attrs, Location locus)
- : TraitItem (), outer_attrs (std::move (outer_attrs)),
- name (std::move (name)), type (std::move (type)), expr (std::move (expr)),
- locus (locus)
+ : TraitItem (locus), outer_attrs (std::move (outer_attrs)),
+ name (std::move (name)), type (std::move (type)), expr (std::move (expr))
{}
// Copy constructor with clones
TraitItemConst (TraitItemConst const &other)
- : outer_attrs (other.outer_attrs), name (other.name), locus (other.locus)
+ : TraitItem (other.locus), outer_attrs (other.outer_attrs),
+ name (other.name)
{
node_id = other.node_id;
@@ -3328,8 +3320,6 @@ class TraitItemType : public TraitItem
std::vector<std::unique_ptr<TypeParamBound>>
type_param_bounds; // inlined form
- Location locus;
-
public:
// Returns whether trait item type has type param bounds.
bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
@@ -3337,14 +3327,14 @@ public:
TraitItemType (Identifier name,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
std::vector<Attribute> outer_attrs, Location locus)
- : TraitItem (), outer_attrs (std::move (outer_attrs)),
- name (std::move (name)),
- type_param_bounds (std::move (type_param_bounds)), locus (locus)
+ : TraitItem (locus), outer_attrs (std::move (outer_attrs)),
+ name (std::move (name)), type_param_bounds (std::move (type_param_bounds))
{}
// Copy constructor with vector clone
TraitItemType (TraitItemType const &other)
- : outer_attrs (other.outer_attrs), name (other.name), locus (other.locus)
+ : TraitItem (other.locus), outer_attrs (other.outer_attrs),
+ name (other.name)
{
node_id = other.node_id;
type_param_bounds.reserve (other.type_param_bounds.size ());
@@ -3374,8 +3364,6 @@ public:
std::string as_string () const override;
- Location get_locus () const { return locus; }
-
void accept_vis (ASTVisitor &vis) override;
// Invalid if name is empty, so base stripping on that.
@@ -4391,8 +4379,6 @@ protected:
}
};
-// Replaced with forward decls - defined in "rust-macro.h"
-class MacroItem;
class MacroRulesDefinition;
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/ast/rust-macro.cc
new file mode 100644
index 0000000..b6f8f6c
--- /dev/null
+++ b/gcc/rust/ast/rust-macro.cc
@@ -0,0 +1,64 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-macro.h"
+
+namespace Rust {
+namespace AST {
+
+BuiltinMacro
+builtin_macro_from_string (const std::string &identifier)
+{
+ if (identifier == "assert")
+ return BuiltinMacro::Assert;
+
+ if (identifier == "file")
+ return BuiltinMacro::File;
+
+ if (identifier == "line")
+ return BuiltinMacro::Line;
+
+ if (identifier == "column")
+ return BuiltinMacro::Column;
+
+ if (identifier == "include_bytes")
+ return BuiltinMacro::IncludeBytes;
+
+ if (identifier == "include_str")
+ return BuiltinMacro::IncludeStr;
+
+ if (identifier == "compile_error")
+ return BuiltinMacro::CompileError;
+
+ if (identifier == "concat")
+ return BuiltinMacro::Concat;
+
+ if (identifier == "env")
+ return BuiltinMacro::Env;
+
+ if (identifier == "cfg")
+ return BuiltinMacro::Cfg;
+
+ if (identifier == "include")
+ return BuiltinMacro::Include;
+
+ gcc_unreachable ();
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index fc4b5b8..be8ed56 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -23,13 +23,11 @@
#include "rust-ast.h"
#include "rust-ast-fragment.h"
#include "rust-location.h"
+#include "rust-item.h"
+#include "rust-make-unique.h"
namespace Rust {
namespace AST {
-
-// Decls as definitions moved to rust-ast.h
-class MacroItem;
-
class MacroFragSpec
{
public:
@@ -224,7 +222,7 @@ public:
};
private:
- std::vector<std::unique_ptr<MacroMatch> > matches;
+ std::vector<std::unique_ptr<MacroMatch>> matches;
MacroRepOp op;
// bool has_sep;
@@ -237,7 +235,7 @@ public:
// Returns whether macro match repetition has separator token.
bool has_sep () const { return sep != nullptr; }
- MacroMatchRepetition (std::vector<std::unique_ptr<MacroMatch> > matches,
+ MacroMatchRepetition (std::vector<std::unique_ptr<MacroMatch>> matches,
MacroRepOp op, std::unique_ptr<MacroRepSep> sep,
Location locus)
: matches (std::move (matches)), op (op), sep (std::move (sep)),
@@ -292,8 +290,8 @@ public:
MacroRepOp get_op () const { return op; }
const std::unique_ptr<MacroRepSep> &get_sep () const { return sep; }
- std::vector<std::unique_ptr<MacroMatch> > &get_matches () { return matches; }
- const std::vector<std::unique_ptr<MacroMatch> > &get_matches () const
+ std::vector<std::unique_ptr<MacroMatch>> &get_matches () { return matches; }
+ const std::vector<std::unique_ptr<MacroMatch>> &get_matches () const
{
return matches;
}
@@ -311,7 +309,7 @@ protected:
class MacroMatcher : public MacroMatch
{
DelimType delim_type;
- std::vector<std::unique_ptr<MacroMatch> > matches;
+ std::vector<std::unique_ptr<MacroMatch>> matches;
Location locus;
// TODO: think of way to mark invalid that doesn't take up more space
@@ -319,7 +317,7 @@ class MacroMatcher : public MacroMatch
public:
MacroMatcher (DelimType delim_type,
- std::vector<std::unique_ptr<MacroMatch> > matches,
+ std::vector<std::unique_ptr<MacroMatch>> matches,
Location locus)
: delim_type (delim_type), matches (std::move (matches)), locus (locus),
is_invalid (false)
@@ -371,8 +369,8 @@ public:
}
DelimType get_delim_type () const { return delim_type; }
- std::vector<std::unique_ptr<MacroMatch> > &get_matches () { return matches; }
- const std::vector<std::unique_ptr<MacroMatch> > &get_matches () const
+ std::vector<std::unique_ptr<MacroMatch>> &get_matches () { return matches; }
+ const std::vector<std::unique_ptr<MacroMatch>> &get_matches () const
{
return matches;
}
@@ -446,8 +444,18 @@ public:
};
// A macro rules definition item AST node
-class MacroRulesDefinition : public MacroItem
+class MacroRulesDefinition : public VisItem
{
+public:
+ enum MacroKind
+ {
+ // Macro by Example (legacy macro rules)
+ MBE,
+ // Declarative macros 2.0
+ DeclMacro,
+ };
+
+private:
std::vector<Attribute> outer_attrs;
Identifier rule_name;
// MacroRulesDef rules_def;
@@ -460,6 +468,7 @@ class MacroRulesDefinition : public MacroItem
std::function<Fragment (Location, MacroInvocData &)> associated_transcriber;
// Since we can't compare std::functions, we need to use an extra boolean
bool is_builtin_rule;
+ MacroKind kind;
/**
* Default function to use as an associated transcriber. This function should
@@ -479,27 +488,51 @@ class MacroRulesDefinition : public MacroItem
* I am not aware of the implications of this decision. The rustc spec does
* mention that using the same parser for macro definitions and invocations
* is "extremely self-referential and non-intuitive". */
-
-public:
- std::string as_string () const override;
-
MacroRulesDefinition (Identifier rule_name, DelimType delim_type,
std::vector<MacroRule> rules,
- std::vector<Attribute> outer_attrs, Location locus)
- : outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
+ std::vector<Attribute> outer_attrs, Location locus,
+ MacroKind kind, Visibility vis)
+ : VisItem (std::move (vis), outer_attrs),
+ outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
delim_type (delim_type), rules (std::move (rules)), locus (locus),
- associated_transcriber (dummy_builtin), is_builtin_rule (false)
+ associated_transcriber (dummy_builtin), is_builtin_rule (false),
+ kind (kind)
{}
MacroRulesDefinition (
Identifier builtin_name, DelimType delim_type,
- std::function<Fragment (Location, MacroInvocData &)> associated_transcriber)
- : outer_attrs (std::vector<Attribute> ()), rule_name (builtin_name),
+ std::function<Fragment (Location, MacroInvocData &)> associated_transcriber,
+ MacroKind kind, Visibility vis)
+ : VisItem (std::move (vis), std::vector<Attribute> ()),
+ outer_attrs (std::vector<Attribute> ()), rule_name (builtin_name),
delim_type (delim_type), rules (std::vector<MacroRule> ()),
locus (Location ()), associated_transcriber (associated_transcriber),
- is_builtin_rule (true)
+ is_builtin_rule (true), kind (kind)
{}
+public:
+ std::string as_string () const override;
+
+ static std::unique_ptr<MacroRulesDefinition>
+ mbe (Identifier rule_name, DelimType delim_type, std::vector<MacroRule> rules,
+ std::vector<Attribute> outer_attrs, Location locus)
+ {
+ return Rust::make_unique<MacroRulesDefinition> (
+ MacroRulesDefinition (rule_name, delim_type, rules, outer_attrs, locus,
+ AST::MacroRulesDefinition::MacroKind::MBE,
+ AST::Visibility::create_error ()));
+ }
+
+ static std::unique_ptr<MacroRulesDefinition>
+ decl_macro (Identifier rule_name, std::vector<MacroRule> rules,
+ std::vector<Attribute> outer_attrs, Location locus,
+ Visibility vis)
+ {
+ return Rust::make_unique<MacroRulesDefinition> (MacroRulesDefinition (
+ rule_name, AST::DelimType::CURLY, rules, outer_attrs, locus,
+ AST::MacroRulesDefinition::MacroKind::DeclMacro, vis));
+ }
+
void accept_vis (ASTVisitor &vis) override;
// Invalid if rule name is empty, so base stripping on that.
@@ -545,37 +578,87 @@ protected:
}
};
+/**
+ * All builtin macros possible
+ */
+enum class BuiltinMacro
+{
+ Assert,
+ File,
+ Line,
+ Column,
+ IncludeBytes,
+ IncludeStr,
+ CompileError,
+ Concat,
+ Env,
+ Cfg,
+ Include
+};
+
+BuiltinMacro
+builtin_macro_from_string (const std::string &identifier);
+
/* AST node of a macro invocation, which is replaced by the macro result at
- * compile time */
+ * compile time. This is technically a sum-type/tagged-union, which represents
+ * both classic macro invocations and builtin macro invocations. Regular macro
+ * invocations are expanded lazily, but builtin macro invocations need to be
+ * expanded eagerly, hence the differentiation.
+ */
class MacroInvocation : public TypeNoBounds,
public Pattern,
- public MacroItem,
+ public Item,
public TraitItem,
public TraitImplItem,
public InherentImplItem,
public ExternalItem,
public ExprWithoutBlock
{
- std::vector<Attribute> outer_attrs;
- MacroInvocData invoc_data;
- Location locus;
-
- // Important for when we actually expand the macro
- bool is_semi_coloned;
-
- NodeId node_id;
-
public:
+ enum class InvocKind
+ {
+ Regular,
+ Builtin,
+ };
+
std::string as_string () const override;
- MacroInvocation (MacroInvocData invoc_data,
- std::vector<Attribute> outer_attrs, Location locus,
- bool is_semi_coloned = false)
- : outer_attrs (std::move (outer_attrs)),
- invoc_data (std::move (invoc_data)), locus (locus),
- is_semi_coloned (is_semi_coloned),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
- {}
+ /**
+ * The default constructor you should use. Whenever we parse a macro call, we
+ * cannot possibly know whether or not this call refers to a builtin macro or
+ * a regular macro. With name resolution and scopes and nested macro calls,
+ * this is literally impossible. Hence, always start by creating a `Regular`
+ * MacroInvocation which will then (maybe!) become a `Builtin` macro
+ * invocation in the expander.
+ */
+ static std::unique_ptr<MacroInvocation>
+ Regular (MacroInvocData invoc_data, std::vector<Attribute> outer_attrs,
+ Location locus, bool is_semi_coloned = false)
+ {
+ return std::unique_ptr<MacroInvocation> (
+ new MacroInvocation (InvocKind::Regular, Optional<BuiltinMacro>::none (),
+ invoc_data, outer_attrs, locus, is_semi_coloned,
+ {}));
+ }
+
+ /**
+ * Create a builtin macro invocation. This can only be done after macro
+ * name-resolution and within the macro expander, so unless you're modifying
+ * these visitors, you probably do not want to use this function.
+ */
+ static std::unique_ptr<MacroInvocation> Builtin (
+ BuiltinMacro kind, MacroInvocData invoc_data,
+ std::vector<Attribute> outer_attrs, Location locus,
+ std::vector<std::unique_ptr<MacroInvocation>> &&pending_eager_invocations
+ = {},
+ bool is_semi_coloned = false)
+ {
+ return std::unique_ptr<MacroInvocation> (
+ new MacroInvocation (InvocKind::Builtin,
+ Optional<BuiltinMacro>::some (kind), invoc_data,
+ outer_attrs, locus, is_semi_coloned,
+ std::move (pending_eager_invocations)));
+ }
Location get_locus () const override final { return locus; }
@@ -609,6 +692,82 @@ public:
bool has_semicolon () const { return is_semi_coloned; }
+ InvocKind get_kind () const { return kind; }
+ Optional<BuiltinMacro> get_builtin_kind () const { return builtin_kind; }
+
+ /**
+ * Turn the current MacroInvocation into a builtin macro invocation
+ */
+ void map_to_builtin (BuiltinMacro macro)
+ {
+ kind = InvocKind::Builtin;
+ builtin_kind = Optional<BuiltinMacro>::some (macro);
+ }
+
+ /**
+ * Get the list of pending macro invcations within the builtin macro
+ * invocation that should get expanded eagerly.
+ */
+ std::vector<std::unique_ptr<MacroInvocation>> &
+ get_pending_eager_invocations ()
+ {
+ rust_assert (kind == InvocKind::Builtin);
+
+ return pending_eager_invocs;
+ }
+
+private:
+ /* Full constructor */
+ MacroInvocation (
+ InvocKind kind, Optional<BuiltinMacro> builtin_kind,
+ MacroInvocData invoc_data, std::vector<Attribute> outer_attrs,
+ Location locus, bool is_semi_coloned,
+ std::vector<std::unique_ptr<MacroInvocation>> &&pending_eager_invocs)
+ : TraitItem (locus), outer_attrs (std::move (outer_attrs)), locus (locus),
+ node_id (Analysis::Mappings::get ()->get_next_node_id ()),
+ invoc_data (std::move (invoc_data)), is_semi_coloned (is_semi_coloned),
+ kind (kind), builtin_kind (builtin_kind),
+ pending_eager_invocs (std::move (pending_eager_invocs))
+ {}
+
+ MacroInvocation (const MacroInvocation &other)
+ : TraitItem (other.locus), outer_attrs (other.outer_attrs),
+ locus (other.locus), node_id (other.node_id),
+ invoc_data (other.invoc_data), is_semi_coloned (other.is_semi_coloned),
+ kind (other.kind), builtin_kind (other.builtin_kind)
+ {
+ if (other.kind == InvocKind::Builtin)
+ for (auto &pending : other.pending_eager_invocs)
+ pending_eager_invocs.emplace_back (
+ pending->clone_macro_invocation_impl ());
+ }
+
+ std::vector<Attribute> outer_attrs;
+ Location locus;
+ NodeId node_id;
+
+ /* The data given to the macro invocation */
+ MacroInvocData invoc_data;
+
+ /* Important for when we actually expand the macro */
+ bool is_semi_coloned;
+
+ /* Is this a builtin macro or a regular macro */
+ InvocKind kind;
+
+ /* If it is a builtin macro, which one */
+ Optional<BuiltinMacro> builtin_kind = Optional<BuiltinMacro>::none ();
+
+ /**
+ * Pending invocations within a builtin macro invocation. This vector is empty
+ * and should not be accessed for a regular macro invocation. The macro
+ * invocations within should be name resolved and expanded before the builtin
+ * macro invocation get expanded again. It is then the role of the expander to
+ * insert these new tokens properly in the delimited token tree and try the
+ * builtin transcriber once again.
+ */
+ std::vector<std::unique_ptr<MacroInvocation>> pending_eager_invocs;
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -692,6 +851,8 @@ public:
return path;
}
+ Location get_locus () const override { return path.get_locus (); }
+
bool check_cfg_predicate (const Session &session) const override;
Attribute to_attribute () const override;
@@ -708,11 +869,10 @@ protected:
class MetaItemSeq : public MetaItem
{
SimplePath path;
- std::vector<std::unique_ptr<MetaItemInner> > seq;
+ std::vector<std::unique_ptr<MetaItemInner>> seq;
public:
- MetaItemSeq (SimplePath path,
- std::vector<std::unique_ptr<MetaItemInner> > seq)
+ MetaItemSeq (SimplePath path, std::vector<std::unique_ptr<MetaItemInner>> seq)
: path (std::move (path)), seq (std::move (seq))
{}
@@ -745,6 +905,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ Location get_locus () const override { return path.get_locus (); }
+
bool check_cfg_predicate (const Session &session) const override;
Attribute to_attribute () const override;
@@ -772,6 +934,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ Location get_locus () const override { return ident_locus; }
+
bool check_cfg_predicate (const Session &session) const override;
Attribute to_attribute () const override;
@@ -814,6 +978,8 @@ public:
return std::unique_ptr<MetaNameValueStr> (clone_meta_item_inner_impl ());
}
+ Location get_locus () const override { return ident_locus; }
+
bool check_cfg_predicate (const Session &session) const override;
Attribute to_attribute () const override;
@@ -852,6 +1018,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ Location get_locus () const override { return ident_locus; }
+
bool check_cfg_predicate (const Session &session) const override;
Attribute to_attribute () const override;
@@ -886,6 +1054,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ Location get_locus () const override { return ident_locus; }
+
bool check_cfg_predicate (const Session &session) const override;
Attribute to_attribute () const override;
@@ -905,18 +1075,18 @@ struct AttributeParser
{
private:
// TODO: might as well rewrite to use lexer tokens
- std::vector<std::unique_ptr<Token> > token_stream;
+ std::vector<std::unique_ptr<Token>> token_stream;
int stream_pos;
public:
- AttributeParser (std::vector<std::unique_ptr<Token> > token_stream,
+ AttributeParser (std::vector<std::unique_ptr<Token>> token_stream,
int stream_start_pos = 0)
: token_stream (std::move (token_stream)), stream_pos (stream_start_pos)
{}
~AttributeParser () = default;
- std::vector<std::unique_ptr<MetaItemInner> > parse_meta_item_seq ();
+ std::vector<std::unique_ptr<MetaItemInner>> parse_meta_item_seq ();
private:
// Parses a MetaItemInner.
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index c86bdf6..a62e9b9 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -469,6 +469,10 @@ public:
return pattern;
}
+ bool is_double_reference () const { return has_two_amps; }
+
+ bool get_is_mut () const { return is_mut; }
+
NodeId get_node_id () const { return node_id; }
NodeId get_pattern_node_id () const override final { return node_id; }
@@ -759,7 +763,7 @@ struct StructPatternElements
{
private:
// bool has_struct_pattern_fields;
- std::vector<std::unique_ptr<StructPatternField> > fields;
+ std::vector<std::unique_ptr<StructPatternField>> fields;
bool has_struct_pattern_etc;
std::vector<Attribute> struct_pattern_etc_attrs;
@@ -784,7 +788,7 @@ public:
// Constructor for StructPatternElements with both (potentially)
StructPatternElements (
- std::vector<std::unique_ptr<StructPatternField> > fields,
+ std::vector<std::unique_ptr<StructPatternField>> fields,
std::vector<Attribute> etc_attrs)
: fields (std::move (fields)), has_struct_pattern_etc (true),
struct_pattern_etc_attrs (std::move (etc_attrs))
@@ -792,7 +796,7 @@ public:
// Constructor for StructPatternElements with no StructPatternEtc
StructPatternElements (
- std::vector<std::unique_ptr<StructPatternField> > fields)
+ std::vector<std::unique_ptr<StructPatternField>> fields)
: fields (std::move (fields)), has_struct_pattern_etc (false),
struct_pattern_etc_attrs ()
{}
@@ -828,18 +832,17 @@ public:
static StructPatternElements create_empty ()
{
return StructPatternElements (
- std::vector<std::unique_ptr<StructPatternField> > ());
+ std::vector<std::unique_ptr<StructPatternField>> ());
}
std::string as_string () const;
// TODO: seems kinda dodgy. Think of better way.
- std::vector<std::unique_ptr<StructPatternField> > &
- get_struct_pattern_fields ()
+ std::vector<std::unique_ptr<StructPatternField>> &get_struct_pattern_fields ()
{
return fields;
}
- const std::vector<std::unique_ptr<StructPatternField> > &
+ const std::vector<std::unique_ptr<StructPatternField>> &
get_struct_pattern_fields () const
{
return fields;
@@ -952,10 +955,10 @@ protected:
// Class for non-ranged tuple struct pattern patterns
class TupleStructItemsNoRange : public TupleStructItems
{
- std::vector<std::unique_ptr<Pattern> > patterns;
+ std::vector<std::unique_ptr<Pattern>> patterns;
public:
- TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern> > patterns)
+ TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern>> patterns)
: patterns (std::move (patterns))
{}
@@ -987,8 +990,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: seems kinda dodgy. Think of better way.
- std::vector<std::unique_ptr<Pattern> > &get_patterns () { return patterns; }
- const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
{
return patterns;
}
@@ -1007,12 +1010,12 @@ protected:
// Class for ranged tuple struct pattern patterns
class TupleStructItemsRange : public TupleStructItems
{
- std::vector<std::unique_ptr<Pattern> > lower_patterns;
- std::vector<std::unique_ptr<Pattern> > upper_patterns;
+ std::vector<std::unique_ptr<Pattern>> lower_patterns;
+ std::vector<std::unique_ptr<Pattern>> upper_patterns;
public:
- TupleStructItemsRange (std::vector<std::unique_ptr<Pattern> > lower_patterns,
- std::vector<std::unique_ptr<Pattern> > upper_patterns)
+ TupleStructItemsRange (std::vector<std::unique_ptr<Pattern>> lower_patterns,
+ std::vector<std::unique_ptr<Pattern>> upper_patterns)
: lower_patterns (std::move (lower_patterns)),
upper_patterns (std::move (upper_patterns))
{}
@@ -1052,21 +1055,21 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: seems kinda dodgy. Think of better way.
- std::vector<std::unique_ptr<Pattern> > &get_lower_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
{
return lower_patterns;
}
- const std::vector<std::unique_ptr<Pattern> > &get_lower_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
{
return lower_patterns;
}
// TODO: seems kinda dodgy. Think of better way.
- std::vector<std::unique_ptr<Pattern> > &get_upper_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
{
return upper_patterns;
}
- const std::vector<std::unique_ptr<Pattern> > &get_upper_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
{
return upper_patterns;
}
@@ -1229,10 +1232,10 @@ TuplePatternItemsSingle(*this);
// Class representing TuplePattern patterns where there are multiple patterns
class TuplePatternItemsMultiple : public TuplePatternItems
{
- std::vector<std::unique_ptr<Pattern> > patterns;
+ std::vector<std::unique_ptr<Pattern>> patterns;
public:
- TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern> > patterns)
+ TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern>> patterns)
: patterns (std::move (patterns))
{}
@@ -1264,8 +1267,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: seems kinda dodgy. Think of better way.
- std::vector<std::unique_ptr<Pattern> > &get_patterns () { return patterns; }
- const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
{
return patterns;
}
@@ -1287,13 +1290,12 @@ protected:
// Class representing TuplePattern patterns where there are a range of patterns
class TuplePatternItemsRanged : public TuplePatternItems
{
- std::vector<std::unique_ptr<Pattern> > lower_patterns;
- std::vector<std::unique_ptr<Pattern> > upper_patterns;
+ std::vector<std::unique_ptr<Pattern>> lower_patterns;
+ std::vector<std::unique_ptr<Pattern>> upper_patterns;
public:
- TuplePatternItemsRanged (
- std::vector<std::unique_ptr<Pattern> > lower_patterns,
- std::vector<std::unique_ptr<Pattern> > upper_patterns)
+ TuplePatternItemsRanged (std::vector<std::unique_ptr<Pattern>> lower_patterns,
+ std::vector<std::unique_ptr<Pattern>> upper_patterns)
: lower_patterns (std::move (lower_patterns)),
upper_patterns (std::move (upper_patterns))
{}
@@ -1334,21 +1336,21 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: seems kinda dodgy. Think of better way.
- std::vector<std::unique_ptr<Pattern> > &get_lower_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
{
return lower_patterns;
}
- const std::vector<std::unique_ptr<Pattern> > &get_lower_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
{
return lower_patterns;
}
// TODO: seems kinda dodgy. Think of better way.
- std::vector<std::unique_ptr<Pattern> > &get_upper_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
{
return upper_patterns;
}
- const std::vector<std::unique_ptr<Pattern> > &get_upper_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
{
return upper_patterns;
}
@@ -1499,14 +1501,14 @@ protected:
// AST node representing patterns that can match slices and arrays
class SlicePattern : public Pattern
{
- std::vector<std::unique_ptr<Pattern> > items;
+ std::vector<std::unique_ptr<Pattern>> items;
Location locus;
NodeId node_id;
public:
std::string as_string () const override;
- SlicePattern (std::vector<std::unique_ptr<Pattern> > items, Location locus)
+ SlicePattern (std::vector<std::unique_ptr<Pattern>> items, Location locus)
: items (std::move (items)), locus (locus),
node_id (Analysis::Mappings::get ()->get_next_node_id ())
{}
@@ -1542,8 +1544,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: seems kinda dodgy. Think of better way.
- std::vector<std::unique_ptr<Pattern> > &get_items () { return items; }
- const std::vector<std::unique_ptr<Pattern> > &get_items () const
+ std::vector<std::unique_ptr<Pattern>> &get_items () { return items; }
+ const std::vector<std::unique_ptr<Pattern>> &get_items () const
{
return items;
}
@@ -1561,6 +1563,72 @@ protected:
}
};
+// AST node for alternate patterns
+// joins together what are technically 'PatternNoTopAlt's
+class AltPattern : public Pattern
+{
+ std::vector<std::unique_ptr<Pattern>> alts;
+ Location locus;
+ NodeId node_id;
+
+public:
+ std::string as_string () const override;
+
+ AltPattern (std::vector<std::unique_ptr<Pattern>> alts, Location locus)
+ : alts (std::move (alts)), locus (locus),
+ node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ {}
+
+ // Copy constructor with vector clone
+ AltPattern (AltPattern const &other) : locus (other.locus)
+ {
+ node_id = other.node_id;
+ alts.reserve (other.alts.size ());
+ for (const auto &e : other.alts)
+ alts.push_back (e->clone_pattern ());
+ }
+
+ // Overloaded assignment operator to vector clone
+ AltPattern &operator= (AltPattern const &other)
+ {
+ locus = other.locus;
+ node_id = other.node_id;
+
+ alts.reserve (other.alts.size ());
+ for (const auto &e : other.alts)
+ alts.push_back (e->clone_pattern ());
+
+ return *this;
+ }
+
+ // move constructors
+ AltPattern (AltPattern &&other) = default;
+ AltPattern &operator= (AltPattern &&other) = default;
+
+ Location get_locus () const override final { return locus; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_alts () { return alts; }
+ const std::vector<std::unique_ptr<Pattern>> &get_alts () const
+ {
+ return alts;
+ }
+
+ NodeId get_node_id () const { return node_id; }
+
+ NodeId get_pattern_node_id () const override final { return node_id; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ AltPattern *clone_pattern_impl () const override
+ {
+ return new AltPattern (*this);
+ }
+};
+
// Moved definition to rust-path.h
class PathPattern;
diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc
index 568abf9..c108661 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -457,9 +457,7 @@ HIRCompileBase::compile_locals_for_block (Context *ctx, Resolver::Rib &rib,
// compile the local
tree type = TyTyResolveCompile::compile (ctx, tyty);
- Bvariable *compiled
- = CompileVarDecl::compile (fndecl, type, pattern, ctx);
- locals.push_back (compiled);
+ CompileVarDecl::compile (fndecl, type, pattern, locals, ctx);
}
return locals;
}
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 436fc92..d7945db 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -26,6 +26,7 @@
#include "rust-compile-block.h"
#include "rust-compile-implitem.h"
#include "rust-constexpr.h"
+#include "rust-unify.h"
#include "rust-gcc.h"
#include "fold-const.h"
@@ -1341,30 +1342,6 @@ CompileExpr::visit (HIR::MatchExpr &expr)
// SWITCH_ALL_CASES_P is true if the switch includes a default label or the
// case label ranges cover all possible values of the condition expression
- /* Switch expression.
-
- TREE_TYPE is the original type of the condition, before any
- language required type conversions. It may be NULL, in which case
- the original type and final types are assumed to be the same.
-
- Operand 0 is the expression used to perform the branch,
- Operand 1 is the body of the switch, which probably contains
- CASE_LABEL_EXPRs. It may also be NULL, in which case operand 2
- must not be NULL. */
- // DEFTREECODE (SWITCH_EXPR, "switch_expr", tcc_statement, 2)
-
- /* Used to represent a case label.
-
- Operand 0 is CASE_LOW. It may be NULL_TREE, in which case the label
- is a 'default' label.
- Operand 1 is CASE_HIGH. If it is NULL_TREE, the label is a simple
- (one-value) case label. If it is non-NULL_TREE, the case is a range.
- Operand 2 is CASE_LABEL, which has the corresponding LABEL_DECL.
- Operand 3 is CASE_CHAIN. This operand is only used in tree-cfg.cc to
- speed up the lookup of case labels which use a particular edge in
- the control flow graph. */
- // DEFTREECODE (CASE_LABEL_EXPR, "case_label_expr", tcc_statement, 4)
-
TyTy::TypeKind scrutinee_kind = check_match_scrutinee (expr, ctx);
if (scrutinee_kind == TyTy::TypeKind::ERROR)
{
@@ -2030,7 +2007,10 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref,
{
TyTy::BaseType *infer_impl_call
= candidate_call->infer_substitions (expr_locus);
- monomorphized = infer_impl_call->unify (fntype);
+ monomorphized = Resolver::UnifyRules::Resolve (
+ TyTy::TyWithLocation (infer_impl_call),
+ TyTy::TyWithLocation (fntype), expr_locus, true /* commit */,
+ true /* emit_errors */);
}
return CompileInherentImplItem::Compile (impl_item, ctx, monomorphized);
diff --git a/gcc/rust/backend/rust-compile-fnparam.h b/gcc/rust/backend/rust-compile-fnparam.h
index 0d99814..10e8b67 100644
--- a/gcc/rust/backend/rust-compile-fnparam.h
+++ b/gcc/rust/backend/rust-compile-fnparam.h
@@ -39,7 +39,6 @@ public:
void visit (HIR::TupleStructPattern &) override;
// Empty visit for unused Pattern HIR nodes.
- void visit (HIR::GroupedPattern &) override {}
void visit (HIR::LiteralPattern &) override {}
void visit (HIR::PathInExpression &) override {}
void visit (HIR::QualifiedPathInExpression &) override {}
diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index fc70d4b..d98f7be 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -329,5 +329,134 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
}
}
+void
+CompilePatternLet::visit (HIR::IdentifierPattern &pattern)
+{
+ Bvariable *var = nullptr;
+ rust_assert (
+ ctx->lookup_var_decl (pattern.get_pattern_mappings ().get_hirid (), &var));
+
+ auto fnctx = ctx->peek_fn ();
+ if (ty->is_unit ())
+ {
+ ctx->add_statement (init_expr);
+
+ tree stmt_type = TyTyResolveCompile::compile (ctx, ty);
+
+ auto unit_type_init_expr
+ = ctx->get_backend ()->constructor_expression (stmt_type, false, {}, -1,
+ rval_locus);
+ auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var,
+ unit_type_init_expr);
+ ctx->add_statement (s);
+ }
+ else
+ {
+ auto s
+ = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init_expr);
+ ctx->add_statement (s);
+ }
+}
+
+void
+CompilePatternLet::visit (HIR::WildcardPattern &pattern)
+{
+ tree init_stmt = NULL;
+ tree stmt_type = TyTyResolveCompile::compile (ctx, ty);
+
+ ctx->get_backend ()->temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
+ stmt_type, init_expr, false,
+ pattern.get_locus (), &init_stmt);
+
+ ctx->add_statement (init_stmt);
+}
+
+void
+CompilePatternLet::visit (HIR::TuplePattern &pattern)
+{
+ rust_assert (pattern.has_tuple_pattern_items ());
+
+ tree tuple_type = TyTyResolveCompile::compile (ctx, ty);
+ tree init_stmt;
+ Bvariable *tmp_var
+ = ctx->get_backend ()->temporary_variable (ctx->peek_fn ().fndecl,
+ NULL_TREE, tuple_type, init_expr,
+ false, pattern.get_locus (),
+ &init_stmt);
+ tree access_expr
+ = ctx->get_backend ()->var_expression (tmp_var, pattern.get_locus ());
+ ctx->add_statement (init_stmt);
+
+ switch (pattern.get_items ()->get_pattern_type ())
+ {
+ case HIR::TuplePatternItems::TuplePatternItemType::RANGED: {
+ size_t tuple_idx = 0;
+ auto &items
+ = static_cast<HIR::TuplePatternItemsRanged &> (*pattern.get_items ());
+
+ auto &items_lower = items.get_lower_patterns ();
+ auto &items_upper = items.get_upper_patterns ();
+
+ for (auto &sub : items_lower)
+ {
+ TyTy::BaseType *ty_sub = nullptr;
+ HirId pattern_id = pattern.get_pattern_mappings ().get_hirid ();
+ bool ok = ctx->get_tyctx ()->lookup_type (pattern_id, &ty_sub);
+ rust_assert (ok);
+
+ tree sub_init = ctx->get_backend ()->struct_field_expression (
+ access_expr, tuple_idx, sub->get_locus ());
+ CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
+ rval_locus, ctx);
+ tuple_idx++;
+ }
+
+ rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);
+ tuple_idx = static_cast<TyTy::TupleType &> (*ty).num_fields ()
+ - items_upper.size ();
+
+ for (auto &sub : items_upper)
+ {
+ TyTy::BaseType *ty_sub = nullptr;
+ HirId pattern_id = pattern.get_pattern_mappings ().get_hirid ();
+ bool ok = ctx->get_tyctx ()->lookup_type (pattern_id, &ty_sub);
+ rust_assert (ok);
+
+ tree sub_init = ctx->get_backend ()->struct_field_expression (
+ access_expr, tuple_idx, sub->get_locus ());
+ CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
+ rval_locus, ctx);
+ tuple_idx++;
+ }
+
+ return;
+ }
+ case HIR::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
+ size_t tuple_idx = 0;
+ auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
+ *pattern.get_items ());
+
+ for (auto &sub : items.get_patterns ())
+ {
+ TyTy::BaseType *ty_sub = nullptr;
+ HirId pattern_id = pattern.get_pattern_mappings ().get_hirid ();
+ bool ok = ctx->get_tyctx ()->lookup_type (pattern_id, &ty_sub);
+ rust_assert (ok);
+
+ tree sub_init = ctx->get_backend ()->struct_field_expression (
+ access_expr, tuple_idx, sub->get_locus ());
+ CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
+ rval_locus, ctx);
+ tuple_idx++;
+ }
+
+ return;
+ }
+ default: {
+ gcc_unreachable ();
+ }
+ }
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h
index 22812a4..8f44b7b 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -40,7 +40,6 @@ public:
void visit (HIR::RangePattern &pattern) override;
// Empty visit for unused Pattern HIR nodes.
- void visit (HIR::GroupedPattern &) override {}
void visit (HIR::IdentifierPattern &) override {}
void visit (HIR::LiteralPattern &) override;
void visit (HIR::QualifiedPathInExpression &) override {}
@@ -72,7 +71,6 @@ public:
void visit (HIR::TupleStructPattern &pattern) override;
// Empty visit for unused Pattern HIR nodes.
- void visit (HIR::GroupedPattern &) override {}
void visit (HIR::IdentifierPattern &) override {}
void visit (HIR::LiteralPattern &) override {}
void visit (HIR::PathInExpression &) override {}
@@ -91,5 +89,81 @@ protected:
tree match_scrutinee_expr;
};
+class CompilePatternLet : public HIRCompileBase, public HIR::HIRPatternVisitor
+{
+public:
+ static void Compile (HIR::Pattern *pattern, tree init_expr,
+ TyTy::BaseType *ty, Location rval_locus, Context *ctx)
+ {
+ CompilePatternLet compiler (ctx, init_expr, ty, rval_locus);
+ pattern->accept_vis (compiler);
+ }
+
+ void visit (HIR::IdentifierPattern &) override;
+ void visit (HIR::WildcardPattern &) override;
+ void visit (HIR::TuplePattern &) override;
+
+ // check for unimplemented Pattern HIR nodes.
+ void visit (HIR::LiteralPattern &pattern) override
+ {
+ rust_sorry_at (pattern.get_locus (),
+ "literal pattern let statements not supported");
+ }
+
+ void visit (HIR::PathInExpression &pattern) override
+ {
+ rust_sorry_at (pattern.get_locus (),
+ "path-in-expression pattern let statements not supported");
+ }
+
+ void visit (HIR::QualifiedPathInExpression &pattern) override
+ {
+ rust_sorry_at (
+ pattern.get_locus (),
+ "qualified-path-in-expression pattern let statements not supported");
+ }
+
+ void visit (HIR::RangePattern &pattern) override
+ {
+ rust_sorry_at (pattern.get_locus (),
+ "range pattern let statements not supported");
+ }
+
+ void visit (HIR::ReferencePattern &pattern) override
+ {
+ rust_sorry_at (pattern.get_locus (),
+ "reference pattern let statements not supported");
+ }
+
+ void visit (HIR::SlicePattern &pattern) override
+ {
+ rust_sorry_at (pattern.get_locus (),
+ "slice pattern let statements not supported");
+ }
+
+ void visit (HIR::StructPattern &pattern) override
+ {
+ rust_sorry_at (pattern.get_locus (),
+ "struct pattern let statements not supported");
+ }
+
+ void visit (HIR::TupleStructPattern &pattern) override
+ {
+ rust_sorry_at (pattern.get_locus (),
+ "tuple-struct pattern let statements not supported");
+ }
+
+protected:
+ CompilePatternLet (Context *ctx, tree init_expr, TyTy::BaseType *ty,
+ Location rval_locus)
+ : HIRCompileBase (ctx), init_expr (init_expr), ty (ty),
+ rval_locus (rval_locus)
+ {}
+
+ tree init_expr;
+ TyTy::BaseType *ty;
+ Location rval_locus;
+};
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h
index 67ff7ee..6aec7be 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.h
+++ b/gcc/rust/backend/rust-compile-resolve-path.h
@@ -45,7 +45,6 @@ public:
void visit (HIR::QualifiedPathInExpression &expr) override;
// Empty visit for unused Pattern HIR nodes.
- void visit (HIR::GroupedPattern &) override {}
void visit (HIR::IdentifierPattern &) override {}
void visit (HIR::LiteralPattern &) override {}
void visit (HIR::RangePattern &) override {}
diff --git a/gcc/rust/backend/rust-compile-stmt.cc b/gcc/rust/backend/rust-compile-stmt.cc
index 3fc2528..6bb4ead 100644
--- a/gcc/rust/backend/rust-compile-stmt.cc
+++ b/gcc/rust/backend/rust-compile-stmt.cc
@@ -16,6 +16,7 @@
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+#include "rust-compile-pattern.h"
#include "rust-compile-stmt.h"
#include "rust-compile-expr.h"
@@ -53,7 +54,7 @@ CompileStmt::visit (HIR::LetStmt &stmt)
if (!stmt.has_init_expr ())
return;
- const HIR::Pattern &stmt_pattern = *stmt.get_pattern ();
+ HIR::Pattern &stmt_pattern = *stmt.get_pattern ();
HirId stmt_id = stmt_pattern.get_pattern_mappings ().get_hirid ();
TyTy::BaseType *ty = nullptr;
@@ -65,15 +66,6 @@ CompileStmt::visit (HIR::LetStmt &stmt)
return;
}
- Bvariable *var = nullptr;
- if (!ctx->lookup_var_decl (stmt_id, &var))
- {
- // FIXME this should be an assertion instead and use error mark node
- rust_fatal_error (stmt.get_locus (),
- "failed to lookup compiled variable declaration");
- return;
- }
-
tree init = CompileExpr::Compile (stmt.get_init_expr (), ctx);
// FIXME use error_mark_node, check that CompileExpr returns error_mark_node
// on failure and make this an assertion
@@ -84,7 +76,6 @@ CompileStmt::visit (HIR::LetStmt &stmt)
bool ok = ctx->get_tyctx ()->lookup_type (
stmt.get_init_expr ()->get_mappings ().get_hirid (), &actual);
rust_assert (ok);
- tree stmt_type = TyTyResolveCompile::compile (ctx, ty);
Location lvalue_locus = stmt.get_pattern ()->get_locus ();
Location rvalue_locus = stmt.get_init_expr ()->get_locus ();
@@ -92,23 +83,7 @@ CompileStmt::visit (HIR::LetStmt &stmt)
init = coercion_site (stmt.get_mappings ().get_hirid (), init, actual,
expected, lvalue_locus, rvalue_locus);
- auto fnctx = ctx->peek_fn ();
- if (ty->is_unit ())
- {
- ctx->add_statement (init);
-
- auto unit_type_init_expr
- = ctx->get_backend ()->constructor_expression (stmt_type, false, {}, -1,
- rvalue_locus);
- auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var,
- unit_type_init_expr);
- ctx->add_statement (s);
- }
- else
- {
- auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init);
- ctx->add_statement (s);
- }
+ CompilePatternLet::Compile (&stmt_pattern, init, ty, rvalue_locus, ctx);
}
} // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h
index 00146a4..13b429d 100644
--- a/gcc/rust/backend/rust-compile-var-decl.h
+++ b/gcc/rust/backend/rust-compile-var-decl.h
@@ -30,12 +30,11 @@ class CompileVarDecl : public HIRCompileBase, public HIR::HIRPatternVisitor
using HIR::HIRPatternVisitor::visit;
public:
- static ::Bvariable *compile (tree fndecl, tree translated_type,
- HIR::Pattern *pattern, Context *ctx)
+ static void compile (tree fndecl, tree translated_type, HIR::Pattern *pattern,
+ std::vector<Bvariable *> &locals, Context *ctx)
{
- CompileVarDecl compiler (ctx, fndecl, translated_type);
+ CompileVarDecl compiler (ctx, fndecl, translated_type, locals);
pattern->accept_vis (compiler);
- return compiler.compiled_variable;
}
void visit (HIR::IdentifierPattern &pattern) override
@@ -43,30 +42,18 @@ public:
if (!pattern.is_mut ())
translated_type = ctx->get_backend ()->immutable_type (translated_type);
- compiled_variable
+ Bvariable *var
= ctx->get_backend ()->local_variable (fndecl, pattern.get_identifier (),
translated_type, NULL /*decl_var*/,
pattern.get_locus ());
HirId stmt_id = pattern.get_pattern_mappings ().get_hirid ();
- ctx->insert_var_decl (stmt_id, compiled_variable);
- }
-
- void visit (HIR::WildcardPattern &pattern) override
- {
- translated_type = ctx->get_backend ()->immutable_type (translated_type);
+ ctx->insert_var_decl (stmt_id, var);
- compiled_variable
- = ctx->get_backend ()->local_variable (fndecl, "_", translated_type,
- NULL /*decl_var*/,
- pattern.get_locus ());
-
- HirId stmt_id = pattern.get_pattern_mappings ().get_hirid ();
- ctx->insert_var_decl (stmt_id, compiled_variable);
+ locals.push_back (var);
}
// Empty visit for unused Pattern HIR nodes.
- void visit (HIR::GroupedPattern &) override {}
void visit (HIR::LiteralPattern &) override {}
void visit (HIR::PathInExpression &) override {}
void visit (HIR::QualifiedPathInExpression &) override {}
@@ -76,17 +63,19 @@ public:
void visit (HIR::StructPattern &) override {}
void visit (HIR::TuplePattern &) override {}
void visit (HIR::TupleStructPattern &) override {}
+ void visit (HIR::WildcardPattern &) override {}
private:
- CompileVarDecl (Context *ctx, tree fndecl, tree translated_type)
+ CompileVarDecl (Context *ctx, tree fndecl, tree translated_type,
+ std::vector<Bvariable *> &locals)
: HIRCompileBase (ctx), fndecl (fndecl), translated_type (translated_type),
- compiled_variable (ctx->get_backend ()->error_variable ())
+ locals (locals)
{}
tree fndecl;
tree translated_type;
- Bvariable *compiled_variable;
+ std::vector<Bvariable *> &locals;
};
} // namespace Compile
diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
index becb9fd..30afaf9 100644
--- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
+++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
@@ -63,7 +63,7 @@ VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction,
NodeId ref_node_id = UNKNOWN_NODEID;
if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
{
- invalid_path.emit_error ();
+ invalid_path.emit ();
return false;
}
// FIXME: Add a hint here if we can find the path in another scope, such as
@@ -77,7 +77,7 @@ VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction,
auto module = mappings.lookup_module (ref);
if (!module)
{
- invalid_path.emit_error ();
+ invalid_path.emit ();
return false;
}
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc
index 576c1b1..3752cf3 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -835,10 +835,6 @@ ConstChecker::visit (TuplePattern &)
{}
void
-ConstChecker::visit (GroupedPattern &)
-{}
-
-void
ConstChecker::visit (SlicePattern &)
{}
@@ -898,8 +894,12 @@ ConstChecker::visit (RawPointerType &)
{}
void
-ConstChecker::visit (ReferenceType &)
-{}
+ConstChecker::visit (ReferenceType &type)
+{
+ if (const_context.is_in_context () && type.is_mut ())
+ rust_error_at (type.get_locus (),
+ "mutable references are not allowed in constant functions");
+}
void
ConstChecker::visit (ArrayType &type)
diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h
index 2381738..e040236 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -186,7 +186,6 @@ private:
virtual void visit (TuplePatternItemsMultiple &tuple_items) override;
virtual void visit (TuplePatternItemsRanged &tuple_items) override;
virtual void visit (TuplePattern &pattern) override;
- virtual void visit (GroupedPattern &pattern) override;
virtual void visit (SlicePattern &pattern) override;
virtual void visit (EmptyStmt &stmt) override;
virtual void visit (LetStmt &stmt) override;
diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc b/gcc/rust/checks/errors/rust-feature-gate.cc
new file mode 100644
index 0000000..bd01b52
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-feature-gate.cc
@@ -0,0 +1,108 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-feature-gate.h"
+#include "rust-abi.h"
+
+namespace Rust {
+
+void
+FeatureGate::check (AST::Crate &crate)
+{
+ valid_features.clear ();
+
+ for (const auto &attr : crate.inner_attrs)
+ {
+ if (attr.get_path ().as_string () == "feature")
+ {
+ const auto &attr_input = attr.get_attr_input ();
+ auto type = attr_input.get_attr_input_type ();
+ if (type == AST::AttrInput::AttrInputType::TOKEN_TREE)
+ {
+ const auto &option = static_cast<const AST::DelimTokenTree &> (
+ attr.get_attr_input ());
+ std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item (
+ option.parse_to_meta_item ());
+ for (const auto &item : meta_item->get_items ())
+ {
+ const auto &name_str = item->as_string ();
+ auto tname = Feature::as_name (name_str);
+ if (!tname.is_none ())
+ {
+ auto name = tname.get ();
+ valid_features.insert (name);
+ }
+
+ else
+ rust_error_at (item->get_locus (), "unknown feature '%s'",
+ name_str.c_str ());
+ }
+ }
+ }
+ }
+
+ auto &items = crate.items;
+ for (auto it = items.begin (); it != items.end (); it++)
+ {
+ auto &item = *it;
+ item->accept_vis (*this);
+ }
+}
+
+void
+FeatureGate::gate (Feature::Name name, Location loc,
+ const std::string &error_msg)
+{
+ if (!valid_features.count (name))
+ {
+ auto feature = Feature::create (name);
+ auto issue = feature.issue ();
+ if (issue > 0)
+ {
+ const char *fmt_str
+ = "%s. see issue %ld "
+ "<https://github.com/rust-lang/rust/issues/%ld> for more "
+ "information. add `#![feature(%s)]` to the crate attributes to "
+ "enable.";
+ rust_error_at (loc, fmt_str, error_msg.c_str (), issue, issue,
+ feature.as_string ().c_str ());
+ }
+ else
+ {
+ const char *fmt_str
+ = "%s. add `#![feature(%s)]` to the crate attributes to enable.";
+ rust_error_at (loc, fmt_str, error_msg.c_str (),
+ feature.as_string ().c_str ());
+ }
+ }
+}
+
+void
+FeatureGate::visit (AST::ExternBlock &block)
+{
+ if (block.has_abi ())
+ {
+ const auto abi = block.get_abi ();
+
+ if (get_abi_from_string (abi) == ABI::INTRINSIC)
+ gate (Feature::Name::INTRINSICS, block.get_locus (),
+ "intrinsics are subject to change");
+ }
+}
+
+} // namespace Rust \ No newline at end of file
diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/rust-feature-gate.h
new file mode 100644
index 0000000..20af147
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-feature-gate.h
@@ -0,0 +1,197 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_FEATURE_GATE_H
+#define RUST_FEATURE_GATE_H
+
+#include "rust-ast-visitor.h"
+#include "rust-ast-full.h"
+#include "rust-feature.h"
+
+namespace Rust {
+
+struct Feature;
+
+class FeatureGate : public AST::ASTVisitor
+{
+public:
+ FeatureGate () {}
+
+ void check (AST::Crate &crate);
+
+ void visit (AST::Token &tok) override {}
+ void visit (AST::DelimTokenTree &delim_tok_tree) override {}
+ void visit (AST::AttrInputMetaItemContainer &input) override {}
+ void visit (AST::IdentifierExpr &ident_expr) override {}
+ void visit (AST::Lifetime &lifetime) override {}
+ void visit (AST::LifetimeParam &lifetime_param) override {}
+ void visit (AST::ConstGenericParam &const_param) override {}
+ void visit (AST::PathInExpression &path) override {}
+ void visit (AST::TypePathSegment &segment) override {}
+ void visit (AST::TypePathSegmentGeneric &segment) override {}
+ void visit (AST::TypePathSegmentFunction &segment) override {}
+ void visit (AST::TypePath &path) override {}
+ void visit (AST::QualifiedPathInExpression &path) override {}
+ void visit (AST::QualifiedPathInType &path) override {}
+ void visit (AST::LiteralExpr &expr) override {}
+ void visit (AST::AttrInputLiteral &attr_input) override {}
+ void visit (AST::MetaItemLitExpr &meta_item) override {}
+ void visit (AST::MetaItemPathLit &meta_item) override {}
+ void visit (AST::BorrowExpr &expr) override {}
+ void visit (AST::DereferenceExpr &expr) override {}
+ void visit (AST::ErrorPropagationExpr &expr) override {}
+ void visit (AST::NegationExpr &expr) override {}
+ void visit (AST::ArithmeticOrLogicalExpr &expr) override {}
+ void visit (AST::ComparisonExpr &expr) override {}
+ void visit (AST::LazyBooleanExpr &expr) override {}
+ void visit (AST::TypeCastExpr &expr) override {}
+ void visit (AST::AssignmentExpr &expr) override {}
+ void visit (AST::CompoundAssignmentExpr &expr) override {}
+ void visit (AST::GroupedExpr &expr) override {}
+ void visit (AST::ArrayElemsValues &elems) override {}
+ void visit (AST::ArrayElemsCopied &elems) override {}
+ void visit (AST::ArrayExpr &expr) override {}
+ void visit (AST::ArrayIndexExpr &expr) override {}
+ void visit (AST::TupleExpr &expr) override {}
+ void visit (AST::TupleIndexExpr &expr) override {}
+ void visit (AST::StructExprStruct &expr) override {}
+ void visit (AST::StructExprFieldIdentifier &field) override {}
+ void visit (AST::StructExprFieldIdentifierValue &field) override {}
+ void visit (AST::StructExprFieldIndexValue &field) override {}
+ void visit (AST::StructExprStructFields &expr) override {}
+ void visit (AST::StructExprStructBase &expr) override {}
+ void visit (AST::CallExpr &expr) override {}
+ void visit (AST::MethodCallExpr &expr) override {}
+ void visit (AST::FieldAccessExpr &expr) override {}
+ void visit (AST::ClosureExprInner &expr) override {}
+ void visit (AST::BlockExpr &expr) override {}
+ void visit (AST::ClosureExprInnerTyped &expr) override {}
+ void visit (AST::ContinueExpr &expr) override {}
+ void visit (AST::BreakExpr &expr) override {}
+ void visit (AST::RangeFromToExpr &expr) override {}
+ void visit (AST::RangeFromExpr &expr) override {}
+ void visit (AST::RangeToExpr &expr) override {}
+ void visit (AST::RangeFullExpr &expr) override {}
+ void visit (AST::RangeFromToInclExpr &expr) override {}
+ void visit (AST::RangeToInclExpr &expr) override {}
+ void visit (AST::ReturnExpr &expr) override {}
+ void visit (AST::UnsafeBlockExpr &expr) override {}
+ void visit (AST::LoopExpr &expr) override {}
+ void visit (AST::WhileLoopExpr &expr) override {}
+ void visit (AST::WhileLetLoopExpr &expr) override {}
+ void visit (AST::ForLoopExpr &expr) override {}
+ void visit (AST::IfExpr &expr) override {}
+ void visit (AST::IfExprConseqElse &expr) override {}
+ void visit (AST::IfExprConseqIf &expr) override {}
+ void visit (AST::IfExprConseqIfLet &expr) override {}
+ void visit (AST::IfLetExpr &expr) override {}
+ void visit (AST::IfLetExprConseqElse &expr) override {}
+ void visit (AST::IfLetExprConseqIf &expr) override {}
+ void visit (AST::IfLetExprConseqIfLet &expr) override {}
+ void visit (AST::MatchExpr &expr) override {}
+ void visit (AST::AwaitExpr &expr) override {}
+ void visit (AST::AsyncBlockExpr &expr) override {}
+ void visit (AST::TypeParam &param) override {}
+ void visit (AST::LifetimeWhereClauseItem &item) override {}
+ void visit (AST::TypeBoundWhereClauseItem &item) override {}
+ void visit (AST::Method &method) override {}
+ void visit (AST::Module &module) override {}
+ void visit (AST::ExternCrate &crate) override {}
+ void visit (AST::UseTreeGlob &use_tree) override {}
+ void visit (AST::UseTreeList &use_tree) override {}
+ void visit (AST::UseTreeRebind &use_tree) override {}
+ void visit (AST::UseDeclaration &use_decl) override {}
+ void visit (AST::Function &function) override {}
+ void visit (AST::TypeAlias &type_alias) override {}
+ void visit (AST::StructStruct &struct_item) override {}
+ void visit (AST::TupleStruct &tuple_struct) 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 {}
+ void visit (AST::Enum &enum_item) override {}
+ void visit (AST::Union &union_item) override {}
+ void visit (AST::ConstantItem &const_item) override {}
+ void visit (AST::StaticItem &static_item) override {}
+ void visit (AST::TraitItemFunc &item) override {}
+ void visit (AST::TraitItemMethod &item) override {}
+ void visit (AST::TraitItemConst &item) override {}
+ void visit (AST::TraitItemType &item) override {}
+ void visit (AST::Trait &trait) override {}
+ void visit (AST::InherentImpl &impl) override {}
+ void visit (AST::TraitImpl &impl) override {}
+ void visit (AST::ExternalStaticItem &item) override {}
+ void visit (AST::ExternalFunctionItem &item) override {}
+ void visit (AST::ExternBlock &block) override;
+ void visit (AST::MacroMatchFragment &match) override {}
+ void visit (AST::MacroMatchRepetition &match) override {}
+ void visit (AST::MacroMatcher &matcher) override {}
+ void visit (AST::MacroRulesDefinition &rules_def) override {}
+ void visit (AST::MacroInvocation &macro_invoc) override {}
+ void visit (AST::MetaItemPath &meta_item) override {}
+ void visit (AST::MetaItemSeq &meta_item) override {}
+ void visit (AST::MetaWord &meta_item) override {}
+ void visit (AST::MetaNameValueStr &meta_item) override {}
+ void visit (AST::MetaListPaths &meta_item) override {}
+ void visit (AST::MetaListNameValueStr &meta_item) override {}
+ void visit (AST::LiteralPattern &pattern) override {}
+ void visit (AST::IdentifierPattern &pattern) override {}
+ void visit (AST::WildcardPattern &pattern) override {}
+ void visit (AST::RangePatternBoundLiteral &bound) override {}
+ void visit (AST::RangePatternBoundPath &bound) override {}
+ void visit (AST::RangePatternBoundQualPath &bound) override {}
+ void visit (AST::RangePattern &pattern) override {}
+ void visit (AST::ReferencePattern &pattern) override {}
+ void visit (AST::StructPatternFieldTuplePat &field) override {}
+ void visit (AST::StructPatternFieldIdentPat &field) override {}
+ void visit (AST::StructPatternFieldIdent &field) override {}
+ void visit (AST::StructPattern &pattern) override {}
+ void visit (AST::TupleStructItemsNoRange &tuple_items) override {}
+ void visit (AST::TupleStructItemsRange &tuple_items) override {}
+ void visit (AST::TupleStructPattern &pattern) override {}
+ void visit (AST::TuplePatternItemsMultiple &tuple_items) override {}
+ void visit (AST::TuplePatternItemsRanged &tuple_items) override {}
+ void visit (AST::TuplePattern &pattern) override {}
+ void visit (AST::GroupedPattern &pattern) override {}
+ void visit (AST::SlicePattern &pattern) override {}
+ void visit (AST::AltPattern &pattern) override {}
+ void visit (AST::EmptyStmt &stmt) override {}
+ void visit (AST::LetStmt &stmt) override {}
+ void visit (AST::ExprStmtWithoutBlock &stmt) override {}
+ void visit (AST::ExprStmtWithBlock &stmt) override {}
+ void visit (AST::TraitBound &bound) override {}
+ void visit (AST::ImplTraitType &type) override {}
+ void visit (AST::TraitObjectType &type) override {}
+ void visit (AST::ParenthesisedType &type) override {}
+ void visit (AST::ImplTraitTypeOneBound &type) override {}
+ void visit (AST::TraitObjectTypeOneBound &type) override {}
+ void visit (AST::TupleType &type) override {}
+ void visit (AST::NeverType &type) override {}
+ void visit (AST::RawPointerType &type) override {}
+ void visit (AST::ReferenceType &type) override {}
+ void visit (AST::ArrayType &type) override {}
+ void visit (AST::SliceType &type) override {}
+ void visit (AST::InferredType &type) override {}
+ void visit (AST::BareFunctionType &type) override {}
+
+private:
+ void gate (Feature::Name name, Location loc, const std::string &error_msg);
+ std::set<Feature::Name> valid_features;
+};
+} // namespace Rust
+#endif
diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/rust-feature.cc
new file mode 100644
index 0000000..81689d9
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-feature.cc
@@ -0,0 +1,66 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-feature.h"
+#include "rust-session-manager.h"
+
+namespace Rust {
+
+Feature
+Feature::create (Feature::Name name)
+{
+ switch (name)
+ {
+ case Feature::Name::ASSOCIATED_TYPE_BOUNDS:
+ return Feature (Feature::Name::ASSOCIATED_TYPE_BOUNDS,
+ Feature::State::ACCEPTED, "associated_type_bounds",
+ "1.34.0", 52662,
+ Optional<CompileOptions::Edition>::none (), "");
+ case Feature::Name::INTRINSICS:
+ return Feature (Feature::Name::INTRINSICS, Feature::State::ACCEPTED,
+ "intrinsics", "1.0.0", 0,
+ Optional<CompileOptions::Edition>::none (), "");
+ case Feature::Name::RUSTC_ATTRS:
+ return Feature (Feature::Name::RUSTC_ATTRS, Feature::State::ACCEPTED,
+ "rustc_attrs", "1.0.0", 0,
+ Optional<CompileOptions::Edition>::none (), "");
+ case Feature::Name::DECL_MACRO:
+ return Feature (Feature::Name::DECL_MACRO, Feature::State::ACCEPTED,
+ "decl_macro", "1.0.0", 0,
+ Optional<CompileOptions::Edition>::none (), "");
+ default:
+ gcc_unreachable ();
+ }
+}
+
+const std::map<std::string, Feature::Name> Feature::name_hash_map = {
+ {"associated_type_bounds", Feature::Name::ASSOCIATED_TYPE_BOUNDS},
+ {"intrinsics", Feature::Name::INTRINSICS},
+ {"rustc_attrs", Feature::Name::RUSTC_ATTRS},
+ {"decl_macro", Feature::Name::DECL_MACRO},
+};
+
+Optional<Feature::Name>
+Feature::as_name (const std::string &name)
+{
+ if (Feature::name_hash_map.count (name))
+ return Optional<Feature::Name>::some (Feature::name_hash_map.at (name));
+ return Optional<Feature::Name>::none ();
+}
+
+} // namespace Rust \ No newline at end of file
diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/rust-feature.h
new file mode 100644
index 0000000..7bd76c0
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-feature.h
@@ -0,0 +1,77 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_FEATURE_H
+#define RUST_FEATURE_H
+
+#include "rust-session-manager.h"
+#include "rust-optional.h"
+
+namespace Rust {
+
+class Feature
+{
+public:
+ enum class State
+ {
+ ACCEPTED,
+ ACTIVE,
+ REMOVED,
+ STABILIZED,
+ };
+
+ enum class Name
+ {
+ ASSOCIATED_TYPE_BOUNDS,
+ INTRINSICS,
+ RUSTC_ATTRS,
+ DECL_MACRO,
+ };
+
+ const std::string &as_string () { return m_name_str; }
+ Name name () { return m_name; }
+ const std::string &description () { return m_description; }
+ State state () { return m_state; }
+ uint64_t issue () { return m_issue; }
+
+ static Optional<Name> as_name (const std::string &name);
+ static Feature create (Name name);
+
+private:
+ Feature (Name name, State state, const char *name_str,
+ const char *rustc_since, uint64_t issue_number,
+ const Optional<CompileOptions::Edition> &edition,
+ const char *description)
+ : m_state (state), m_name (name), m_name_str (name_str),
+ m_rustc_since (rustc_since), m_issue (issue_number), edition (edition),
+ m_description (description)
+ {}
+
+ State m_state;
+ Name m_name;
+ std::string m_name_str;
+ std::string m_rustc_since;
+ uint64_t m_issue;
+ Optional<CompileOptions::Edition> edition;
+ std::string m_description;
+
+ static const std::map<std::string, Name> name_hash_map;
+};
+
+} // namespace Rust
+#endif \ No newline at end of file
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc
index 9480863..ff7a0b3 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -179,6 +179,31 @@ UnsafeChecker::check_function_call (HirId node_id, Location locus)
locus);
}
+static void
+check_target_attr (HIR::Function *fn, Location locus)
+{
+ if (std::any_of (fn->get_outer_attrs ().begin (),
+ fn->get_outer_attrs ().end (),
+ [] (const AST::Attribute &attr) {
+ return attr.get_path ().as_string () == "target_feature";
+ }))
+ rust_error_at (locus,
+ "call to function with %<#[target_feature]%> requires "
+ "unsafe function or block");
+}
+
+void
+UnsafeChecker::check_function_attr (HirId node_id, Location locus)
+{
+ if (unsafe_context.is_in_context ())
+ return;
+
+ auto maybe_fn = mappings.lookup_hir_item (node_id);
+
+ if (maybe_fn && maybe_fn->get_item_kind () == Item::ItemKind::Function)
+ check_target_attr (static_cast<Function *> (maybe_fn), locus);
+}
+
void
UnsafeChecker::visit (Lifetime &)
{}
@@ -398,11 +423,13 @@ UnsafeChecker::visit (CallExpr &expr)
rust_assert (mappings.lookup_node_to_hir (ref_node_id, &definition_id));
- // At this point we have the function's HIR Id. There are two checks we
+ // At this point we have the function's HIR Id. There are three checks we
// must perform:
// 1. The function is an unsafe one
// 2. The function is an extern one
+ // 3. The function is marked with a target_feature attribute
check_function_call (definition_id, expr.get_locus ());
+ check_function_attr (definition_id, expr.get_locus ());
if (expr.has_params ())
for (auto &arg : expr.get_arguments ())
@@ -875,10 +902,6 @@ UnsafeChecker::visit (TuplePattern &)
{}
void
-UnsafeChecker::visit (GroupedPattern &)
-{}
-
-void
UnsafeChecker::visit (SlicePattern &)
{}
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h
index 9df44db..ce270c0 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.h
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.h
@@ -46,6 +46,11 @@ private:
*/
void check_function_call (HirId node_id, Location locus);
+ /**
+ * Check if any unsafe attributes are present on a function
+ */
+ void check_function_attr (HirId node_id, Location locus);
+
StackedContexts<HirId> unsafe_context;
Resolver::TypeCheckContext &context;
@@ -163,7 +168,6 @@ private:
virtual void visit (TuplePatternItemsMultiple &tuple_items) override;
virtual void visit (TuplePatternItemsRanged &tuple_items) override;
virtual void visit (TuplePattern &pattern) override;
- virtual void visit (GroupedPattern &pattern) override;
virtual void visit (SlicePattern &pattern) override;
virtual void visit (EmptyStmt &stmt) override;
virtual void visit (LetStmt &stmt) override;
diff --git a/gcc/rust/expand/rust-attribute-visitor.cc b/gcc/rust/expand/rust-attribute-visitor.cc
index a189574..3a94699 100644
--- a/gcc/rust/expand/rust-attribute-visitor.cc
+++ b/gcc/rust/expand/rust-attribute-visitor.cc
@@ -1122,7 +1122,7 @@ AttrVisitor::visit (AST::CallExpr &expr)
stmt->accept_vis (*this);
- auto final_fragment = expand_macro_fragment_recursive ();
+ auto final_fragment = expander.take_expanded_fragment ();
if (final_fragment.should_expand ())
{
// Remove the current expanded invocation
@@ -3152,6 +3152,20 @@ AttrVisitor::visit (AST::SlicePattern &pattern)
// TODO: quit stripping now? or keep going?
}
}
+void
+AttrVisitor::visit (AST::AltPattern &pattern)
+{
+ // can't strip individual patterns, only sub-patterns
+ for (auto &alt : pattern.get_alts ())
+ {
+ alt->accept_vis (*this);
+
+ if (alt->is_marked_for_strip ())
+ rust_error_at (alt->get_locus (),
+ "cannot strip pattern in this position");
+ // TODO: quit stripping now? or keep going?
+ }
+}
void
AttrVisitor::visit (AST::EmptyStmt &)
@@ -3421,7 +3435,7 @@ AttrVisitor::visit (AST::BareFunctionType &type)
void
AttrVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
{
- auto final_fragment = expand_macro_fragment_recursive ();
+ auto final_fragment = expander.take_expanded_fragment ();
if (final_fragment.should_expand ()
&& final_fragment.is_expression_fragment ())
expr = final_fragment.take_expression_fragment ();
@@ -3430,7 +3444,7 @@ AttrVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
void
AttrVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
{
- auto final_fragment = expand_macro_fragment_recursive ();
+ auto final_fragment = expander.take_expanded_fragment ();
if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
type = final_fragment.take_type_fragment ();
}
diff --git a/gcc/rust/expand/rust-attribute-visitor.h b/gcc/rust/expand/rust-attribute-visitor.h
index cbddc16..2d10735 100644
--- a/gcc/rust/expand/rust-attribute-visitor.h
+++ b/gcc/rust/expand/rust-attribute-visitor.h
@@ -44,39 +44,6 @@ public:
void expand_trait_method_decl (AST::TraitMethodDecl &decl);
/**
- * Expand The current macro fragment recursively until it could not be
- * expanded further.
- *
- * The return value checking works because correctly
- * expanded fragment can never be an error (if the fragment can not be
- * expanded, a stand-in error fragment will be returned; for fragments that
- * could not be further expanded: the fragment prior to the expansion failure
- * will be returned).
- *
- * @return Either the expanded fragment or an empty errored-out fragment
- * indicating an expansion failure.
- */
- AST::Fragment expand_macro_fragment_recursive ()
- {
- auto fragment = expander.take_expanded_fragment (*this);
- unsigned int original_depth = expander.expansion_depth;
- auto final_fragment = AST::Fragment::create_error ();
-
- while (fragment.should_expand ())
- {
- final_fragment = std::move (fragment);
- expander.expansion_depth++;
- // further expand the previously expanded macro fragment
- auto new_fragment = expander.take_expanded_fragment (*this);
- if (new_fragment.is_error ())
- break;
- fragment = std::move (new_fragment);
- }
- expander.expansion_depth = original_depth;
- return final_fragment;
- }
-
- /**
* Expand a set of values, erasing them if they are marked for strip, and
* replacing them with expanded macro nodes if necessary.
* This function is slightly different from `expand_pointer_allow_strip` as
@@ -101,8 +68,7 @@ public:
// mark for stripping if required
value->accept_vis (*this);
- // recursively expand the children
- auto final_fragment = expand_macro_fragment_recursive ();
+ auto final_fragment = expander.take_expanded_fragment ();
if (final_fragment.should_expand ())
{
@@ -292,6 +258,7 @@ public:
void visit (AST::TuplePattern &pattern) override;
void visit (AST::GroupedPattern &pattern) override;
void visit (AST::SlicePattern &pattern) override;
+ void visit (AST::AltPattern &pattern) override;
void visit (AST::EmptyStmt &) override;
void visit (AST::LetStmt &stmt) override;
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index 1133440..cf90b38 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -29,6 +29,16 @@
namespace Rust {
namespace {
+
+/**
+ * Shorthand function for creating unique_ptr tokens
+ */
+static std::unique_ptr<AST::Token>
+make_token (const TokenPtr tok)
+{
+ return std::unique_ptr<AST::Token> (new AST::Token (tok));
+}
+
std::unique_ptr<AST::Expr>
make_string (Location locus, std::string value)
{
@@ -37,8 +47,64 @@ make_string (Location locus, std::string value)
PrimitiveCoreType::CORETYPE_STR, {}, locus));
}
-/* Match the end token of a macro given the start delimiter of the macro */
+// TODO: Is this correct?
+static AST::Fragment
+make_eager_builtin_invocation (
+ AST::BuiltinMacro kind, Location locus, AST::DelimTokenTree arguments,
+ std::vector<std::unique_ptr<AST::MacroInvocation>> &&pending_invocations)
+{
+ std::string path_str;
+
+ switch (kind)
+ {
+ // TODO: Should this be a table lookup?
+ case AST::BuiltinMacro::Assert:
+ path_str = "assert";
+ break;
+ case AST::BuiltinMacro::File:
+ path_str = "file";
+ break;
+ case AST::BuiltinMacro::Line:
+ path_str = "line";
+ break;
+ case AST::BuiltinMacro::Column:
+ path_str = "column";
+ break;
+ case AST::BuiltinMacro::IncludeBytes:
+ path_str = "include_bytes";
+ break;
+ case AST::BuiltinMacro::IncludeStr:
+ path_str = "include_str";
+ break;
+ case AST::BuiltinMacro::CompileError:
+ path_str = "compile_error";
+ break;
+ case AST::BuiltinMacro::Concat:
+ path_str = "concat";
+ break;
+ case AST::BuiltinMacro::Env:
+ path_str = "env";
+ break;
+ case AST::BuiltinMacro::Cfg:
+ path_str = "cfg";
+ break;
+ case AST::BuiltinMacro::Include:
+ path_str = "include";
+ break;
+ }
+ std::unique_ptr<AST::Expr> node = AST::MacroInvocation::Builtin (
+ kind,
+ AST::MacroInvocData (AST::SimplePath (
+ {AST::SimplePathSegment (path_str, locus)}),
+ std::move (arguments)),
+ {}, locus, std::move (pending_invocations));
+
+ return AST::Fragment ({AST::SingleASTNode (std::move (node))},
+ arguments.to_token_stream ());
+}
+
+/* Match the end token of a macro given the start delimiter of the macro */
static inline TokenId
macro_end_token (AST::DelimTokenTree &invoc_token_tree,
Parser<MacroInvocLexer> &parser)
@@ -64,22 +130,7 @@ macro_end_token (AST::DelimTokenTree &invoc_token_tree,
return last_token_id;
}
-/* Expand and extract an expression from the macro */
-
-static inline AST::Fragment
-try_expand_macro_expression (AST::Expr *expr, MacroExpander *expander)
-{
- rust_assert (expander);
-
- auto attr_visitor = Rust::AttrVisitor (*expander);
- auto early_name_resolver = Resolver::EarlyNameResolver ();
- expr->accept_vis (early_name_resolver);
- expr->accept_vis (attr_visitor);
- return expander->take_expanded_fragment (attr_visitor);
-}
-
/* Expand and then extract a string literal from the macro */
-
static std::unique_ptr<AST::LiteralExpr>
try_extract_string_literal_from_fragment (const Location &parent_locus,
std::unique_ptr<AST::Expr> &node)
@@ -97,22 +148,6 @@ try_extract_string_literal_from_fragment (const Location &parent_locus,
static_cast<AST::LiteralExpr *> (node->clone_expr ().release ()));
}
-static std::unique_ptr<AST::LiteralExpr>
-try_expand_single_string_literal (AST::Expr *input_expr,
- MacroExpander *expander)
-{
- auto nodes = try_expand_macro_expression (input_expr, expander);
- if (nodes.is_error () || nodes.is_expression_fragment ())
- {
- rust_error_at (input_expr->get_locus (),
- "argument must be a string literal");
- return nullptr;
- }
- auto expr = nodes.take_expression_fragment ();
- return try_extract_string_literal_from_fragment (input_expr->get_locus (),
- expr);
-}
-
static std::vector<std::unique_ptr<AST::Expr>>
try_expand_many_expr (Parser<MacroInvocLexer> &parser,
const TokenId last_token_id, MacroExpander *expander,
@@ -140,22 +175,7 @@ try_expand_many_expr (Parser<MacroInvocLexer> &parser,
auto expr = parser.parse_expr (AST::AttrVec (), restrictions);
// something must be so wrong that the expression could not be parsed
rust_assert (expr);
- auto nodes = try_expand_macro_expression (expr.get (), expander);
- if (nodes.is_error ())
- {
- // not macro
- result.push_back (std::move (expr));
- }
- else if (!nodes.is_expression_fragment ())
- {
- rust_error_at (expr->get_locus (), "expected expression");
- has_error = true;
- return empty_expr;
- }
- else
- {
- result.push_back (nodes.take_expression_fragment ());
- }
+ result.push_back (std::move (expr));
auto next_token = parser.peek_current_token ();
if (!parser.skip_token (COMMA) && next_token->get_id () != last_token_id)
@@ -199,12 +219,7 @@ parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree,
else if (parser.peek_current_token ()->get_id () == last_token_id)
rust_error_at (invoc_locus, "macro takes 1 argument");
else
- {
- // when the expression does not seem to be a string literal, we then try
- // to parse/expand it as macro to see if it expands to a string literal
- auto expr = parser.parse_expr ();
- lit_expr = try_expand_single_string_literal (expr.get (), expander);
- }
+ rust_error_at (invoc_locus, "argument must be a string literal");
parser.skip_token (last_token_id);
@@ -276,8 +291,10 @@ MacroBuiltin::file_handler (Location invoc_locus, AST::MacroInvocData &)
auto current_file
= Session::get_instance ().linemap->location_file (invoc_locus);
auto file_str = AST::SingleASTNode (make_string (invoc_locus, current_file));
+ auto str_token
+ = make_token (Token::make_string (invoc_locus, std::move (current_file)));
- return AST::Fragment::complete ({file_str});
+ return AST::Fragment ({file_str}, std::move (str_token));
}
AST::Fragment
@@ -286,11 +303,13 @@ MacroBuiltin::column_handler (Location invoc_locus, AST::MacroInvocData &)
auto current_column
= Session::get_instance ().linemap->location_to_column (invoc_locus);
+ auto column_tok = make_token (
+ Token::make_int (invoc_locus, std::to_string (current_column)));
auto column_no = AST::SingleASTNode (std::unique_ptr<AST::Expr> (
new AST::LiteralExpr (std::to_string (current_column), AST::Literal::INT,
PrimitiveCoreType::CORETYPE_U32, {}, invoc_locus)));
- return AST::Fragment::complete ({column_no});
+ return AST::Fragment ({column_no}, std::move (column_tok));
}
/* Expand builtin macro include_bytes!("filename"), which includes the contents
@@ -316,14 +335,25 @@ MacroBuiltin::include_bytes_handler (Location invoc_locus,
/* Is there a more efficient way to do this? */
std::vector<std::unique_ptr<AST::Expr>> elts;
+
+ // We create the tokens for a borrow expression of a byte array, so
+ // & [ <byte0>, <byte1>, ... ]
+ std::vector<std::unique_ptr<AST::Token>> toks;
+ toks.emplace_back (make_token (Token::make (AMP, invoc_locus)));
+ toks.emplace_back (make_token (Token::make (LEFT_SQUARE, invoc_locus)));
+
for (uint8_t b : bytes)
{
elts.emplace_back (
new AST::LiteralExpr (std::string (1, (char) b), AST::Literal::BYTE,
PrimitiveCoreType::CORETYPE_U8,
{} /* outer_attrs */, invoc_locus));
+ toks.emplace_back (make_token (Token::make_byte_char (invoc_locus, b)));
+ toks.emplace_back (make_token (Token::make (COMMA, invoc_locus)));
}
+ toks.emplace_back (make_token (Token::make (RIGHT_SQUARE, invoc_locus)));
+
auto elems = std::unique_ptr<AST::ArrayElems> (
new AST::ArrayElemsValues (std::move (elts), invoc_locus));
@@ -334,8 +364,9 @@ MacroBuiltin::include_bytes_handler (Location invoc_locus,
new AST::BorrowExpr (std::move (array), false, false, {}, invoc_locus));
auto node = AST::SingleASTNode (std::move (borrow));
- return AST::Fragment::complete ({node});
-}
+
+ return AST::Fragment ({node}, std::move (toks));
+} // namespace Rust
/* Expand builtin macro include_str!("filename"), which includes the contents
of the given file as a string. The file must be UTF-8 encoded. Yields an
@@ -358,11 +389,61 @@ MacroBuiltin::include_str_handler (Location invoc_locus,
std::vector<uint8_t> bytes = load_file_bytes (target_filename.c_str ());
- /* FIXME: Enforce that the file contents are valid UTF-8. */
- std::string str ((const char *) &bytes[0], bytes.size ());
+ /* FIXME: reuse lexer */
+ int expect_single = 0;
+ for (uint8_t b : bytes)
+ {
+ if (expect_single)
+ {
+ if ((b & 0xC0) != 0x80)
+ /* character was truncated, exit with expect_single != 0 */
+ break;
+ expect_single--;
+ }
+ else if (b & 0x80)
+ {
+ if (b >= 0xF8)
+ {
+ /* more than 4 leading 1s */
+ expect_single = 1;
+ break;
+ }
+ else if (b >= 0xF0)
+ {
+ /* 4 leading 1s */
+ expect_single = 3;
+ }
+ else if (b >= 0xE0)
+ {
+ /* 3 leading 1s */
+ expect_single = 2;
+ }
+ else if (b >= 0xC0)
+ {
+ /* 2 leading 1s */
+ expect_single = 1;
+ }
+ else
+ {
+ /* only 1 leading 1 */
+ expect_single = 1;
+ break;
+ }
+ }
+ }
+
+ std::string str;
+ if (expect_single)
+ rust_error_at (invoc_locus, "%s was not a valid utf-8 file",
+ target_filename.c_str ());
+ else
+ str = std::string ((const char *) &bytes[0], bytes.size ());
auto node = AST::SingleASTNode (make_string (invoc_locus, str));
- return AST::Fragment::complete ({node});
+ auto str_tok = make_token (Token::make_string (invoc_locus, std::move (str)));
+
+ // FIXME: Do not return an empty token vector here
+ return AST::Fragment ({node}, std::move (str_tok));
}
/* Expand builtin macro compile_error!("error"), which forces a compile error
@@ -383,9 +464,62 @@ MacroBuiltin::compile_error_handler (Location invoc_locus,
return AST::Fragment::create_error ();
}
+static std::vector<std::unique_ptr<AST::MacroInvocation>>
+check_for_eager_invocations (
+ std::vector<std::unique_ptr<AST::Expr>> &expressions)
+{
+ std::vector<std::unique_ptr<AST::MacroInvocation>> pending;
+
+ for (auto &expr : expressions)
+ if (expr->get_ast_kind () == AST::Kind::MACRO_INVOCATION)
+ pending.emplace_back (std::unique_ptr<AST::MacroInvocation> (
+ static_cast<AST::MacroInvocation *> (expr->clone_expr ().release ())));
+
+ return pending;
+}
+
/* Expand builtin macro concat!(), which joins all the literal parameters
into a string with no delimiter. */
+// This is a weird one. We want to do something where, if something cannot be
+// expanded yet (i.e. macro invocation?) we return the whole MacroInvocation
+// node again but expanded as much as possible.
+// Is that possible? How do we do that?
+//
+// Let's take a few examples:
+//
+// 1. concat!(1, 2, true);
+// 2. concat!(a!(), 2, true);
+// 3. concat!(concat!(1, false), 2, true);
+// 4. concat!(concat!(1, a!()), 2, true);
+//
+// 1. We simply want to return the new fragment: "12true"
+// 2. We want to return `concat!(a_expanded, 2, true)` as a fragment
+// 3. We want to return `concat!(1, false, 2, true)`
+// 4. We want to return `concat!(concat!(1, a_expanded), 2, true);
+//
+// How do we do that?
+//
+// For each (un)expanded fragment: we check if it is expanded fully
+//
+// 1. What is expanded fully?
+// 2. How to check?
+//
+// If it is expanded fully and not a literal, then we error out.
+// Otherwise we simply emplace it back and keep going.
+//
+// In the second case, we must mark that this concat invocation still has some
+// expansion to do: This allows us to return a `MacroInvocation { ... }` as an
+// AST fragment, instead of a completed string.
+//
+// This means that we must change all the `try_expand_many_*` APIs and so on to
+// return some sort of index or way to signify that we might want to reuse some
+// bits and pieces of the original token tree.
+//
+// Now, before that: How do we resolve the names used in a builtin macro
+// invocation?
+// Do we split the two passes of parsing the token tree and then expanding it?
+// Can we do that easily?
AST::Fragment
MacroBuiltin::concat_handler (Location invoc_locus, AST::MacroInvocData &invoc)
{
@@ -398,12 +532,25 @@ MacroBuiltin::concat_handler (Location invoc_locus, AST::MacroInvocData &invoc)
auto last_token_id = macro_end_token (invoc_token_tree, parser);
+ auto start = lex.get_offs ();
/* NOTE: concat! could accept no argument, so we don't have any checks here */
auto expanded_expr = try_expand_many_expr (parser, last_token_id,
invoc.get_expander (), has_error);
+ auto end = lex.get_offs ();
+
+ auto tokens = lex.get_token_slice (start, end);
+
+ auto pending_invocations = check_for_eager_invocations (expanded_expr);
+ if (!pending_invocations.empty ())
+ return make_eager_builtin_invocation (AST::BuiltinMacro::Concat,
+ invoc_locus,
+ invoc.get_delim_tok_tree (),
+ std::move (pending_invocations));
+
for (auto &expr : expanded_expr)
{
- if (!expr->is_literal ())
+ if (!expr->is_literal ()
+ && expr->get_ast_kind () != AST::MACRO_INVOCATION)
{
has_error = true;
rust_error_at (expr->get_locus (), "expected a literal");
@@ -431,12 +578,13 @@ MacroBuiltin::concat_handler (Location invoc_locus, AST::MacroInvocData &invoc)
return AST::Fragment::create_error ();
auto node = AST::SingleASTNode (make_string (invoc_locus, str));
- return AST::Fragment::complete ({node});
+ auto str_tok = make_token (Token::make_string (invoc_locus, std::move (str)));
+
+ return AST::Fragment ({node}, std::move (str_tok));
}
/* Expand builtin macro env!(), which inspects an environment variable at
compile time. */
-
AST::Fragment
MacroBuiltin::env_handler (Location invoc_locus, AST::MacroInvocData &invoc)
{
@@ -449,10 +597,22 @@ MacroBuiltin::env_handler (Location invoc_locus, AST::MacroInvocData &invoc)
std::unique_ptr<AST::LiteralExpr> lit_expr = nullptr;
bool has_error = false;
+ auto start = lex.get_offs ();
auto expanded_expr = try_expand_many_expr (parser, last_token_id,
invoc.get_expander (), has_error);
+ auto end = lex.get_offs ();
+
+ auto tokens = lex.get_token_slice (start, end);
+
if (has_error)
return AST::Fragment::create_error ();
+
+ auto pending = check_for_eager_invocations (expanded_expr);
+ if (!pending.empty ())
+ return make_eager_builtin_invocation (AST::BuiltinMacro::Env, invoc_locus,
+ invoc_token_tree,
+ std::move (pending));
+
if (expanded_expr.size () < 1 || expanded_expr.size () > 2)
{
rust_error_at (invoc_locus, "env! takes 1 or 2 arguments");
@@ -492,7 +652,11 @@ MacroBuiltin::env_handler (Location invoc_locus, AST::MacroInvocData &invoc)
}
auto node = AST::SingleASTNode (make_string (invoc_locus, env_value));
- return AST::Fragment::complete ({node});
+ auto tok
+ = make_token (Token::make_string (invoc_locus, std::move (env_value)));
+
+ // FIXME: Do not return an empty token vector here
+ return AST::Fragment ({node}, std::move (tok));
}
AST::Fragment
@@ -527,8 +691,11 @@ MacroBuiltin::cfg_handler (Location invoc_locus, AST::MacroInvocData &invoc)
auto literal_exp = AST::SingleASTNode (std::unique_ptr<AST::Expr> (
new AST::LiteralExpr (result ? "true" : "false", AST::Literal::BOOL,
PrimitiveCoreType::CORETYPE_BOOL, {}, invoc_locus)));
+ auto tok = make_token (
+ Token::make (result ? TRUE_LITERAL : FALSE_LITERAL, invoc_locus));
- return AST::Fragment::complete ({literal_exp});
+ // FIXME: Do not return an empty token vector here
+ return AST::Fragment ({literal_exp}, std::move (tok));
}
/* Expand builtin macro include!(), which includes a source file at the current
@@ -569,7 +736,7 @@ MacroBuiltin::include_handler (Location invoc_locus, AST::MacroInvocData &invoc)
bool has_error = !parser.get_errors ().empty ();
for (const auto &error : parser.get_errors ())
- error.emit_error ();
+ error.emit ();
if (has_error)
{
@@ -585,7 +752,19 @@ MacroBuiltin::include_handler (Location invoc_locus, AST::MacroInvocData &invoc)
nodes.push_back (node);
}
- return AST::Fragment::complete (nodes);
+ // FIXME: This returns an empty vector of tokens and works fine, but is that
+ // the expected behavior? `include` macros are a bit harder to reason about
+ // since they include tokens. Furthermore, our lexer has no easy way to return
+ // a slice of tokens like the MacroInvocLexer. So it gets even harder to
+ // extrac tokens from here. For now, let's keep it that way and see if it
+ // eventually breaks, but I don't expect it to cause many issues since the
+ // list of tokens is only used when a macro invocation mixes eager
+ // macro invocations and already expanded tokens. Think
+ // `concat!(a!(), 15, b!())`. We need to be able to expand a!(), expand b!(),
+ // and then insert the `15` token in between. In the case of `include!()`, we
+ // only have one argument. So it's either going to be a macro invocation or a
+ // string literal.
+ return AST::Fragment (nodes, std::vector<std::unique_ptr<AST::Token>> ());
}
AST::Fragment
@@ -597,8 +776,11 @@ MacroBuiltin::line_handler (Location invoc_locus, AST::MacroInvocData &)
auto line_no = AST::SingleASTNode (std::unique_ptr<AST::Expr> (
new AST::LiteralExpr (std::to_string (current_line), AST::Literal::INT,
PrimitiveCoreType::CORETYPE_U32, {}, invoc_locus)));
+ auto tok
+ = make_token (Token::make_int (invoc_locus, std::to_string (current_line)));
- return AST::Fragment::complete ({line_no});
+ // FIXME: Do not return an empty token vector here
+ return AST::Fragment ({line_no}, std::move (tok));
}
} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 9c3523e..71aafef 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -111,6 +111,122 @@ MacroExpander::expand_decl_macro (Location invoc_locus,
}
void
+MacroExpander::expand_eager_invocations (AST::MacroInvocation &invoc)
+{
+ if (invoc.get_pending_eager_invocations ().empty ())
+ return;
+
+ // We have to basically create a new delimited token tree which contains the
+ // result of one step of expansion. In the case of builtin macros called with
+ // other macro invocations, such as `concat!("h", 'a', a!())`, we need to
+ // expand `a!()` before expanding the concat macro.
+ // This will, ideally, give us a new token tree containing the various
+ // existing tokens + the result of the expansion of a!().
+ // To do this, we "parse" the given token tree to find anything that "looks
+ // like a macro invocation". Then, we get the corresponding macro invocation
+ // from the `pending_eager_invocations` vector and expand it.
+ // Because the `pending_eager_invocations` vector is created in the same order
+ // that the DelimTokenTree is parsed, we know that the first macro invocation
+ // within the DelimTokenTree corresponds to the first element in
+ // `pending_eager_invocations`. The idea is thus to:
+ // 1. Find a macro invocation in the token tree, noting the index of the start
+ // token and of the end token
+ // 2. Get its associated invocation in `pending_eager_invocations`
+ // 3. Expand that element
+ // 4. Get the token tree associated with that AST fragment
+ // 5. Replace the original tokens corresponding to the invocation with the new
+ // tokens from the fragment
+ // pseudo-code:
+ //
+ // i = 0;
+ // for tok in dtt:
+ // if tok is identifier && tok->next() is !:
+ // start = index(tok);
+ // l_delim = tok->next()->next();
+ // tok = skip_until_r_delim();
+ // end = index(tok);
+ //
+ // new_tt = expand_eager_invoc(eagers[i++]);
+ // old_tt[start..end] = new_tt;
+
+ auto dtt = invoc.get_invoc_data ().get_delim_tok_tree ();
+ auto stream = dtt.to_token_stream ();
+ std::vector<std::unique_ptr<AST::TokenTree>> new_stream;
+ size_t current_pending = 0;
+
+ // we need to create a clone of the delimited token tree as the lexer
+ // expects ownership of the tokens
+ std::vector<std::unique_ptr<Rust::AST::Token>> dtt_clone;
+ for (auto &tok : stream)
+ dtt_clone.emplace_back (tok->clone_token ());
+
+ MacroInvocLexer lex (std::move (dtt_clone));
+ Parser<MacroInvocLexer> parser (lex);
+
+ // we want to build a substitution map - basically, associating a `start` and
+ // `end` index for each of the pending macro invocations
+ std::map<std::pair<size_t, size_t>, std::unique_ptr<AST::MacroInvocation> &>
+ substitution_map;
+
+ for (size_t i = 0; i < stream.size (); i++)
+ {
+ // FIXME: Can't these offsets be figure out when we actually parse the
+ // pending_eager_invocation in the first place?
+ auto invocation = parser.parse_macro_invocation ({});
+
+ // if we've managed to parse a macro invocation, we look at the current
+ // offset and store them in the substitution map. Otherwise, we skip one
+ // token and try parsing again
+ if (invocation)
+ substitution_map.insert (
+ {{i, parser.get_token_source ().get_offs ()},
+ invoc.get_pending_eager_invocations ()[current_pending++]});
+ else
+ parser.skip_token (stream[i]->get_id ());
+ }
+
+ size_t current_idx = 0;
+ for (auto kv : substitution_map)
+ {
+ auto &to_expand = kv.second;
+ expand_invoc (*to_expand, false);
+
+ auto fragment = take_expanded_fragment ();
+ auto &new_tokens = fragment.get_tokens ();
+
+ auto start = kv.first.first;
+ auto end = kv.first.second;
+
+ // We're now going to re-add the tokens to the invocation's token tree.
+ // 1. Basically, what we want to do is insert all tokens up until the
+ // beginning of the macro invocation (start).
+ // 2. Then, we'll insert all of the tokens resulting from the macro
+ // expansion: These are in `new_tokens`.
+ // 3. Finally, we'll do that again from
+ // the end of macro and go back to 1.
+
+ for (size_t i = current_idx; i < start; i++)
+ new_stream.emplace_back (stream[i]->clone_token ());
+
+ for (auto &tok : new_tokens)
+ new_stream.emplace_back (tok->clone_token ());
+
+ current_idx = end;
+ }
+
+ // Once all of that is done, we copy the last remaining tokens from the
+ // original stream
+ for (size_t i = current_idx; i < stream.size (); i++)
+ new_stream.emplace_back (stream[i]->clone_token ());
+
+ auto new_dtt
+ = AST::DelimTokenTree (dtt.get_delim_type (), std::move (new_stream));
+
+ invoc.get_pending_eager_invocations ().clear ();
+ invoc.get_invoc_data ().set_delim_tok_tree (new_dtt);
+}
+
+void
MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
{
if (depth_exceeds_recursion_limit ())
@@ -119,6 +235,9 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
return;
}
+ if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
+ expand_eager_invocations (invoc);
+
AST::MacroInvocData &invoc_data = invoc.get_invoc_data ();
// ??
@@ -151,6 +270,11 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
if (!ok)
return;
+ // We store the last expanded invocation and macro definition for error
+ // reporting in case the recursion limit is reached
+ last_invoc = &invoc;
+ last_def = rules_def;
+
if (rules_def->is_builtin ())
fragment
= rules_def->get_builtin_transcriber () (invoc.get_locus (), invoc_data);
@@ -292,7 +416,7 @@ MacroExpander::expand_crate ()
// mark for stripping if required
item->accept_vis (attr_visitor);
- auto fragment = take_expanded_fragment (attr_visitor);
+ auto fragment = take_expanded_fragment ();
if (fragment.should_expand ())
{
// Remove the current expanded invocation
@@ -711,6 +835,9 @@ static AST::Fragment
parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
std::function<AST::SingleASTNode ()> parse_fn)
{
+ auto &lexer = parser.get_token_source ();
+ auto start = lexer.get_offs ();
+
std::vector<AST::SingleASTNode> nodes;
while (true)
{
@@ -721,15 +848,16 @@ parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
if (node.is_error ())
{
for (auto err : parser.get_errors ())
- err.emit_error ();
+ err.emit ();
return AST::Fragment::create_error ();
}
nodes.emplace_back (std::move (node));
}
+ auto end = lexer.get_offs ();
- return AST::Fragment::complete (std::move (nodes));
+ return AST::Fragment (std::move (nodes), lexer.get_token_slice (start, end));
}
/**
@@ -838,9 +966,16 @@ transcribe_many_stmts (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
static AST::Fragment
transcribe_expression (Parser<MacroInvocLexer> &parser)
{
+ auto &lexer = parser.get_token_source ();
+ auto start = lexer.get_offs ();
+
auto expr = parser.parse_expr ();
+ if (expr == nullptr)
+ return AST::Fragment::create_error ();
+
+ auto end = lexer.get_offs ();
- return AST::Fragment::complete ({std::move (expr)});
+ return AST::Fragment ({std::move (expr)}, lexer.get_token_slice (start, end));
}
/**
@@ -851,11 +986,16 @@ transcribe_expression (Parser<MacroInvocLexer> &parser)
static AST::Fragment
transcribe_type (Parser<MacroInvocLexer> &parser)
{
+ auto &lexer = parser.get_token_source ();
+ auto start = lexer.get_offs ();
+
auto type = parser.parse_type (true);
for (auto err : parser.get_errors ())
- err.emit_error ();
+ err.emit ();
+
+ auto end = lexer.get_offs ();
- return AST::Fragment::complete ({std::move (type)});
+ return AST::Fragment ({std::move (type)}, lexer.get_token_slice (start, end));
}
static AST::Fragment
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index bf761c1..9471416 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -231,7 +231,7 @@ struct MacroExpander
: cfg (cfg), crate (crate), session (session),
sub_stack (SubstitutionScope ()),
expanded_fragment (AST::Fragment::create_error ()),
- resolver (Resolver::Resolver::get ()),
+ has_changed_flag (false), resolver (Resolver::Resolver::get ()),
mappings (Analysis::Mappings::get ())
{}
@@ -240,6 +240,12 @@ struct MacroExpander
// Expands all macros in the crate passed in.
void expand_crate ();
+ /**
+ * Expand the eager invocations contained within a builtin macro invocation.
+ * Called by `expand_invoc` when expanding builtin invocations.
+ */
+ void expand_eager_invocations (AST::MacroInvocation &invoc);
+
/* Expands a macro invocation - possibly make both
* have similar duck-typed interface and use templates?*/
// should this be public or private?
@@ -315,49 +321,44 @@ struct MacroExpander
void set_expanded_fragment (AST::Fragment &&fragment)
{
+ if (!fragment.is_error ())
+ has_changed_flag = true;
+
expanded_fragment = std::move (fragment);
}
- AST::Fragment take_expanded_fragment (AST::ASTVisitor &vis)
+ AST::Fragment take_expanded_fragment ()
{
- AST::Fragment old_fragment = std::move (expanded_fragment);
- auto accumulator = std::vector<AST::SingleASTNode> ();
+ auto fragment = std::move (expanded_fragment);
expanded_fragment = AST::Fragment::create_error ();
- auto early_name_resolver = Resolver::EarlyNameResolver ();
-
- for (auto &node : old_fragment.get_nodes ())
- {
- expansion_depth++;
-
- node.accept_vis (early_name_resolver);
- node.accept_vis (vis);
- // we'll decide the next move according to the outcome of the macro
- // expansion
- if (expanded_fragment.is_error ())
- accumulator.push_back (node); // if expansion fails, there might be a
- // non-macro expression we need to keep
- else
- {
- // if expansion succeeded, then we need to merge the fragment with
- // the contents in the accumulator, so that our final expansion
- // result will contain non-macro nodes as it should
- auto new_nodes = expanded_fragment.get_nodes ();
- std::move (new_nodes.begin (), new_nodes.end (),
- std::back_inserter (accumulator));
- expanded_fragment = AST::Fragment::complete (accumulator);
- }
- expansion_depth--;
- }
-
- return old_fragment;
+
+ return fragment;
}
+ /**
+ * Has the MacroExpander expanded a macro since its state was last reset?
+ */
+ bool has_changed () const { return has_changed_flag; }
+
+ /**
+ * Reset the expander's "changed" state. This function should be executed at
+ * each iteration in a fixed point loop
+ */
+ void reset_changed_state () { has_changed_flag = false; }
+
+ AST::MacroRulesDefinition *get_last_definition () { return last_def; }
+ AST::MacroInvocation *get_last_invocation () { return last_invoc; }
+
private:
AST::Crate &crate;
Session &session;
SubstitutionScope sub_stack;
std::vector<ContextType> context;
AST::Fragment expanded_fragment;
+ bool has_changed_flag;
+
+ AST::MacroRulesDefinition *last_def;
+ AST::MacroInvocation *last_invoc;
public:
Resolver::Resolver *resolver;
diff --git a/gcc/rust/expand/rust-macro-invoc-lexer.cc b/gcc/rust/expand/rust-macro-invoc-lexer.cc
index 8a43d29..321f0f9 100644
--- a/gcc/rust/expand/rust-macro-invoc-lexer.cc
+++ b/gcc/rust/expand/rust-macro-invoc-lexer.cc
@@ -26,4 +26,18 @@ MacroInvocLexer::split_current_token (TokenId new_left __attribute__ ((unused)),
// FIXME
gcc_unreachable ();
}
+
+std::vector<std::unique_ptr<AST::Token>>
+MacroInvocLexer::get_token_slice (size_t start_idx, size_t end_idx) const
+{
+ std::vector<std::unique_ptr<AST::Token>> slice;
+
+ rust_assert (end_idx < token_stream.size ());
+
+ for (size_t i = start_idx; i < end_idx; i++)
+ slice.emplace_back (token_stream[i]->clone_token ());
+
+ return slice;
+}
+
} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-invoc-lexer.h b/gcc/rust/expand/rust-macro-invoc-lexer.h
index a0d3016..0923c18 100644
--- a/gcc/rust/expand/rust-macro-invoc-lexer.h
+++ b/gcc/rust/expand/rust-macro-invoc-lexer.h
@@ -55,6 +55,9 @@ public:
size_t get_offs () const { return offs; }
+ std::vector<std::unique_ptr<AST::Token>>
+ get_token_slice (size_t start_idx, size_t end_idx) const;
+
private:
size_t offs;
std::vector<std::unique_ptr<AST::Token>> token_stream;
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index 3379572..5d7b5d2 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -461,6 +461,9 @@ ASTLoweringBase::visit (AST::GroupedPattern &)
void
ASTLoweringBase::visit (AST::SlicePattern &)
{}
+void
+ASTLoweringBase::visit (AST::AltPattern &)
+{}
// rust-stmt.h
void
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index 1af44aa..85343aa 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -231,6 +231,7 @@ public:
virtual void visit (AST::TuplePattern &pattern);
virtual void visit (AST::GroupedPattern &pattern);
virtual void visit (AST::SlicePattern &pattern);
+ virtual void visit (AST::AltPattern &pattern);
// rust-stmt.h
virtual void visit (AST::EmptyStmt &stmt);
diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc
index df4ba9d..50c2eae 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.cc
+++ b/gcc/rust/hir/rust-ast-lower-expr.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
// This file is part of GCC.
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc
index 30a1882..1961c74 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -243,5 +243,40 @@ ASTLoweringPattern::visit (AST::RangePattern &pattern)
std::move (upper_bound), pattern.get_locus ());
}
+void
+ASTLoweringPattern::visit (AST::GroupedPattern &pattern)
+{
+ pattern.get_pattern_in_parens ()->accept_vis (*this);
+}
+
+void
+ASTLoweringPattern::visit (AST::ReferencePattern &pattern)
+{
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::Pattern *inner
+ = ASTLoweringPattern::translate (pattern.get_referenced_pattern ().get ());
+
+ translated
+ = new HIR::ReferencePattern (mapping, std::unique_ptr<HIR::Pattern> (inner),
+ pattern.get_is_mut () ? Mutability::Mut
+ : Mutability::Imm,
+ pattern.get_locus ());
+
+ if (pattern.is_double_reference ())
+ {
+ Analysis::NodeMapping mapping2 (crate_num, pattern.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+ translated
+ = new HIR::ReferencePattern (mapping2,
+ std::unique_ptr<HIR::Pattern> (translated),
+ Mutability::Imm, pattern.get_locus ());
+ }
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.h b/gcc/rust/hir/rust-ast-lower-pattern.h
index 8b191d5..2d175a2 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.h
+++ b/gcc/rust/hir/rust-ast-lower-pattern.h
@@ -39,6 +39,8 @@ public:
void visit (AST::TuplePattern &pattern) override;
void visit (AST::LiteralPattern &pattern) override;
void visit (AST::RangePattern &pattern) override;
+ void visit (AST::GroupedPattern &pattern) override;
+ void visit (AST::ReferencePattern &pattern) override;
private:
ASTLoweringPattern ();
diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc
index 92a14f4..9ea22b0 100644
--- a/gcc/rust/hir/rust-ast-lower-type.cc
+++ b/gcc/rust/hir/rust-ast-lower-type.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
// This file is part of GCC.
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index 875e1dd..10720c4 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -457,9 +457,6 @@ void
Dump::visit (TuplePattern &)
{}
void
-Dump::visit (GroupedPattern &)
-{}
-void
Dump::visit (SlicePattern &)
{}
diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h
index 8715a95..b66e6b1 100644
--- a/gcc/rust/hir/rust-hir-dump.h
+++ b/gcc/rust/hir/rust-hir-dump.h
@@ -163,7 +163,6 @@ private:
virtual void visit (TuplePatternItemsMultiple &) override;
virtual void visit (TuplePatternItemsRanged &) override;
virtual void visit (TuplePattern &) override;
- virtual void visit (GroupedPattern &) override;
virtual void visit (SlicePattern &) override;
virtual void visit (EmptyStmt &) override;
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index cc88442..bf10351 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -23,7 +23,7 @@
#include "rust-ast-full-decls.h"
#include "rust-hir.h"
#include "rust-hir-path.h"
-#include "operator.h"
+#include "rust-operators.h"
namespace Rust {
namespace HIR {
diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h
index 7870a54..30adda6 100644
--- a/gcc/rust/hir/tree/rust-hir-full-decls.h
+++ b/gcc/rust/hir/tree/rust-hir-full-decls.h
@@ -206,7 +206,6 @@ class TuplePatternItems;
class TuplePatternItemsMultiple;
class TuplePatternItemsRanged;
class TuplePattern;
-class GroupedPattern;
class SlicePattern;
// rust-type.h
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index f7bf1f8..03e1f71 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -1226,6 +1226,11 @@ public:
SelfParam &get_self_param () { return self; }
+ std::string get_impl_item_name () const override final
+ {
+ return get_function_name ();
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1345,6 +1350,11 @@ public:
return get_mappings ();
};
+ std::string get_impl_item_name () const override final
+ {
+ return get_new_type_name ();
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2116,7 +2126,7 @@ public:
Expr *get_expr () { return const_expr.get (); }
- std::string get_identifier () { return identifier; }
+ std::string get_identifier () const { return identifier; }
Analysis::NodeMapping get_impl_mappings () const override
{
@@ -2130,6 +2140,11 @@ public:
ItemKind get_item_kind () const override { return ItemKind::Constant; }
+ std::string get_impl_item_name () const override final
+ {
+ return get_identifier ();
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h
index 17eedb8..740de93 100644
--- a/gcc/rust/hir/tree/rust-hir-path.h
+++ b/gcc/rust/hir/tree/rust-hir-path.h
@@ -105,9 +105,11 @@ public:
std::string as_string () const;
- Identifier get_identifier () const { return identifier; }
+ Identifier &get_identifier () { return identifier; }
+ const Identifier &get_identifier () const { return identifier; }
std::unique_ptr<Type> &get_type () { return type; }
+ const std::unique_ptr<Type> &get_type () const { return type; }
Location get_locus () const { return locus; }
};
diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h
index 80fa9b7..1b08ab8 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -424,7 +424,6 @@ protected:
// HIR node for pattern based on dereferencing the pointers given
class ReferencePattern : public Pattern
{
- bool has_two_amps;
Mutability mut;
std::unique_ptr<Pattern> pattern;
Location locus;
@@ -435,16 +434,15 @@ public:
ReferencePattern (Analysis::NodeMapping mappings,
std::unique_ptr<Pattern> pattern, Mutability reference_mut,
- bool ref_has_two_amps, Location locus)
- : has_two_amps (ref_has_two_amps), mut (reference_mut),
- pattern (std::move (pattern)), locus (locus), mappings (mappings)
+ Location locus)
+ : mut (reference_mut), pattern (std::move (pattern)), locus (locus),
+ mappings (mappings)
{}
// Copy constructor requires clone
ReferencePattern (ReferencePattern const &other)
- : has_two_amps (other.has_two_amps), mut (other.mut),
- pattern (other.pattern->clone_pattern ()), locus (other.locus),
- mappings (other.mappings)
+ : mut (other.mut), pattern (other.pattern->clone_pattern ()),
+ locus (other.locus), mappings (other.mappings)
{}
// Overload assignment operator to clone
@@ -452,7 +450,6 @@ public:
{
pattern = other.pattern->clone_pattern ();
mut = other.mut;
- has_two_amps = other.has_two_amps;
locus = other.locus;
mappings = other.mappings;
@@ -1145,6 +1142,24 @@ public:
return TuplePatternItemType::RANGED;
}
+ std::vector<std::unique_ptr<Pattern> > &get_lower_patterns ()
+ {
+ return lower_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern> > &get_lower_patterns () const
+ {
+ return lower_patterns;
+ }
+
+ std::vector<std::unique_ptr<Pattern> > &get_upper_patterns ()
+ {
+ return upper_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern> > &get_upper_patterns () const
+ {
+ return upper_patterns;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1215,69 +1230,6 @@ protected:
}
};
-// HIR node representing a pattern in parentheses, used to control precedence
-class GroupedPattern : public Pattern
-{
- std::unique_ptr<Pattern> pattern_in_parens;
- Location locus;
- Analysis::NodeMapping mappings;
-
-public:
- std::string as_string () const override
- {
- return "(" + pattern_in_parens->as_string () + ")";
- }
-
- GroupedPattern (Analysis::NodeMapping mappings,
- std::unique_ptr<Pattern> pattern_in_parens, Location locus)
- : pattern_in_parens (std::move (pattern_in_parens)), locus (locus),
- mappings (mappings)
- {}
-
- // Copy constructor uses clone
- GroupedPattern (GroupedPattern const &other)
- : pattern_in_parens (other.pattern_in_parens->clone_pattern ()),
- locus (other.locus), mappings (other.mappings)
- {}
-
- // Overload assignment operator to clone
- GroupedPattern &operator= (GroupedPattern const &other)
- {
- pattern_in_parens = other.pattern_in_parens->clone_pattern ();
- locus = other.locus;
- mappings = other.mappings;
-
- return *this;
- }
-
- // default move semantics
- GroupedPattern (GroupedPattern &&other) = default;
- GroupedPattern &operator= (GroupedPattern &&other) = default;
-
- Location get_locus () const override { return locus; }
-
- void accept_vis (HIRFullVisitor &vis) override;
- void accept_vis (HIRPatternVisitor &vis) override;
-
- Analysis::NodeMapping get_pattern_mappings () const override final
- {
- return mappings;
- }
-
- PatternType get_pattern_type () const override final
- {
- return PatternType::GROUPED;
- }
-
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- GroupedPattern *clone_pattern_impl () const override
- {
- return new GroupedPattern (*this);
- }
-};
-
// HIR node representing patterns that can match slices and arrays
class SlicePattern : public Pattern
{
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h
index ba6cad7..a635f90 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.h
+++ b/gcc/rust/hir/tree/rust-hir-visitor.h
@@ -138,7 +138,6 @@ public:
virtual void visit (TuplePatternItemsMultiple &tuple_items) = 0;
virtual void visit (TuplePatternItemsRanged &tuple_items) = 0;
virtual void visit (TuplePattern &pattern) = 0;
- virtual void visit (GroupedPattern &pattern) = 0;
virtual void visit (SlicePattern &pattern) = 0;
virtual void visit (EmptyStmt &stmt) = 0;
virtual void visit (LetStmt &stmt) = 0;
@@ -290,7 +289,6 @@ public:
virtual void visit (TuplePatternItemsMultiple &) override {}
virtual void visit (TuplePatternItemsRanged &) override {}
virtual void visit (TuplePattern &) override {}
- virtual void visit (GroupedPattern &) override {}
virtual void visit (SlicePattern &) override {}
virtual void visit (EmptyStmt &) override {}
@@ -470,7 +468,6 @@ public:
class HIRPatternVisitor
{
public:
- virtual void visit (GroupedPattern &) = 0;
virtual void visit (IdentifierPattern &) = 0;
virtual void visit (LiteralPattern &) = 0;
virtual void visit (PathInExpression &) = 0;
diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir.cc
index 230b7f7..0ddb841 100644
--- a/gcc/rust/hir/tree/rust-hir-full-test.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -2583,11 +2583,6 @@ ReferencePattern::as_string () const
{
std::string str ("&");
- if (has_two_amps)
- {
- str += "&";
- }
-
if (is_mut ())
{
str += "mut ";
@@ -4477,12 +4472,6 @@ TuplePattern::accept_vis (HIRFullVisitor &vis)
}
void
-GroupedPattern::accept_vis (HIRFullVisitor &vis)
-{
- vis.visit (*this);
-}
-
-void
SlicePattern::accept_vis (HIRFullVisitor &vis)
{
vis.visit (*this);
@@ -4609,12 +4598,6 @@ EmptyStmt::accept_vis (HIRStmtVisitor &vis)
}
void
-GroupedPattern::accept_vis (HIRPatternVisitor &vis)
-{
- vis.visit (*this);
-}
-
-void
WildcardPattern::accept_vis (HIRPatternVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 314aafb..28f1f21 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -839,6 +839,8 @@ public:
virtual ImplItemType get_impl_item_type () const = 0;
+ virtual std::string get_impl_item_name () const = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual ImplItem *clone_inherent_impl_item_impl () const = 0;
diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index ac7ced5..9967cec 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -447,6 +447,7 @@ Lexer::build_token ()
// match arm arrow
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (MATCH_ARROW, loc);
}
@@ -455,6 +456,7 @@ Lexer::build_token ()
// equality operator
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (EQUAL_EQUAL, loc);
}
@@ -473,6 +475,7 @@ Lexer::build_token ()
// return type specifier
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (RETURN_TYPE, loc);
}
@@ -481,6 +484,7 @@ Lexer::build_token ()
// minus-assign
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (MINUS_EQ, loc);
}
@@ -496,6 +500,7 @@ Lexer::build_token ()
// add-assign
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (PLUS_EQ, loc);
}
@@ -517,6 +522,7 @@ Lexer::build_token ()
// multiplication-assign
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (ASTERISK_EQ, loc);
}
@@ -535,6 +541,7 @@ Lexer::build_token ()
// division-assign
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (DIV_EQ, loc);
}
@@ -602,6 +609,8 @@ Lexer::build_token ()
start_line (current_line, max_column_hint);
str.shrink_to_fit ();
+
+ loc += str.size () - 1;
if (is_inner)
return Token::make_inner_doc_comment (loc, std::move (str));
else
@@ -756,6 +765,8 @@ Lexer::build_token ()
}
str.shrink_to_fit ();
+
+ loc += str.size () - 1;
if (is_inner)
return Token::make_inner_doc_comment (loc, std::move (str));
else
@@ -773,6 +784,7 @@ Lexer::build_token ()
// modulo-assign
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (PERCENT_EQ, loc);
}
@@ -788,6 +800,7 @@ Lexer::build_token ()
// xor-assign?
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (CARET_EQ, loc);
}
@@ -805,6 +818,7 @@ Lexer::build_token ()
// left-shift assign
skip_input (1);
current_column += 3;
+ loc += 2;
return Token::make (LEFT_SHIFT_EQ, loc);
}
@@ -813,6 +827,7 @@ Lexer::build_token ()
// left-shift
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (LEFT_SHIFT, loc);
}
@@ -822,6 +837,7 @@ Lexer::build_token ()
// smaller than or equal to
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (LESS_OR_EQUAL, loc);
}
@@ -840,6 +856,7 @@ Lexer::build_token ()
// right-shift-assign
skip_input (1);
current_column += 3;
+ loc += 2;
return Token::make (RIGHT_SHIFT_EQ, loc);
}
@@ -848,6 +865,7 @@ Lexer::build_token ()
// right-shift
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (RIGHT_SHIFT, loc);
}
@@ -857,6 +875,7 @@ Lexer::build_token ()
// larger than or equal to
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (GREATER_OR_EQUAL, loc);
}
@@ -872,6 +891,7 @@ Lexer::build_token ()
// scope resolution ::
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (SCOPE_RESOLUTION, loc);
}
@@ -888,6 +908,7 @@ Lexer::build_token ()
// not equal boolean operator
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (NOT_EQUAL, loc);
}
@@ -937,6 +958,7 @@ Lexer::build_token ()
// bitwise or-assign?
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (PIPE_EQ, loc);
}
@@ -945,6 +967,7 @@ Lexer::build_token ()
// logical or
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (OR, loc);
}
@@ -961,6 +984,7 @@ Lexer::build_token ()
// bitwise and-assign?
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (AMP_EQ, loc);
}
@@ -969,6 +993,7 @@ Lexer::build_token ()
// logical and
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (LOGICAL_AND, loc);
}
@@ -987,6 +1012,7 @@ Lexer::build_token ()
// ellipsis
skip_input (1);
current_column += 3;
+ loc += 2;
return Token::make (ELLIPSIS, loc);
}
@@ -995,6 +1021,7 @@ Lexer::build_token ()
// ..=
skip_input (1);
current_column += 3;
+ loc += 2;
return Token::make (DOT_DOT_EQ, loc);
}
@@ -1003,6 +1030,7 @@ Lexer::build_token ()
// ..
skip_input ();
current_column += 2;
+ loc += 1;
return Token::make (DOT_DOT, loc);
}
@@ -1717,6 +1745,8 @@ Lexer::parse_byte_char (Location loc)
current_column += length;
+ loc += length - 1;
+
return Token::make_byte_char (loc, byte_char);
}
@@ -1781,6 +1811,7 @@ Lexer::parse_byte_string (Location loc)
}
str.shrink_to_fit ();
+ loc += str.size () - 1;
return Token::make_byte_string (loc, std::move (str));
}
@@ -1861,6 +1892,8 @@ Lexer::parse_raw_byte_string (Location loc)
current_column += length;
+ loc += length - 1;
+
str.shrink_to_fit ();
return Token::make_byte_string (loc, std::move (str));
@@ -1912,6 +1945,7 @@ Lexer::parse_raw_identifier (Location loc)
else
{
str.shrink_to_fit ();
+ loc += length - 1;
return Token::make_identifier (loc, std::move (str));
}
@@ -2009,6 +2043,8 @@ Lexer::parse_string (Location loc)
}
str.shrink_to_fit ();
+ loc += length - 1;
+
return Token::make_string (loc, std::move (str));
}
@@ -2043,6 +2079,8 @@ Lexer::parse_identifier_or_keyword (Location loc)
str.shrink_to_fit ();
+ loc += length - 1;
+
TokenId keyword = classify_keyword (str);
if (keyword == IDENTIFIER)
return Token::make_identifier (loc, std::move (str));
@@ -2120,6 +2158,8 @@ Lexer::parse_raw_string (Location loc, int initial_hash_count)
current_column += length;
+ loc += length - 1;
+
str.shrink_to_fit ();
return Token::make_string (loc, std::move (str));
@@ -2183,6 +2223,9 @@ Lexer::parse_non_decimal_int_literal (Location loc, IsDigitFunc is_digit_func,
: "<insert unknown base>")));
return nullptr;
}
+
+ loc += length - 1;
+
return Token::make_int (loc, std::move (existent_str), type_hint);
}
@@ -2275,6 +2318,8 @@ Lexer::parse_decimal_int_or_float (Location loc)
current_column += length;
+ loc += length - 1;
+
str.shrink_to_fit ();
return Token::make_float (loc, std::move (str), type_hint);
}
@@ -2295,6 +2340,8 @@ Lexer::parse_decimal_int_or_float (Location loc)
current_column += length;
+ loc += length - 1;
+
str.shrink_to_fit ();
return Token::make_float (loc, std::move (str), CORETYPE_UNKNOWN);
}
@@ -2324,6 +2371,8 @@ Lexer::parse_decimal_int_or_float (Location loc)
current_column += length;
+ loc += length - 1;
+
str.shrink_to_fit ();
return Token::make_float (loc, std::move (str), type_hint);
}
@@ -2345,6 +2394,8 @@ Lexer::parse_decimal_int_or_float (Location loc)
current_column += length;
+ loc += length - 1;
+
str.shrink_to_fit ();
return Token::make_int (loc, std::move (str), type_hint);
}
@@ -2382,6 +2433,8 @@ Lexer::parse_char_or_lifetime (Location loc)
current_column += length;
+ loc += length - 1;
+
return Token::make_char (loc, current_char32);
}
else
@@ -2399,6 +2452,8 @@ Lexer::parse_char_or_lifetime (Location loc)
// TODO fix due to different widths of utf-8 chars?
current_column += 3;
+ loc += 2;
+
return Token::make_char (loc, current_char32);
}
else if (ISDIGIT (current_char32.value) || ISALPHA (current_char32.value)
@@ -2421,6 +2476,8 @@ Lexer::parse_char_or_lifetime (Location loc)
current_column += length;
+ loc += length - 1;
+
str.shrink_to_fit ();
return Token::make_lifetime (loc, std::move (str));
}
diff --git a/gcc/rust/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h
index 2dd60b3..5042471 100644
--- a/gcc/rust/lex/rust-lex.h
+++ b/gcc/rust/lex/rust-lex.h
@@ -38,13 +38,37 @@ private:
fclose (file);
}
+ static bool allowed_filetype (const struct stat &statbuf)
+ {
+ // The file could be either
+ // - a regular file
+ // - a char device (/dev/null...)
+ return S_ISREG (statbuf.st_mode) || S_ISCHR (statbuf.st_mode);
+ }
+
public:
RAIIFile (const char *filename) : filename (filename)
{
if (strcmp (filename, "-") == 0)
- file = stdin;
+ {
+ file = stdin;
+ }
else
- file = fopen (filename, "r");
+ {
+ struct stat statbuf;
+ if (!(file = fopen (filename, "r")))
+ {
+ return;
+ }
+
+ if (-1 == fstat (fileno (file), &statbuf)
+ || !allowed_filetype (statbuf))
+ {
+ fclose (file);
+ file = nullptr;
+ errno = EISDIR;
+ }
+ }
}
/**
diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index 18f1afa..0fc55a2 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -171,7 +171,7 @@ enum PrimitiveCoreType
RS_TOKEN_KEYWORD (IN, "in") \
RS_TOKEN_KEYWORD (LET, "let") \
RS_TOKEN_KEYWORD (LOOP, "loop") \
- RS_TOKEN_KEYWORD (MACRO, "macro") /* unused */ \
+ RS_TOKEN_KEYWORD (MACRO, "macro") \
RS_TOKEN_KEYWORD (MATCH_TOK, "match") \
RS_TOKEN_KEYWORD (MOD, "mod") \
RS_TOKEN_KEYWORD (MOVE, "move") \
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index cbd40ef..db32803d 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -444,7 +444,7 @@ Parser<ManagedTokenSource>::parse_crate ()
// emit all errors
for (const auto &error : error_table)
- error.emit_error ();
+ error.emit ();
return std::unique_ptr<AST::Crate> (
new AST::Crate (std::move (items), std::move (inner_attrs)));
@@ -1032,11 +1032,6 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
// parse outer attributes for item
AST::AttrVec outer_attrs = parse_outer_attributes ();
-
- // TODO: decide how to deal with VisItem vs MacroItem dichotomy
- /* best current solution: catch all keywords that would imply a VisItem in a
- * switch and have MacroItem as a last resort */
-
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
@@ -1064,6 +1059,7 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
case STATIC_TOK:
case TRAIT:
case IMPL:
+ case MACRO:
/* 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. */
@@ -1078,7 +1074,7 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
case CRATE:
case DOLLAR_SIGN:
// almost certainly macro invocation semi
- return parse_macro_item (std::move (outer_attrs));
+ return parse_macro_invocation_semi (std::move (outer_attrs));
break;
// crappy hack to do union "keyword"
case IDENTIFIER:
@@ -1092,19 +1088,18 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
else if (t->get_str () == "macro_rules")
{
// macro_rules! macro item
- return parse_macro_item (std::move (outer_attrs));
+ return parse_macro_rules_def (std::move (outer_attrs));
}
else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION
|| lexer.peek_token (1)->get_id () == EXCLAM)
{
/* path (probably) or macro invocation, so probably a macro invocation
* semi */
- return parse_macro_item (std::move (outer_attrs));
+ return parse_macro_invocation_semi (std::move (outer_attrs));
}
gcc_fallthrough ();
default:
// otherwise unrecognised
- // return parse_macro_item(std::move(outer_attrs));
add_error (Error (t->get_locus (),
"unrecognised token %qs for start of %s",
t->get_token_description (),
@@ -1335,6 +1330,8 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
lexer.skip_token (1); // TODO: is this right thing to do?
return nullptr;
}
+ case MACRO:
+ return parse_decl_macro_def (std::move (vis), std::move (outer_attrs));
default:
// otherwise vis item clearly doesn't exist, which is not an error
// has a catch-all post-switch return to allow other breaks to occur
@@ -1343,42 +1340,6 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
return nullptr;
}
-// Parses a MacroItem (either a MacroInvocationSemi or MacroRulesDefinition).
-template <typename ManagedTokenSource>
-std::unique_ptr<AST::MacroItem>
-Parser<ManagedTokenSource>::parse_macro_item (AST::AttrVec outer_attrs)
-{
- const_TokenPtr t = lexer.peek_token ();
-
- /* dodgy way of detecting macro due to weird context-dependence thing.
- * probably can be improved */
- // TODO: ensure that string compare works properly
- if (t->get_id () == IDENTIFIER && t->get_str () == "macro_rules")
- {
- return parse_macro_rules_def (std::move (outer_attrs));
- }
- else
- {
- // DEBUG: TODO: remove
- rust_debug (
- "DEBUG - parse_macro_item called and token is not macro_rules");
- if (t->get_id () == IDENTIFIER)
- {
- rust_debug ("just add to last error: token is not macro_rules and is "
- "instead '%s'",
- t->get_str ().c_str ());
- }
- else
- {
- rust_debug ("just add to last error: token is not macro_rules and is "
- "not an identifier either - it is '%s'",
- t->get_token_description ());
- }
-
- return parse_macro_invocation_semi (std::move (outer_attrs));
- }
-}
-
// Parses a macro rules definition syntax extension whatever thing.
template <typename ManagedTokenSource>
std::unique_ptr<AST::MacroRulesDefinition>
@@ -1512,16 +1473,16 @@ Parser<ManagedTokenSource>::parse_macro_rules_def (AST::AttrVec outer_attrs)
{
// as this is the end, allow recovery (probably) - may change
return std::unique_ptr<AST::MacroRulesDefinition> (
- new AST::MacroRulesDefinition (
+ AST::MacroRulesDefinition::mbe (
std::move (rule_name), delim_type, std::move (macro_rules),
std::move (outer_attrs), macro_locus));
}
}
return std::unique_ptr<AST::MacroRulesDefinition> (
- new AST::MacroRulesDefinition (std::move (rule_name), delim_type,
- std::move (macro_rules),
- std::move (outer_attrs), macro_locus));
+ AST::MacroRulesDefinition::mbe (std::move (rule_name), delim_type,
+ std::move (macro_rules),
+ std::move (outer_attrs), macro_locus));
}
else
{
@@ -1541,6 +1502,165 @@ Parser<ManagedTokenSource>::parse_macro_rules_def (AST::AttrVec outer_attrs)
}
}
+// Parses a declarative macro 2.0 definition.
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::MacroRulesDefinition>
+Parser<ManagedTokenSource>::parse_decl_macro_def (AST::Visibility vis,
+ AST::AttrVec outer_attrs)
+{
+ // ensure that first token is identifier saying "macro"
+ const_TokenPtr t = lexer.peek_token ();
+ if (t->get_id () != MACRO)
+ {
+ Error error (
+ t->get_locus (),
+ "declarative macro definition does not start with %<macro%>");
+ add_error (std::move (error));
+
+ // skip after somewhere?
+ return nullptr;
+ }
+ lexer.skip_token ();
+ Location macro_locus = t->get_locus ();
+
+ // parse macro name
+ const_TokenPtr ident_tok = expect_token (IDENTIFIER);
+ if (ident_tok == nullptr)
+ {
+ return nullptr;
+ }
+ Identifier rule_name = ident_tok->get_str ();
+
+ t = lexer.peek_token ();
+ if (t->get_id () == LEFT_PAREN)
+ {
+ // single definiton of macro rule
+ // e.g. `macro foo($e:expr) {}`
+
+ // parse macro matcher
+ Location locus = lexer.peek_token ()->get_locus ();
+ AST::MacroMatcher matcher = parse_macro_matcher ();
+ if (matcher.is_error ())
+ return nullptr;
+
+ // check delimiter of macro matcher
+ if (matcher.get_delim_type () != AST::DelimType::PARENS)
+ {
+ Error error (locus, "only parenthesis can be used for a macro "
+ "matcher in declarative macro definition");
+ add_error (std::move (error));
+ return nullptr;
+ }
+
+ Location transcriber_loc = lexer.peek_token ()->get_locus ();
+ AST::DelimTokenTree delim_tok_tree = parse_delim_token_tree ();
+ AST::MacroTranscriber transcriber (delim_tok_tree, transcriber_loc);
+
+ if (transcriber.get_token_tree ().get_delim_type ()
+ != AST::DelimType::CURLY)
+ {
+ Error error (transcriber_loc,
+ "only braces can be used for a macro transcriber "
+ "in declarative macro definition");
+ add_error (std::move (error));
+ return nullptr;
+ }
+
+ AST::MacroRule macro_rule
+ = AST::MacroRule (std::move (matcher), std::move (transcriber), locus);
+ std::vector<AST::MacroRule> macro_rules;
+ macro_rules.push_back (macro_rule);
+
+ return std::unique_ptr<AST::MacroRulesDefinition> (
+ AST::MacroRulesDefinition::decl_macro (std::move (rule_name),
+ macro_rules,
+ std::move (outer_attrs),
+ macro_locus, vis));
+ }
+ else if (t->get_id () == LEFT_CURLY)
+ {
+ // multiple definitions of macro rule separated by comma
+ // e.g. `macro foo { () => {}, ($e:expr) => {}, }`
+
+ // parse left curly
+ const_TokenPtr left_curly = expect_token (LEFT_CURLY);
+ if (left_curly == nullptr)
+ {
+ return nullptr;
+ }
+
+ // parse actual macro rules
+ std::vector<AST::MacroRule> macro_rules;
+
+ // must be at least one macro rule, so parse it
+ AST::MacroRule initial_rule = parse_macro_rule ();
+ if (initial_rule.is_error ())
+ {
+ Error error (
+ lexer.peek_token ()->get_locus (),
+ "required first macro rule in declarative macro definition "
+ "could not be parsed");
+ add_error (std::move (error));
+
+ // skip after somewhere?
+ return nullptr;
+ }
+ macro_rules.push_back (std::move (initial_rule));
+
+ t = lexer.peek_token ();
+ // parse macro rules
+ while (t->get_id () == COMMA)
+ {
+ // skip comma
+ lexer.skip_token ();
+
+ // don't parse if end of macro rules
+ if (token_id_matches_delims (lexer.peek_token ()->get_id (),
+ AST::CURLY))
+ {
+ break;
+ }
+
+ // try to parse next rule
+ AST::MacroRule rule = parse_macro_rule ();
+ if (rule.is_error ())
+ {
+ Error error (
+ lexer.peek_token ()->get_locus (),
+ "failed to parse macro rule in declarative macro definition");
+ add_error (std::move (error));
+
+ return nullptr;
+ }
+
+ macro_rules.push_back (std::move (rule));
+
+ t = lexer.peek_token ();
+ }
+
+ // parse right curly
+ const_TokenPtr right_curly = expect_token (RIGHT_CURLY);
+ if (right_curly == nullptr)
+ {
+ return nullptr;
+ }
+
+ return std::unique_ptr<AST::MacroRulesDefinition> (
+ AST::MacroRulesDefinition::decl_macro (std::move (rule_name),
+ std::move (macro_rules),
+ std::move (outer_attrs),
+ macro_locus, vis));
+ }
+ else
+ {
+ add_error (Error (t->get_locus (),
+ "unexpected token %qs - expecting delimiters "
+ "(for a declarative macro definiton)",
+ t->get_token_description ()));
+ return nullptr;
+ }
+}
+
// Parses a semi-coloned (except for full block) macro invocation item.
template <typename ManagedTokenSource>
std::unique_ptr<AST::MacroInvocation>
@@ -1632,10 +1752,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation_semi (
{
// as this is the end, allow recovery (probably) - may change
- return std::unique_ptr<AST::MacroInvocation> (
- new AST::MacroInvocation (std::move (invoc_data),
- std::move (outer_attrs), macro_locus,
- true));
+ return AST::MacroInvocation::Regular (std::move (invoc_data),
+ std::move (outer_attrs),
+ macro_locus, true);
}
}
@@ -1644,9 +1763,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation_semi (
t->get_token_description (),
lexer.peek_token ()->get_token_description ());
- return std::unique_ptr<AST::MacroInvocation> (
- new AST::MacroInvocation (std::move (invoc_data),
- std::move (outer_attrs), macro_locus, true));
+ return AST::MacroInvocation::Regular (std::move (invoc_data),
+ std::move (outer_attrs),
+ macro_locus, true);
}
else
{
@@ -1694,10 +1813,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation (AST::AttrVec outer_attrs)
Location macro_locus = macro_path.get_locus ();
- return std::unique_ptr<AST::MacroInvocation> (
- new AST::MacroInvocation (AST::MacroInvocData (std::move (macro_path),
- std::move (delim_tok_tree)),
- std::move (outer_attrs), macro_locus));
+ return AST::MacroInvocation::Regular (
+ AST::MacroInvocData (std::move (macro_path), std::move (delim_tok_tree)),
+ std::move (outer_attrs), macro_locus);
}
// Parses a macro rule definition - does not parse semicolons.
@@ -6004,6 +6122,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
case STATIC_TOK:
case TRAIT:
case IMPL:
+ case MACRO:
/* 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. */
@@ -6012,14 +6131,22 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
/* if any of these (should be all possible VisItem prefixes), parse a
* VisItem can't parse item because would require reparsing outer
* attributes */
- return parse_vis_item (std::move (outer_attrs));
+ // may also be unsafe block
+ if (lexer.peek_token (1)->get_id () == LEFT_CURLY)
+ {
+ return parse_expr_stmt (std::move (outer_attrs), restrictions);
+ }
+ else
+ {
+ return parse_vis_item (std::move (outer_attrs));
+ }
break;
case SUPER:
case SELF:
case CRATE:
case DOLLAR_SIGN:
// almost certainly macro invocation semi
- return parse_macro_item (std::move (outer_attrs));
+ return parse_macro_invocation_semi (std::move (outer_attrs));
break;
// crappy hack to do union "keyword"
case IDENTIFIER:
@@ -6032,7 +6159,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
else if (t->get_str () == "macro_rules")
{
// macro_rules! macro item
- return parse_macro_item (std::move (outer_attrs));
+ return parse_macro_rules_def (std::move (outer_attrs));
}
else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION
|| lexer.peek_token (1)->get_id () == EXCLAM)
@@ -6040,7 +6167,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions)
// FIXME: ensure doesn't take any expressions by mistake
/* path (probably) or macro invocation, so probably a macro
* invocation semi */
- return parse_macro_item (std::move (outer_attrs));
+ return parse_macro_invocation_semi (std::move (outer_attrs));
}
gcc_fallthrough ();
// TODO: find out how to disable gcc "implicit fallthrough" warning
@@ -6190,7 +6317,9 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
// 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
auto next_tok = lexer.peek_token (1);
- if (next_tok->get_id () == EXCLAM)
+ if (next_tok->get_id () == LEFT_ANGLE
+ || next_tok->get_id () == SCOPE_RESOLUTION
+ || next_tok->get_id () == EXCLAM)
{
auto type = parse_type ();
if (type)
@@ -6198,6 +6327,23 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
else
return AST::GenericArg::create_error ();
}
+ else if (next_tok->get_id () == COLON)
+ {
+ lexer.skip_token (); // skip ident
+ lexer.skip_token (); // skip colon
+
+ auto tok = lexer.peek_token ();
+ std::vector<std::unique_ptr<AST::TypeParamBound>> bounds
+ = parse_type_param_bounds ();
+
+ auto type = std::unique_ptr<AST::TraitObjectType> (
+ new AST::TraitObjectType (std::move (bounds), tok->get_locus (),
+ false));
+ if (type)
+ return AST::GenericArg::create_type (std::move (type));
+ else
+ return AST::GenericArg::create_error ();
+ }
lexer.skip_token ();
return AST::GenericArg::create_ambiguous (tok->get_str (),
tok->get_locus ());
@@ -7050,18 +7196,9 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs,
}
}
case UNSAFE: {
- /* FIXME: are there any expressions without blocks that can have
- * unsafe as their first token? Or is unsafe the only one? */
- // safe side for now
- if (lexer.peek_token (1)->get_id () == LEFT_CURLY)
- {
- return parse_expr_stmt_with_block (std::move (outer_attrs));
- }
- else
- {
- return parse_expr_stmt_without_block (std::move (outer_attrs),
- restrictions);
- }
+ // unsafe block
+ // https://doc.rust-lang.org/reference/unsafe-keyword.html
+ return parse_expr_stmt_with_block (std::move (outer_attrs));
}
default:
// not a parse expr with block, so must be expr without block
@@ -7454,6 +7591,7 @@ Parser<ManagedTokenSource>::parse_closure_expr (AST::AttrVec outer_attrs)
case PIPE:
// actually may have parameters
lexer.skip_token ();
+ t = lexer.peek_token ();
while (t->get_id () != PIPE)
{
@@ -7470,6 +7608,7 @@ Parser<ManagedTokenSource>::parse_closure_expr (AST::AttrVec outer_attrs)
if (lexer.peek_token ()->get_id () != COMMA)
{
+ lexer.skip_token ();
// not an error but means param list is done
break;
}
@@ -9101,6 +9240,7 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
// raw pointer type
return parse_raw_pointer_type ();
case AMP: // does this also include AMP_AMP?
+ case LOGICAL_AND:
// reference type
return parse_reference_type ();
case LIFETIME: {
@@ -9170,11 +9310,10 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
AST::DelimTokenTree tok_tree = parse_delim_token_tree ();
- return std::unique_ptr<AST::MacroInvocation> (
- new AST::MacroInvocation (
- AST::MacroInvocData (std::move (macro_path),
- std::move (tok_tree)),
- {}, locus));
+ return AST::MacroInvocation::Regular (
+ AST::MacroInvocData (std::move (macro_path),
+ std::move (tok_tree)),
+ {}, locus);
}
case PLUS: {
// type param bounds
@@ -9751,14 +9890,10 @@ Parser<ManagedTokenSource>::parse_bare_function_type (
std::move (return_type), best_try_locus));
}
-// Parses a reference type (mutable or immutable, with given lifetime).
template <typename ManagedTokenSource>
std::unique_ptr<AST::ReferenceType>
-Parser<ManagedTokenSource>::parse_reference_type ()
+Parser<ManagedTokenSource>::parse_reference_type_inner (Location locus)
{
- Location locus = lexer.peek_token ()->get_locus ();
- skip_token (AMP);
-
// parse optional lifetime
AST::Lifetime lifetime = AST::Lifetime::error ();
if (lexer.peek_token ()->get_id () == LIFETIME)
@@ -9797,6 +9932,29 @@ Parser<ManagedTokenSource>::parse_reference_type ()
std::move (lifetime)));
}
+// Parses a reference type (mutable or immutable, with given lifetime).
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::ReferenceType>
+Parser<ManagedTokenSource>::parse_reference_type ()
+{
+ auto t = lexer.peek_token ();
+ auto locus = t->get_locus ();
+
+ switch (t->get_id ())
+ {
+ case AMP:
+ skip_token (AMP);
+ return parse_reference_type_inner (locus);
+ case LOGICAL_AND:
+ skip_token (LOGICAL_AND);
+ return std::unique_ptr<AST::ReferenceType> (
+ new AST::ReferenceType (false, parse_reference_type_inner (locus),
+ locus));
+ default:
+ gcc_unreachable ();
+ }
+}
+
// Parses a raw (unsafe) pointer type.
template <typename ManagedTokenSource>
std::unique_ptr<AST::RawPointerType>
@@ -9944,7 +10102,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
case ASTERISK:
// raw pointer type
return parse_raw_pointer_type ();
- case AMP: // does this also include AMP_AMP?
+ case AMP: // does this also include AMP_AMP? Yes! Which is... LOGICAL_AND?
+ case LOGICAL_AND:
// reference type
return parse_reference_type ();
case LIFETIME:
@@ -10008,11 +10167,10 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
AST::DelimTokenTree tok_tree = parse_delim_token_tree ();
- return std::unique_ptr<AST::MacroInvocation> (
- new AST::MacroInvocation (
- AST::MacroInvocData (std::move (macro_path),
- std::move (tok_tree)),
- {}, locus));
+ return AST::MacroInvocation::Regular (
+ AST::MacroInvocData (std::move (macro_path),
+ std::move (tok_tree)),
+ {}, locus);
}
default:
// assume that this is a type path and not an error
@@ -10767,6 +10925,15 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern ()
return std::unique_ptr<AST::TuplePattern> (
new AST::TuplePattern (std::move (items), paren_locus));
}
+ else if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
+ {
+ skip_token (RIGHT_PAREN);
+ auto items = std::unique_ptr<AST::TuplePatternItemsMultiple> (
+ new AST::TuplePatternItemsMultiple (
+ std::vector<std::unique_ptr<AST::Pattern>> ()));
+ return std::unique_ptr<AST::TuplePattern> (
+ new AST::TuplePattern (std::move (items), paren_locus));
+ }
// parse initial pattern (required)
std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern ();
@@ -11694,8 +11861,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr_without_block ()
else if (t->get_str () == "macro_rules")
{
// macro_rules! macro item
- std::unique_ptr<AST::MacroItem> item (
- parse_macro_item (std::move (outer_attrs)));
+ std::unique_ptr<AST::Item> item (
+ parse_macro_rules_def (std::move (outer_attrs)));
return ExprOrStmt (std::move (item));
}
else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION
@@ -11872,18 +12039,17 @@ Parser<ManagedTokenSource>::parse_path_based_stmt_or_expr (
{
lexer.skip_token ();
- std::unique_ptr<AST::MacroInvocation> stmt (
- new AST::MacroInvocation (std::move (invoc_data),
- std::move (outer_attrs),
- stmt_or_expr_loc, true));
+ auto stmt
+ = AST::MacroInvocation::Regular (std::move (invoc_data),
+ std::move (outer_attrs),
+ stmt_or_expr_loc, true);
return ExprOrStmt (std::move (stmt));
}
// otherwise, create macro invocation
- std::unique_ptr<AST::MacroInvocation> expr (
- new AST::MacroInvocation (std::move (invoc_data),
- std::move (outer_attrs),
- stmt_or_expr_loc, false));
+ auto expr = AST::MacroInvocation::Regular (std::move (invoc_data),
+ std::move (outer_attrs),
+ stmt_or_expr_loc, false);
return ExprOrStmt (std::move (expr));
}
else
@@ -12192,17 +12358,16 @@ Parser<ManagedTokenSource>::parse_macro_invocation_maybe_semi (
{
lexer.skip_token ();
- std::unique_ptr<AST::MacroInvocation> stmt (
- new AST::MacroInvocation (std::move (invoc_data),
- std::move (outer_attrs), macro_locus,
- true));
+ auto stmt = AST::MacroInvocation::Regular (std::move (invoc_data),
+ std::move (outer_attrs),
+ macro_locus, true);
return ExprOrStmt (std::move (stmt));
}
// otherwise, create macro invocation
- std::unique_ptr<AST::MacroInvocation> expr (
- new AST::MacroInvocation (std::move (invoc_data),
- std::move (outer_attrs), macro_locus));
+ auto expr
+ = AST::MacroInvocation::Regular (std::move (invoc_data),
+ std::move (outer_attrs), macro_locus);
return ExprOrStmt (std::move (expr));
}
else
@@ -12883,6 +13048,12 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
case UNSAFE:
return parse_unsafe_block_expr (std::move (outer_attrs),
tok->get_locus ());
+ case UNDERSCORE:
+ add_error (
+ Error (tok->get_locus (),
+ "use of %qs is not allowed on the right-side of an assignment",
+ tok->get_token_description ()));
+ return nullptr;
default:
if (!restrictions.expr_can_be_null)
add_error (Error (tok->get_locus (),
@@ -14408,9 +14579,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation_partial (
Location macro_locus = converted_path.get_locus ();
- return std::unique_ptr<AST::MacroInvocation> (new AST::MacroInvocation (
+ return AST::MacroInvocation::Regular (
AST::MacroInvocData (std::move (converted_path), std::move (tok_tree)),
- std::move (outer_attrs), macro_locus, restrictions.expr_can_be_stmt));
+ std::move (outer_attrs), macro_locus, restrictions.expr_can_be_stmt);
}
/* Parses a struct expr struct with a path in expression already parsed (but
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 8449181..a4b65c5 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -150,6 +150,8 @@ public:
std::unique_ptr<AST::TokenTree> parse_token_tree ();
AST::Attribute parse_attribute_body ();
AST::AttrVec parse_inner_attributes ();
+ std::unique_ptr<AST::MacroInvocation>
+ parse_macro_invocation (AST::AttrVec outer_attrs);
private:
void skip_after_semicolon ();
@@ -197,10 +199,10 @@ private:
AST::DelimTokenTree parse_delim_token_tree ();
std::unique_ptr<AST::MacroRulesDefinition>
parse_macro_rules_def (AST::AttrVec outer_attrs);
+ std::unique_ptr<AST::MacroRulesDefinition>
+ parse_decl_macro_def (AST::Visibility vis, AST::AttrVec outer_attrs);
std::unique_ptr<AST::MacroInvocation>
parse_macro_invocation_semi (AST::AttrVec outer_attrs);
- std::unique_ptr<AST::MacroInvocation>
- parse_macro_invocation (AST::AttrVec outer_attrs);
AST::MacroRule parse_macro_rule ();
AST::MacroMatcher parse_macro_matcher ();
std::unique_ptr<AST::MacroMatch> parse_macro_match ();
@@ -209,7 +211,6 @@ private:
// Top-level item-related
std::unique_ptr<AST::VisItem> parse_vis_item (AST::AttrVec outer_attrs);
- std::unique_ptr<AST::MacroItem> parse_macro_item (AST::AttrVec outer_attrs);
// VisItem subclass-related
std::unique_ptr<AST::Module> parse_module (AST::Visibility vis,
@@ -603,6 +604,8 @@ private:
std::unique_ptr<AST::TypeNoBounds> parse_type_no_bounds ();
std::unique_ptr<AST::TypeNoBounds> parse_slice_or_array_type ();
std::unique_ptr<AST::RawPointerType> parse_raw_pointer_type ();
+ std::unique_ptr<AST::ReferenceType>
+ parse_reference_type_inner (Location locus);
std::unique_ptr<AST::ReferenceType> parse_reference_type ();
std::unique_ptr<AST::BareFunctionType>
parse_bare_function_type (std::vector<AST::LifetimeParam> for_lifetimes);
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc
index 0a78d26..5b3f4a0 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-base.cc
@@ -583,6 +583,10 @@ ResolverBase::visit (AST::SlicePattern &)
{}
void
+ResolverBase::visit (AST::AltPattern &)
+{}
+
+void
ResolverBase::visit (AST::EmptyStmt &)
{}
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h
index 9d88f8f..aab1324 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.h
+++ b/gcc/rust/resolve/rust-ast-resolve-base.h
@@ -178,6 +178,7 @@ public:
void visit (AST::TuplePattern &);
void visit (AST::GroupedPattern &);
void visit (AST::SlicePattern &);
+ void visit (AST::AltPattern &);
void visit (AST::EmptyStmt &);
void visit (AST::LetStmt &);
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h
index 5f2b729..4c7d13a 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.h
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h
@@ -70,11 +70,9 @@ public:
pattern.get_node_id (), pattern.get_locus (), type);
}
- void visit (AST::WildcardPattern &pattern) override
+ void visit (AST::GroupedPattern &pattern) override
{
- resolver->get_name_scope ().insert (
- CanonicalPath::new_seg (pattern.get_node_id (), "_"),
- pattern.get_node_id (), pattern.get_locus (), type);
+ pattern.get_pattern_in_parens ()->accept_vis (*this);
}
// cases in a match expression
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
index 16d05f3..28ab069 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -589,6 +589,11 @@ ResolveGenericArgs::go (AST::GenericArgs &generic_args,
resolver.resolve_disambiguated_generic (arg);
}
+
+ for (auto &binding : generic_args.get_binding_args ())
+ {
+ ResolveType::go (binding.get_type ().get ());
+ }
}
} // namespace Resolver
diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc
index 8100564..f5054f9 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -24,20 +24,17 @@ namespace Rust {
namespace Resolver {
EarlyNameResolver::EarlyNameResolver ()
- : resolver (*Resolver::get ()), mappings (*Analysis::Mappings::get ())
+ : current_scope (UNKNOWN_NODEID), resolver (*Resolver::get ()),
+ mappings (*Analysis::Mappings::get ())
{}
void
EarlyNameResolver::go (AST::Crate &crate)
{
- // FIXME: Is that valid? Why is the regular name resolution doing
- // mappings->get_next_node_id()?
- resolver.get_macro_scope ().push (crate.get_node_id ());
-
- for (auto &item : crate.items)
- item->accept_vis (*this);
-
- // FIXME: Should we pop the macro scope?
+ scoped (crate.get_node_id (), [&crate, this] () {
+ for (auto &item : crate.items)
+ item->accept_vis (*this);
+ });
}
void
@@ -335,11 +332,13 @@ EarlyNameResolver::visit (AST::ClosureExprInner &expr)
void
EarlyNameResolver::visit (AST::BlockExpr &expr)
{
- for (auto &stmt : expr.get_statements ())
- stmt->accept_vis (*this);
+ scoped (expr.get_node_id (), [&expr, this] () {
+ for (auto &stmt : expr.get_statements ())
+ stmt->accept_vis (*this);
- if (expr.has_tail_expr ())
- expr.get_tail_expr ()->accept_vis (*this);
+ if (expr.has_tail_expr ())
+ expr.get_tail_expr ()->accept_vis (*this);
+ });
}
void
@@ -434,8 +433,11 @@ EarlyNameResolver::visit (AST::WhileLetLoopExpr &expr)
void
EarlyNameResolver::visit (AST::ForLoopExpr &expr)
{
- expr.get_iterator_expr ()->accept_vis (*this);
- expr.get_loop_block ()->accept_vis (*this);
+ scoped (expr.get_node_id (), [&expr, this] () {
+ expr.get_pattern ()->accept_vis (*this);
+ expr.get_iterator_expr ()->accept_vis (*this);
+ expr.get_loop_block ()->accept_vis (*this);
+ });
}
void
@@ -473,7 +475,9 @@ void
EarlyNameResolver::visit (AST::IfLetExpr &expr)
{
expr.get_value_expr ()->accept_vis (*this);
- expr.get_if_block ()->accept_vis (*this);
+
+ scoped (expr.get_node_id (),
+ [&expr, this] () { expr.get_if_block ()->accept_vis (*this); });
}
void
@@ -504,16 +508,21 @@ void
EarlyNameResolver::visit (AST::MatchExpr &expr)
{
expr.get_scrutinee_expr ()->accept_vis (*this);
- for (auto &match_arm : expr.get_match_cases ())
- {
- if (match_arm.get_arm ().has_match_arm_guard ())
- match_arm.get_arm ().get_guard_expr ()->accept_vis (*this);
- for (auto &pattern : match_arm.get_arm ().get_patterns ())
- pattern->accept_vis (*this);
+ scoped (expr.get_node_id (), [&expr, this] () {
+ for (auto &arm : expr.get_match_cases ())
+ {
+ scoped (arm.get_node_id (), [&arm, this] () {
+ if (arm.get_arm ().has_match_arm_guard ())
+ arm.get_arm ().get_guard_expr ()->accept_vis (*this);
- match_arm.get_expr ()->accept_vis (*this);
- }
+ for (auto &pattern : arm.get_arm ().get_patterns ())
+ pattern->accept_vis (*this);
+
+ arm.get_expr ()->accept_vis (*this);
+ });
+ }
+ });
}
void
@@ -571,8 +580,10 @@ EarlyNameResolver::visit (AST::Method &method)
void
EarlyNameResolver::visit (AST::Module &module)
{
- for (auto &item : module.get_items ())
- item->accept_vis (*this);
+ scoped (module.get_node_id (), [&module, this] () {
+ for (auto &item : module.get_items ())
+ item->accept_vis (*this);
+ });
}
void
@@ -722,8 +733,13 @@ EarlyNameResolver::visit (AST::TraitItemType &)
void
EarlyNameResolver::visit (AST::Trait &trait)
{
- for (auto &item : trait.get_trait_items ())
- item->accept_vis (*this);
+ for (auto &generic : trait.get_generic_params ())
+ generic->accept_vis (*this);
+
+ scoped (trait.get_node_id (), [&trait, this] () {
+ for (auto &item : trait.get_trait_items ())
+ item->accept_vis (*this);
+ });
}
void
@@ -734,8 +750,10 @@ EarlyNameResolver::visit (AST::InherentImpl &impl)
for (auto &generic : impl.get_generic_params ())
generic->accept_vis (*this);
- for (auto &item : impl.get_impl_items ())
- item->accept_vis (*this);
+ scoped (impl.get_node_id (), [&impl, this] () {
+ for (auto &item : impl.get_impl_items ())
+ item->accept_vis (*this);
+ });
}
void
@@ -746,8 +764,10 @@ EarlyNameResolver::visit (AST::TraitImpl &impl)
for (auto &generic : impl.get_generic_params ())
generic->accept_vis (*this);
- for (auto &item : impl.get_impl_items ())
- item->accept_vis (*this);
+ scoped (impl.get_node_id (), [&impl, this] () {
+ for (auto &item : impl.get_impl_items ())
+ item->accept_vis (*this);
+ });
}
void
@@ -772,8 +792,10 @@ EarlyNameResolver::visit (AST::ExternalFunctionItem &item)
void
EarlyNameResolver::visit (AST::ExternBlock &block)
{
- for (auto &item : block.get_extern_items ())
- item->accept_vis (*this);
+ scoped (block.get_node_id (), [&block, this] () {
+ for (auto &item : block.get_extern_items ())
+ item->accept_vis (*this);
+ });
}
void
@@ -795,6 +817,15 @@ EarlyNameResolver::visit (AST::MacroRulesDefinition &rules_def)
rules_def.get_rule_name ());
resolver.get_macro_scope ().insert (path, rules_def.get_node_id (),
rules_def.get_locus ());
+
+ /* Since the EarlyNameResolver runs multiple time (fixed point algorithm)
+ * we could be inserting the same macro def over and over again until we
+ * implement some optimizations */
+ // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead
+ AST::MacroRulesDefinition *tmp = nullptr;
+ if (mappings.lookup_macro_def (rules_def.get_node_id (), &tmp))
+ return;
+
mappings.insert_macro_def (&rules_def);
rust_debug_loc (rules_def.get_locus (), "inserting macro def: [%s]",
path.get ().c_str ());
@@ -806,6 +837,10 @@ EarlyNameResolver::visit (AST::MacroInvocation &invoc)
auto &invoc_data = invoc.get_invoc_data ();
auto has_semicolon = invoc.has_semicolon ();
+ if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
+ for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
+ pending_invoc->accept_vis (*this);
+
// ??
// switch on type of macro:
// - '!' syntax macro (inner switch)
@@ -847,6 +882,30 @@ EarlyNameResolver::visit (AST::MacroInvocation &invoc)
bool ok = mappings.lookup_macro_def (resolved_node, &rules_def);
rust_assert (ok);
+ auto &outer_attrs = rules_def->get_outer_attrs ();
+ bool is_builtin
+ = std::any_of (outer_attrs.begin (), outer_attrs.end (),
+ [] (AST::Attribute attr) {
+ return attr.get_path () == "rustc_builtin_macro";
+ });
+
+ if (is_builtin)
+ {
+ auto builtin_kind
+ = AST::builtin_macro_from_string (rules_def->get_rule_name ());
+ invoc.map_to_builtin (builtin_kind);
+ }
+
+ auto attributes = rules_def->get_outer_attrs ();
+
+ /* Since the EarlyNameResolver runs multiple time (fixed point algorithm)
+ * we could be inserting the same macro def over and over again until we
+ * implement some optimizations */
+ // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead
+ AST::MacroRulesDefinition *tmp_def = nullptr;
+ if (mappings.lookup_macro_invocation (invoc, &tmp_def))
+ return;
+
mappings.insert_macro_invocation (invoc, rules_def);
}
@@ -994,6 +1053,13 @@ EarlyNameResolver::visit (AST::SlicePattern &pattern)
}
void
+EarlyNameResolver::visit (AST::AltPattern &pattern)
+{
+ for (auto &alt : pattern.get_alts ())
+ alt->accept_vis (*this);
+}
+
+void
EarlyNameResolver::visit (AST::EmptyStmt &)
{}
diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h
index c53ab9f..84ee518 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.h
+++ b/gcc/rust/resolve/rust-early-name-resolver.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -35,6 +35,71 @@ public:
void go (AST::Crate &crate);
private:
+ /**
+ * Execute a lambda within a scope. This is equivalent to calling
+ * `enter_scope` before your code and `exit_scope` after. This ensures
+ * no errors can be committed
+ */
+ void scoped (NodeId scope_id, std::function<void ()> fn)
+ {
+ auto old_scope = current_scope;
+ current_scope = scope_id;
+ resolver.get_macro_scope ().push (scope_id);
+ resolver.push_new_macro_rib (resolver.get_macro_scope ().peek ());
+
+ fn ();
+
+ resolver.get_macro_scope ().pop ();
+ current_scope = old_scope;
+ }
+
+ /**
+ * The "scope" we are currently in.
+ *
+ * This involves lexical scopes:
+ *
+ * ```rust
+ * // current_scope = crate_id;
+ * macro_rules! foo { () => {} )
+ *
+ * {
+ * // current_scope = current_block_id;
+ * macro_rules! foo { () => { something!(); } }
+ * }
+ * // current_scope = crate_id;
+ * ```
+ *
+ * as well as any sort of scope-like structure that might impact import name
+ * resolution or macro name resolution:
+ *
+ * ```rust
+ * macro_rules! foo {
+ * () => { fn empty() {} }
+ * }
+ *
+ *
+ * trait Foo {
+ * fn foo() {
+ * fn inner_foo() {
+ * macro_rules! foo { () => {} )
+ *
+ * foo!();
+ * }
+ *
+ * foo!();
+ * }
+ *
+ * foo!();
+ * }
+ *
+ * foo!();
+ * ```
+ */
+ NodeId current_scope;
+
+ /* The crate's scope */
+ NodeId crate_scope;
+
Resolver &resolver;
Analysis::Mappings &mappings;
@@ -184,6 +249,7 @@ private:
virtual void visit (AST::TuplePattern &pattern);
virtual void visit (AST::GroupedPattern &pattern);
virtual void visit (AST::SlicePattern &pattern);
+ virtual void visit (AST::AltPattern &pattern);
virtual void visit (AST::EmptyStmt &stmt);
virtual void visit (AST::LetStmt &stmt);
virtual void visit (AST::ExprStmtWithoutBlock &stmt);
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index 01c5fc4..076104f 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -26,7 +26,7 @@
#include "rust-location.h"
#include "rust-linemap.h"
#include "rust-diagnostics.h"
-#include "operator.h"
+#include "util/rust-operators.h"
#include "tree.h"
// Pointers to these types are created by the backend, passed to the
diff --git a/gcc/rust/rust-diagnostics.cc b/gcc/rust/rust-diagnostics.cc
index c0f02c2..4e5c2ec 100644
--- a/gcc/rust/rust-diagnostics.cc
+++ b/gcc/rust/rust-diagnostics.cc
@@ -231,14 +231,49 @@ rust_debug_loc (const Location location, const char *fmt, ...)
}
namespace Rust {
-Error::Error (const Location location, const char *fmt, ...) : locus (location)
+
+/**
+ * This function takes ownership of `args` and calls `va_end` on it
+ */
+static Error
+va_constructor (Error::Kind kind, Location locus, const char *fmt, va_list args)
+ RUST_ATTRIBUTE_GCC_DIAG (3, 0);
+
+static Error
+va_constructor (Error::Kind kind, Location locus, const char *fmt, va_list args)
+{
+ std::string message = expand_message (fmt, args);
+ message.shrink_to_fit ();
+ va_end (args);
+
+ return Error (kind, locus, message);
+}
+
+Error::Error (const Location location, const char *fmt, ...)
+ : kind (Kind::Err), locus (location)
{
va_list ap;
+ va_start (ap, fmt);
+ *this = va_constructor (Kind::Err, location, fmt, ap);
+}
+
+Error
+Error::Hint (const Location location, const char *fmt, ...)
+{
+ va_list ap;
va_start (ap, fmt);
- message = expand_message (fmt, ap);
- va_end (ap);
- message.shrink_to_fit ();
+ return va_constructor (Kind::Hint, location, fmt, ap);
+}
+
+Error
+Error::Fatal (const Location location, const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+
+ return va_constructor (Kind::FatalErr, location, fmt, ap);
}
+
} // namespace Rust
diff --git a/gcc/rust/rust-diagnostics.h b/gcc/rust/rust-diagnostics.h
index 900198e..43fee8b 100644
--- a/gcc/rust/rust-diagnostics.h
+++ b/gcc/rust/rust-diagnostics.h
@@ -114,27 +114,69 @@ namespace Rust {
* errors to be ignored, e.g. if backtracking. */
struct Error
{
+ enum class Kind
+ {
+ Hint,
+ Err,
+ FatalErr,
+ };
+
+ Kind kind;
Location locus;
std::string message;
// TODO: store more stuff? e.g. node id?
- Error (Location locus, std::string message)
- : locus (locus), message (std::move (message))
+ Error (Kind kind, Location locus, std::string message)
+ : kind (kind), locus (locus), message (std::move (message))
{
message.shrink_to_fit ();
}
+ Error (Location locus, std::string message)
+ {
+ Error (Kind::Err, locus, std::move (message));
+ }
+
+ static Error Hint (Location locus, std::string message)
+ {
+ return Error (Kind::Hint, locus, std::move (message));
+ }
+
+ static Error Fatal (Location locus, std::string message)
+ {
+ return Error (Kind::FatalErr, locus, std::move (message));
+ }
+
// TODO: the attribute part might be incorrect
Error (Location locus, const char *fmt,
...) /*RUST_ATTRIBUTE_GCC_DIAG (2, 3)*/ RUST_ATTRIBUTE_GCC_DIAG (3, 4);
- // Irreversibly emits the error as an error.
- void emit_error () const { rust_error_at (locus, "%s", message.c_str ()); }
+ /**
+ * printf-like overload of Error::Hint
+ */
+ static Error Hint (Location locus, const char *fmt, ...)
+ RUST_ATTRIBUTE_GCC_DIAG (2, 3);
+
+ /**
+ * printf-like overload of Error::Fatal
+ */
+ static Error Fatal (Location locus, const char *fmt, ...)
+ RUST_ATTRIBUTE_GCC_DIAG (2, 3);
- // Irreversibly emits the error as a fatal error.
- void emit_fatal_error () const
+ void emit () const
{
- rust_fatal_error (locus, "%s", message.c_str ());
+ switch (kind)
+ {
+ case Kind::Hint:
+ rust_inform (locus, "%s", message.c_str ());
+ break;
+ case Kind::Err:
+ rust_error_at (locus, "%s", message.c_str ());
+ break;
+ case Kind::FatalErr:
+ rust_fatal_error (locus, "%s", message.c_str ());
+ break;
+ }
}
};
} // namespace Rust
diff --git a/gcc/rust/rust-gcc.h b/gcc/rust/rust-gcc.h
index 085c16d..0db8194 100644
--- a/gcc/rust/rust-gcc.h
+++ b/gcc/rust/rust-gcc.h
@@ -1,5 +1,5 @@
// rust-gcc.cc -- Rust frontend to gcc IR.
-// Copyright (C) 2011-2022 Free Software Foundation, Inc.
+// Copyright (C) 2011-2023 Free Software Foundation, Inc.
// Contributed by Ian Lance Taylor, Google.
// forked from gccgo
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 732aabe..074bad9 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -27,6 +27,7 @@
#include "rust-hir-type-check.h"
#include "rust-privacy-check.h"
#include "rust-const-checker.h"
+#include "rust-feature-gate.h"
#include "rust-tycheck-dump.h"
#include "rust-compile.h"
#include "rust-cfg-parser.h"
@@ -192,7 +193,7 @@ Session::handle_option (
else
{
rust_assert (!error.message.empty ());
- error.emit_error ();
+ error.emit ();
}
}
else
@@ -390,7 +391,7 @@ Session::handle_crate_name (const AST::Crate &parsed_crate)
if (!validate_crate_name (msg_str, error))
{
error.locus = attr.get_locus ();
- error.emit_error ();
+ error.emit ();
continue;
}
@@ -411,7 +412,7 @@ Session::handle_crate_name (const AST::Crate &parsed_crate)
if (!options.crate_name_set_manually
&& !validate_crate_name (options.crate_name, error))
{
- error.emit_error ();
+ error.emit ();
rust_inform (linemap->get_location (0),
"crate name inferred from this file");
}
@@ -438,9 +439,9 @@ Session::compile_crate (const char *filename)
"manner by passing the following flag:\n\n"
"`-frust-incomplete-and-experimental-compiler-do-not-use`\n\nor by "
"defining the following environment variable (any value will "
- "do)\n\nGCCRS_INCOMPLETE_AND_EXPERIMENTAL_COMPILER_DO_NOT_USE\n\nFor"
+ "do)\n\nGCCRS_INCOMPLETE_AND_EXPERIMENTAL_COMPILER_DO_NOT_USE\n\nFor "
"cargo-gccrs, this means passing\n\n"
- "GCCRS_EXTRA_FLAGS=\"-frust-incomplete-and-experimental-compiler-do-not-"
+ "GCCRS_EXTRA_ARGS=\"-frust-incomplete-and-experimental-compiler-do-not-"
"use\"\n\nas an environment variable.");
RAIIFile file_wrap (filename);
@@ -558,6 +559,9 @@ Session::compile_crate (const char *filename)
rust_debug ("END POST-EXPANSION AST DUMP");
}
+ // feature gating
+ FeatureGate ().check (parsed_crate);
+
if (last_step == CompileOptions::CompileStep::NameResolution)
return;
@@ -817,9 +821,6 @@ Session::injection (AST::Crate &crate)
void
Session::expansion (AST::Crate &crate)
{
- /* We need to name resolve macros and imports here */
- Resolver::EarlyNameResolver ().go (crate);
-
rust_debug ("started expansion");
/* rustc has a modification to windows PATH temporarily here, which may end
@@ -829,11 +830,41 @@ Session::expansion (AST::Crate &crate)
// if not, would at least have to configure recursion_limit
ExpansionCfg cfg;
+ auto fixed_point_reached = false;
+ unsigned iterations = 0;
+
// create extctxt? from parse session, cfg, and resolver?
/* expand by calling cxtctxt object's monotonic_expander's expand_crate
* method. */
MacroExpander expander (crate, cfg, *this);
- expander.expand_crate ();
+
+ while (!fixed_point_reached && iterations < cfg.recursion_limit)
+ {
+ /* We need to name resolve macros and imports here */
+ Resolver::EarlyNameResolver ().go (crate);
+
+ expander.expand_crate ();
+
+ fixed_point_reached = !expander.has_changed ();
+ expander.reset_changed_state ();
+ iterations++;
+
+ if (saw_errors ())
+ break;
+ }
+
+ if (iterations == cfg.recursion_limit)
+ {
+ auto last_invoc = expander.get_last_invocation ();
+ auto last_def = expander.get_last_definition ();
+
+ rust_assert (last_def && last_invoc);
+
+ RichLocation range (last_invoc->get_locus ());
+ range.add_range (last_def->get_locus ());
+
+ rust_error_at (range, "reached recursion limit");
+ }
// error reporting - check unused macros, get missing fragment specifiers
diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc
index fdf8eb9..bea4084 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -18,6 +18,7 @@
#include "rust-hir-type-check-base.h"
#include "rust-coercion.h"
+#include "rust-unify.h"
namespace Rust {
namespace Resolver {
@@ -218,7 +219,10 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver,
// we might be able to replace this with a can_eq because we default
// back to a final unity anyway
rust_debug ("coerce_borrowed_pointer -- unify");
- TyTy::BaseType *result = receiver->unify (expected);
+ TyTy::BaseType *result
+ = UnifyRules::Resolve (TyTy::TyWithLocation (receiver),
+ TyTy::TyWithLocation (expected), locus,
+ true /* commit */, true /* emit_errors */);
return CoercionResult{{}, result};
}
}
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc
index cb3270d..dae4c01 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.cc
+++ b/gcc/rust/typecheck/rust-hir-path-probe.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -18,10 +18,277 @@
#include "rust-hir-path-probe.h"
#include "rust-hir-type-check-item.h"
+#include "rust-hir-trait-resolve.h"
namespace Rust {
namespace Resolver {
+// PathProbeCandidate
+
+PathProbeCandidate::Candidate::Candidate (EnumItemCandidate enum_field)
+ : enum_field (enum_field)
+{}
+
+PathProbeCandidate::Candidate::Candidate (ImplItemCandidate impl) : impl (impl)
+{}
+
+PathProbeCandidate::Candidate::Candidate (TraitItemCandidate trait)
+ : trait (trait)
+{}
+
+PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
+ Location locus,
+ EnumItemCandidate enum_field)
+ : type (type), ty (ty), locus (locus), item (enum_field)
+{}
+
+PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
+ Location locus, ImplItemCandidate impl)
+ : type (type), ty (ty), locus (locus), item (impl)
+{}
+
+PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
+ Location locus,
+ TraitItemCandidate trait)
+ : type (type), ty (ty), locus (locus), item (trait)
+{}
+
+std::string
+PathProbeCandidate::as_string () const
+{
+ return "PathProbe candidate TODO - as_string";
+}
+
+bool
+PathProbeCandidate::is_enum_candidate () const
+{
+ return type == ENUM_VARIANT;
+}
+
+bool
+PathProbeCandidate::is_impl_candidate () const
+{
+ return type == IMPL_CONST || type == IMPL_TYPE_ALIAS || type == IMPL_FUNC;
+}
+
+bool
+PathProbeCandidate::is_trait_candidate () const
+{
+ return type == TRAIT_ITEM_CONST || type == TRAIT_TYPE_ALIAS
+ || type == TRAIT_FUNC;
+}
+
+bool
+PathProbeCandidate::is_full_trait_item_candidate () const
+{
+ return is_trait_candidate () && item.trait.impl == nullptr;
+}
+
+PathProbeCandidate
+PathProbeCandidate::get_error ()
+{
+ return PathProbeCandidate (ERROR, nullptr, Location (),
+ ImplItemCandidate{nullptr, nullptr});
+}
+
+bool
+PathProbeCandidate::is_error () const
+{
+ return type == ERROR;
+}
+
+DefId
+PathProbeCandidate::get_defid () const
+{
+ switch (type)
+ {
+ case ENUM_VARIANT:
+ return item.enum_field.variant->get_defid ();
+ break;
+
+ case IMPL_CONST:
+ case IMPL_TYPE_ALIAS:
+ case IMPL_FUNC:
+ return item.impl.impl_item->get_impl_mappings ().get_defid ();
+ break;
+
+ case TRAIT_ITEM_CONST:
+ case TRAIT_TYPE_ALIAS:
+ case TRAIT_FUNC:
+ return item.trait.item_ref->get_mappings ().get_defid ();
+ break;
+
+ case ERROR:
+ default:
+ return UNKNOWN_DEFID;
+ }
+
+ return UNKNOWN_DEFID;
+}
+
+bool
+PathProbeCandidate::operator< (const PathProbeCandidate &c) const
+{
+ return get_defid () < c.get_defid ();
+}
+
+// PathProbeType
+
+PathProbeType::PathProbeType (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &query,
+ DefId specific_trait_id)
+ : TypeCheckBase (), receiver (receiver), search (query),
+ current_impl (nullptr), specific_trait_id (specific_trait_id)
+{}
+
+std::set<PathProbeCandidate>
+PathProbeType::Probe (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &segment_name,
+ bool probe_impls, bool probe_bounds,
+ bool ignore_mandatory_trait_items,
+ DefId specific_trait_id)
+{
+ PathProbeType probe (receiver, segment_name, specific_trait_id);
+ if (probe_impls)
+ {
+ if (receiver->get_kind () == TyTy::TypeKind::ADT)
+ {
+ const TyTy::ADTType *adt
+ = static_cast<const TyTy::ADTType *> (receiver);
+ if (adt->is_enum ())
+ probe.process_enum_item_for_candiates (adt);
+ }
+
+ probe.process_impl_items_for_candidates ();
+ }
+
+ if (!probe_bounds)
+ return probe.candidates;
+
+ if (!probe.is_reciever_generic ())
+ {
+ std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> probed_bounds
+ = TypeBoundsProbe::Probe (receiver);
+ for (auto &candidate : probed_bounds)
+ {
+ const TraitReference *trait_ref = candidate.first;
+ if (specific_trait_id != UNKNOWN_DEFID)
+ {
+ if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
+ continue;
+ }
+
+ HIR::ImplBlock *impl = candidate.second;
+ probe.process_associated_trait_for_candidates (
+ trait_ref, impl, ignore_mandatory_trait_items);
+ }
+ }
+
+ for (const TyTy::TypeBoundPredicate &predicate :
+ receiver->get_specified_bounds ())
+ {
+ const TraitReference *trait_ref = predicate.get ();
+ if (specific_trait_id != UNKNOWN_DEFID)
+ {
+ if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
+ continue;
+ }
+
+ probe.process_predicate_for_candidates (predicate,
+ ignore_mandatory_trait_items);
+ }
+
+ return probe.candidates;
+}
+
+void
+PathProbeType::visit (HIR::TypeAlias &alias)
+{
+ Identifier name = alias.get_new_type_name ();
+ if (search.as_string ().compare (name) == 0)
+ {
+ HirId tyid = alias.get_mappings ().get_hirid ();
+ TyTy::BaseType *ty = nullptr;
+ bool ok = query_type (tyid, &ty);
+ rust_assert (ok);
+
+ PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias,
+ current_impl};
+ PathProbeCandidate candidate{
+ PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, ty,
+ alias.get_locus (), impl_item_candidate};
+ candidates.insert (std::move (candidate));
+ }
+}
+
+void
+PathProbeType::visit (HIR::ConstantItem &constant)
+{
+ Identifier name = constant.get_identifier ();
+ if (search.as_string ().compare (name) == 0)
+ {
+ HirId tyid = constant.get_mappings ().get_hirid ();
+ TyTy::BaseType *ty = nullptr;
+ bool ok = query_type (tyid, &ty);
+ rust_assert (ok);
+
+ PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant,
+ current_impl};
+ PathProbeCandidate candidate{
+ PathProbeCandidate::CandidateType::IMPL_CONST, ty,
+ constant.get_locus (), impl_item_candidate};
+ candidates.insert (std::move (candidate));
+ }
+}
+
+void
+PathProbeType::visit (HIR::Function &function)
+{
+ Identifier name = function.get_function_name ();
+ if (search.as_string ().compare (name) == 0)
+ {
+ HirId tyid = function.get_mappings ().get_hirid ();
+ TyTy::BaseType *ty = nullptr;
+ bool ok = query_type (tyid, &ty);
+ rust_assert (ok);
+
+ PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function,
+ current_impl};
+ PathProbeCandidate candidate{PathProbeCandidate::CandidateType::IMPL_FUNC,
+ ty, function.get_locus (),
+ impl_item_candidate};
+ candidates.insert (std::move (candidate));
+ }
+}
+
+void
+PathProbeType::process_enum_item_for_candiates (const TyTy::ADTType *adt)
+{
+ if (specific_trait_id != UNKNOWN_DEFID)
+ return;
+
+ TyTy::VariantDef *v;
+ if (!adt->lookup_variant (search.as_string (), &v))
+ return;
+
+ PathProbeCandidate::EnumItemCandidate enum_item_candidate{adt, v};
+ PathProbeCandidate candidate{PathProbeCandidate::CandidateType::ENUM_VARIANT,
+ receiver->clone (),
+ mappings->lookup_location (adt->get_ty_ref ()),
+ enum_item_candidate};
+ candidates.insert (std::move (candidate));
+}
+
+void
+PathProbeType::process_impl_items_for_candidates ()
+{
+ mappings->iterate_impl_items (
+ [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
+ process_impl_item_candidate (id, item, impl);
+ return true;
+ });
+}
+
void
PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item,
HIR::ImplBlock *impl)
@@ -42,5 +309,191 @@ PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item,
item->accept_vis (*this);
}
+void
+PathProbeType::process_associated_trait_for_candidates (
+ const TraitReference *trait_ref, HIR::ImplBlock *impl,
+ bool ignore_mandatory_trait_items)
+{
+ const TraitItemReference *trait_item_ref = nullptr;
+ if (!trait_ref->lookup_trait_item (search.as_string (), &trait_item_ref))
+ return;
+
+ bool trait_item_needs_implementation = !trait_item_ref->is_optional ();
+ if (ignore_mandatory_trait_items && trait_item_needs_implementation)
+ return;
+
+ PathProbeCandidate::CandidateType candidate_type;
+ switch (trait_item_ref->get_trait_item_type ())
+ {
+ case TraitItemReference::TraitItemType::FN:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
+ break;
+ case TraitItemReference::TraitItemType::CONST:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
+ break;
+ case TraitItemReference::TraitItemType::TYPE:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
+ break;
+
+ case TraitItemReference::TraitItemType::ERROR:
+ default:
+ gcc_unreachable ();
+ break;
+ }
+
+ TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ();
+
+ // we can substitute the Self with the receiver here
+ if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF)
+ {
+ TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty);
+ TyTy::SubstitutionParamMapping *param = nullptr;
+ for (auto &param_mapping : fn->get_substs ())
+ {
+ const HIR::TypeParam &type_param = param_mapping.get_generic_param ();
+ if (type_param.get_type_representation ().compare ("Self") == 0)
+ {
+ param = &param_mapping;
+ break;
+ }
+ }
+ rust_assert (param != nullptr);
+
+ std::vector<TyTy::SubstitutionArg> mappings;
+ mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ()));
+
+ Location locus; // FIXME
+ TyTy::SubstitutionArgumentMappings args (std::move (mappings), {}, locus);
+ trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args);
+ }
+
+ PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
+ trait_item_ref,
+ impl};
+
+ PathProbeCandidate candidate{candidate_type, trait_item_tyty,
+ trait_item_ref->get_locus (),
+ trait_item_candidate};
+ candidates.insert (std::move (candidate));
+}
+
+void
+PathProbeType::process_predicate_for_candidates (
+ const TyTy::TypeBoundPredicate &predicate, bool ignore_mandatory_trait_items)
+{
+ const TraitReference *trait_ref = predicate.get ();
+
+ TyTy::TypeBoundPredicateItem item
+ = predicate.lookup_associated_item (search.as_string ());
+ if (item.is_error ())
+ return;
+
+ if (ignore_mandatory_trait_items && item.needs_implementation ())
+ return;
+
+ const TraitItemReference *trait_item_ref = item.get_raw_item ();
+ PathProbeCandidate::CandidateType candidate_type;
+ switch (trait_item_ref->get_trait_item_type ())
+ {
+ case TraitItemReference::TraitItemType::FN:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
+ break;
+ case TraitItemReference::TraitItemType::CONST:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
+ break;
+ case TraitItemReference::TraitItemType::TYPE:
+ candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
+ break;
+
+ case TraitItemReference::TraitItemType::ERROR:
+ default:
+ gcc_unreachable ();
+ break;
+ }
+
+ TyTy::BaseType *trait_item_tyty = item.get_tyty_for_receiver (receiver);
+ PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
+ trait_item_ref,
+ nullptr};
+ PathProbeCandidate candidate{candidate_type, trait_item_tyty,
+ trait_item_ref->get_locus (),
+ trait_item_candidate};
+ candidates.insert (std::move (candidate));
+}
+
+std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
+PathProbeType::union_bounds (
+ const std::vector<std::pair</*const*/ TraitReference *, HIR::ImplBlock *>> a,
+ const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> b)
+ const
+{
+ std::map<DefId, std::pair<const TraitReference *, HIR::ImplBlock *>> mapper;
+ for (auto &ref : a)
+ {
+ mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
+ }
+ for (auto &ref : b)
+ {
+ mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
+ }
+
+ std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_set;
+ for (auto it = mapper.begin (); it != mapper.end (); it++)
+ {
+ union_set.push_back ({it->second.first, it->second.second});
+ }
+ return union_set;
+}
+
+bool
+PathProbeType::is_reciever_generic () const
+{
+ const TyTy::BaseType *root = receiver->get_root ();
+ bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
+ bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
+ return receiver_is_type_param || receiver_is_dyn;
+}
+
+// PathProbImplTrait
+
+PathProbeImplTrait::PathProbeImplTrait (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &query,
+ const TraitReference *trait_reference)
+ : PathProbeType (receiver, query, UNKNOWN_DEFID),
+ trait_reference (trait_reference)
+{}
+
+std::set<PathProbeCandidate>
+PathProbeImplTrait::Probe (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &segment_name,
+ const TraitReference *trait_reference)
+{
+ PathProbeImplTrait probe (receiver, segment_name, trait_reference);
+ // iterate all impls for this trait and receiver
+ // then search for possible candidates using base class behaviours
+ probe.process_trait_impl_items_for_candidates ();
+ return probe.candidates;
+}
+
+void
+PathProbeImplTrait::process_trait_impl_items_for_candidates ()
+{
+ mappings->iterate_impl_items (
+ [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
+ // just need to check if this is an impl block for this trait the next
+ // function checks the receiver
+ if (!impl->has_trait_ref ())
+ return true;
+
+ TraitReference *resolved
+ = TraitResolver::Lookup (*(impl->get_trait_ref ().get ()));
+ if (!trait_reference->is_equal (*resolved))
+ return true;
+
+ process_impl_item_candidate (id, item, impl);
+ return true;
+ });
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index 6d6bcf8..dd511ac 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -73,89 +73,37 @@ struct PathProbeCandidate
ImplItemCandidate impl;
TraitItemCandidate trait;
- Candidate (EnumItemCandidate enum_field) : enum_field (enum_field) {}
- Candidate (ImplItemCandidate impl) : impl (impl) {}
- Candidate (TraitItemCandidate trait) : trait (trait) {}
+ Candidate (EnumItemCandidate enum_field);
+ Candidate (ImplItemCandidate impl);
+ Candidate (TraitItemCandidate trait);
} item;
PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
- EnumItemCandidate enum_field)
- : type (type), ty (ty), locus (locus), item (enum_field)
- {}
+ EnumItemCandidate enum_field);
PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
- ImplItemCandidate impl)
- : type (type), ty (ty), locus (locus), item (impl)
- {}
+ ImplItemCandidate impl);
PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
- TraitItemCandidate trait)
- : type (type), ty (ty), locus (locus), item (trait)
- {}
+ TraitItemCandidate trait);
- std::string as_string () const
- {
- return "PathProbe candidate TODO - as_string";
- }
+ std::string as_string () const;
- bool is_enum_candidate () const { return type == ENUM_VARIANT; }
+ bool is_enum_candidate () const;
- bool is_impl_candidate () const
- {
- return type == IMPL_CONST || type == IMPL_TYPE_ALIAS || type == IMPL_FUNC;
- }
+ bool is_impl_candidate () const;
- bool is_trait_candidate () const
- {
- return type == TRAIT_ITEM_CONST || type == TRAIT_TYPE_ALIAS
- || type == TRAIT_FUNC;
- }
+ bool is_trait_candidate () const;
- bool is_full_trait_item_candidate () const
- {
- return is_trait_candidate () && item.trait.impl == nullptr;
- }
+ bool is_full_trait_item_candidate () const;
- static PathProbeCandidate get_error ()
- {
- return PathProbeCandidate (ERROR, nullptr, Location (),
- ImplItemCandidate{nullptr, nullptr});
- }
+ static PathProbeCandidate get_error ();
- bool is_error () const { return type == ERROR; }
+ bool is_error () const;
- DefId get_defid () const
- {
- switch (type)
- {
- case ENUM_VARIANT:
- return item.enum_field.variant->get_defid ();
- break;
-
- case IMPL_CONST:
- case IMPL_TYPE_ALIAS:
- case IMPL_FUNC:
- return item.impl.impl_item->get_impl_mappings ().get_defid ();
- break;
-
- case TRAIT_ITEM_CONST:
- case TRAIT_TYPE_ALIAS:
- case TRAIT_FUNC:
- return item.trait.item_ref->get_mappings ().get_defid ();
- break;
-
- case ERROR:
- default:
- return UNKNOWN_DEFID;
- }
-
- return UNKNOWN_DEFID;
- }
+ DefId get_defid () const;
- bool operator< (const PathProbeCandidate &c) const
- {
- return get_defid () < c.get_defid ();
- }
+ bool operator< (const PathProbeCandidate &c) const;
};
class PathProbeType : public TypeCheckBase, public HIR::HIRImplVisitor
@@ -165,144 +113,16 @@ public:
Probe (const TyTy::BaseType *receiver,
const HIR::PathIdentSegment &segment_name, bool probe_impls,
bool probe_bounds, bool ignore_mandatory_trait_items,
- DefId specific_trait_id = UNKNOWN_DEFID)
- {
- PathProbeType probe (receiver, segment_name, specific_trait_id);
- if (probe_impls)
- {
- if (receiver->get_kind () == TyTy::TypeKind::ADT)
- {
- const TyTy::ADTType *adt
- = static_cast<const TyTy::ADTType *> (receiver);
- if (adt->is_enum ())
- probe.process_enum_item_for_candiates (adt);
- }
-
- probe.process_impl_items_for_candidates ();
- }
-
- if (!probe_bounds)
- return probe.candidates;
-
- if (!probe.is_reciever_generic ())
- {
- std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> probed_bounds
- = TypeBoundsProbe::Probe (receiver);
- for (auto &candidate : probed_bounds)
- {
- const TraitReference *trait_ref = candidate.first;
- if (specific_trait_id != UNKNOWN_DEFID)
- {
- if (trait_ref->get_mappings ().get_defid ()
- != specific_trait_id)
- continue;
- }
-
- HIR::ImplBlock *impl = candidate.second;
- probe.process_associated_trait_for_candidates (
- trait_ref, impl, ignore_mandatory_trait_items);
- }
- }
-
- for (const TyTy::TypeBoundPredicate &predicate :
- receiver->get_specified_bounds ())
- {
- const TraitReference *trait_ref = predicate.get ();
- if (specific_trait_id != UNKNOWN_DEFID)
- {
- if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
- continue;
- }
-
- probe.process_predicate_for_candidates (predicate,
- ignore_mandatory_trait_items);
- }
-
- return probe.candidates;
- }
-
- void visit (HIR::TypeAlias &alias) override
- {
- Identifier name = alias.get_new_type_name ();
- if (search.as_string ().compare (name) == 0)
- {
- HirId tyid = alias.get_mappings ().get_hirid ();
- TyTy::BaseType *ty = nullptr;
- bool ok = query_type (tyid, &ty);
- rust_assert (ok);
-
- PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias,
- current_impl};
- PathProbeCandidate candidate{
- PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, ty,
- alias.get_locus (), impl_item_candidate};
- candidates.insert (std::move (candidate));
- }
- }
-
- void visit (HIR::ConstantItem &constant) override
- {
- Identifier name = constant.get_identifier ();
- if (search.as_string ().compare (name) == 0)
- {
- HirId tyid = constant.get_mappings ().get_hirid ();
- TyTy::BaseType *ty = nullptr;
- bool ok = query_type (tyid, &ty);
- rust_assert (ok);
-
- PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant,
- current_impl};
- PathProbeCandidate candidate{
- PathProbeCandidate::CandidateType::IMPL_CONST, ty,
- constant.get_locus (), impl_item_candidate};
- candidates.insert (std::move (candidate));
- }
- }
+ DefId specific_trait_id = UNKNOWN_DEFID);
- void visit (HIR::Function &function) override
- {
- Identifier name = function.get_function_name ();
- if (search.as_string ().compare (name) == 0)
- {
- HirId tyid = function.get_mappings ().get_hirid ();
- TyTy::BaseType *ty = nullptr;
- bool ok = query_type (tyid, &ty);
- rust_assert (ok);
-
- PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function,
- current_impl};
- PathProbeCandidate candidate{
- PathProbeCandidate::CandidateType::IMPL_FUNC, ty,
- function.get_locus (), impl_item_candidate};
- candidates.insert (std::move (candidate));
- }
- }
+ void visit (HIR::TypeAlias &alias) override;
+ void visit (HIR::ConstantItem &constant) override;
+ void visit (HIR::Function &function) override;
protected:
- void process_enum_item_for_candiates (const TyTy::ADTType *adt)
- {
- if (specific_trait_id != UNKNOWN_DEFID)
- return;
-
- TyTy::VariantDef *v;
- if (!adt->lookup_variant (search.as_string (), &v))
- return;
-
- PathProbeCandidate::EnumItemCandidate enum_item_candidate{adt, v};
- PathProbeCandidate candidate{
- PathProbeCandidate::CandidateType::ENUM_VARIANT, receiver->clone (),
- mappings->lookup_location (adt->get_ty_ref ()), enum_item_candidate};
- candidates.insert (std::move (candidate));
- }
+ void process_enum_item_for_candiates (const TyTy::ADTType *adt);
- void process_impl_items_for_candidates ()
- {
- mappings->iterate_impl_items ([&] (HirId id, HIR::ImplItem *item,
- HIR::ImplBlock *impl) mutable -> bool {
- process_impl_item_candidate (id, item, impl);
- return true;
- });
- }
+ void process_impl_items_for_candidates ();
void process_impl_item_candidate (HirId id, HIR::ImplItem *item,
HIR::ImplBlock *impl);
@@ -310,155 +130,24 @@ protected:
void
process_associated_trait_for_candidates (const TraitReference *trait_ref,
HIR::ImplBlock *impl,
- bool ignore_mandatory_trait_items)
- {
- const TraitItemReference *trait_item_ref = nullptr;
- if (!trait_ref->lookup_trait_item (search.as_string (), &trait_item_ref))
- return;
-
- bool trait_item_needs_implementation = !trait_item_ref->is_optional ();
- if (ignore_mandatory_trait_items && trait_item_needs_implementation)
- return;
-
- PathProbeCandidate::CandidateType candidate_type;
- switch (trait_item_ref->get_trait_item_type ())
- {
- case TraitItemReference::TraitItemType::FN:
- candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
- break;
- case TraitItemReference::TraitItemType::CONST:
- candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
- break;
- case TraitItemReference::TraitItemType::TYPE:
- candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
- break;
-
- case TraitItemReference::TraitItemType::ERROR:
- default:
- gcc_unreachable ();
- break;
- }
-
- TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ();
-
- // we can substitute the Self with the receiver here
- if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF)
- {
- TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty);
- TyTy::SubstitutionParamMapping *param = nullptr;
- for (auto &param_mapping : fn->get_substs ())
- {
- const HIR::TypeParam &type_param
- = param_mapping.get_generic_param ();
- if (type_param.get_type_representation ().compare ("Self") == 0)
- {
- param = &param_mapping;
- break;
- }
- }
- rust_assert (param != nullptr);
-
- std::vector<TyTy::SubstitutionArg> mappings;
- mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ()));
-
- Location locus; // FIXME
- TyTy::SubstitutionArgumentMappings args (std::move (mappings), locus);
- trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args);
- }
-
- PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
- trait_item_ref,
- impl};
-
- PathProbeCandidate candidate{candidate_type, trait_item_tyty,
- trait_item_ref->get_locus (),
- trait_item_candidate};
- candidates.insert (std::move (candidate));
- }
+ bool ignore_mandatory_trait_items);
void
process_predicate_for_candidates (const TyTy::TypeBoundPredicate &predicate,
- bool ignore_mandatory_trait_items)
- {
- const TraitReference *trait_ref = predicate.get ();
-
- TyTy::TypeBoundPredicateItem item
- = predicate.lookup_associated_item (search.as_string ());
- if (item.is_error ())
- return;
-
- if (ignore_mandatory_trait_items && item.needs_implementation ())
- return;
-
- const TraitItemReference *trait_item_ref = item.get_raw_item ();
- PathProbeCandidate::CandidateType candidate_type;
- switch (trait_item_ref->get_trait_item_type ())
- {
- case TraitItemReference::TraitItemType::FN:
- candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
- break;
- case TraitItemReference::TraitItemType::CONST:
- candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
- break;
- case TraitItemReference::TraitItemType::TYPE:
- candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
- break;
-
- case TraitItemReference::TraitItemType::ERROR:
- default:
- gcc_unreachable ();
- break;
- }
-
- TyTy::BaseType *trait_item_tyty = item.get_tyty_for_receiver (receiver);
- PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
- trait_item_ref,
- nullptr};
- PathProbeCandidate candidate{candidate_type, trait_item_tyty,
- trait_item_ref->get_locus (),
- trait_item_candidate};
- candidates.insert (std::move (candidate));
- }
+ bool ignore_mandatory_trait_items);
protected:
PathProbeType (const TyTy::BaseType *receiver,
- const HIR::PathIdentSegment &query, DefId specific_trait_id)
- : TypeCheckBase (), receiver (receiver), search (query),
- current_impl (nullptr), specific_trait_id (specific_trait_id)
- {}
+ const HIR::PathIdentSegment &query, DefId specific_trait_id);
std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
union_bounds (
const std::vector<std::pair</*const*/ TraitReference *, HIR::ImplBlock *>>
a,
const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> b)
- const
- {
- std::map<DefId, std::pair<const TraitReference *, HIR::ImplBlock *>> mapper;
- for (auto &ref : a)
- {
- mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
- }
- for (auto &ref : b)
- {
- mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
- }
-
- std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_set;
- for (auto it = mapper.begin (); it != mapper.end (); it++)
- {
- union_set.push_back ({it->second.first, it->second.second});
- }
- return union_set;
- }
+ const;
- bool is_reciever_generic () const
- {
- const TyTy::BaseType *root = receiver->get_root ();
- bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM;
- bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
- return receiver_is_type_param || receiver_is_dyn;
- }
+ bool is_reciever_generic () const;
const TyTy::BaseType *receiver;
const HIR::PathIdentSegment &search;
@@ -488,24 +177,14 @@ public:
static std::set<PathProbeCandidate>
Probe (const TyTy::BaseType *receiver,
const HIR::PathIdentSegment &segment_name,
- const TraitReference *trait_reference)
- {
- PathProbeImplTrait probe (receiver, segment_name, trait_reference);
- // iterate all impls for this trait and receiver
- // then search for possible candidates using base class behaviours
- probe.process_trait_impl_items_for_candidates ();
- return probe.candidates;
- }
+ const TraitReference *trait_reference);
private:
- void process_trait_impl_items_for_candidates ();
-
PathProbeImplTrait (const TyTy::BaseType *receiver,
const HIR::PathIdentSegment &query,
- const TraitReference *trait_reference)
- : PathProbeType (receiver, query, UNKNOWN_DEFID),
- trait_reference (trait_reference)
- {}
+ const TraitReference *trait_reference);
+
+ void process_trait_impl_items_for_candidates ();
const TraitReference *trait_reference;
};
diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h
deleted file mode 100644
index 0df3526..0000000
--- a/gcc/rust/typecheck/rust-hir-trait-ref.h
+++ /dev/null
@@ -1,515 +0,0 @@
-// Copyright (C) 2021-2023 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_HIR_TRAIT_REF_H
-#define RUST_HIR_TRAIT_REF_H
-
-#include "rust-hir-full.h"
-#include "rust-tyty-visitor.h"
-#include "rust-hir-type-check-util.h"
-
-namespace Rust {
-namespace Resolver {
-
-// Data Objects for the associated trait items in a structure we can work with
-// https://doc.rust-lang.org/edition-guide/rust-2018/trait-system/associated-constants.html
-class TypeCheckContext;
-class TraitItemReference
-{
-public:
- enum TraitItemType
- {
- FN,
- CONST,
- TYPE,
- ERROR
- };
-
- TraitItemReference (std::string identifier, bool optional, TraitItemType type,
- HIR::TraitItem *hir_trait_item, TyTy::BaseType *self,
- std::vector<TyTy::SubstitutionParamMapping> substitutions,
- Location locus);
-
- TraitItemReference (TraitItemReference const &other);
-
- TraitItemReference &operator= (TraitItemReference const &other);
-
- static TraitItemReference error ()
- {
- return TraitItemReference ("", false, ERROR, nullptr, nullptr, {},
- Location ());
- }
-
- static TraitItemReference &error_node ()
- {
- static TraitItemReference error = TraitItemReference::error ();
- return error;
- }
-
- bool is_error () const { return type == ERROR; }
-
- std::string as_string () const
- {
- return "(" + trait_item_type_as_string (type) + " " + identifier + " "
- + ")";
- }
-
- static std::string trait_item_type_as_string (TraitItemType ty)
- {
- switch (ty)
- {
- case FN:
- return "FN";
- case CONST:
- return "CONST";
- case TYPE:
- return "TYPE";
- case ERROR:
- return "ERROR";
- }
- return "ERROR";
- }
-
- bool is_optional () const { return optional_flag; }
-
- std::string get_identifier () const { return identifier; }
-
- TraitItemType get_trait_item_type () const { return type; }
-
- HIR::TraitItem *get_hir_trait_item () const { return hir_trait_item; }
-
- Location get_locus () const { return locus; }
-
- const Analysis::NodeMapping get_mappings () const
- {
- return hir_trait_item->get_mappings ();
- }
-
- TyTy::BaseType *get_tyty () const
- {
- rust_assert (hir_trait_item != nullptr);
-
- switch (type)
- {
- case CONST:
- return get_type_from_constant (
- static_cast</*const*/ HIR::TraitItemConst &> (*hir_trait_item));
- break;
-
- case TYPE:
- return get_type_from_typealias (
- static_cast</*const*/ HIR::TraitItemType &> (*hir_trait_item));
-
- case FN:
- return get_type_from_fn (
- static_cast</*const*/ HIR::TraitItemFunc &> (*hir_trait_item));
- break;
-
- default:
- return get_error ();
- }
-
- gcc_unreachable ();
- return get_error ();
- }
-
- Analysis::NodeMapping get_parent_trait_mappings () const;
-
- // this is called when the trait is completed resolution and gives the items a
- // chance to run their specific type resolution passes. If we call their
- // resolution on construction it can lead to a case where the trait being
- // resolved recursively trying to resolve the trait itself infinitely since
- // the trait will not be stored in its own map yet
- void on_resolved ();
-
- void associated_type_set (TyTy::BaseType *ty) const;
-
- void associated_type_reset () const;
-
- bool is_object_safe () const;
-
-private:
- TyTy::ErrorType *get_error () const
- {
- return new TyTy::ErrorType (get_mappings ().get_hirid ());
- }
-
- TyTy::BaseType *get_type_from_typealias (/*const*/
- HIR::TraitItemType &type) const;
-
- TyTy::BaseType *
- get_type_from_constant (/*const*/ HIR::TraitItemConst &constant) const;
-
- TyTy::BaseType *get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const;
-
- bool is_item_resolved () const;
- void resolve_item (HIR::TraitItemType &type);
- void resolve_item (HIR::TraitItemConst &constant);
- void resolve_item (HIR::TraitItemFunc &func);
-
- std::string identifier;
- bool optional_flag;
- TraitItemType type;
- HIR::TraitItem *hir_trait_item;
- std::vector<TyTy::SubstitutionParamMapping> inherited_substitutions;
- Location locus;
-
- TyTy::BaseType
- *self; // this is the implict Self TypeParam required for methods
- Resolver::TypeCheckContext *context;
-};
-
-// this wraps up the HIR::Trait so we can do analysis on it
-
-class TraitReference
-{
-public:
- TraitReference (const HIR::Trait *hir_trait_ref,
- std::vector<TraitItemReference> item_refs,
- std::vector<const TraitReference *> super_traits,
- std::vector<TyTy::SubstitutionParamMapping> substs)
- : hir_trait_ref (hir_trait_ref), item_refs (item_refs),
- super_traits (super_traits)
- {
- trait_substs.clear ();
- trait_substs.reserve (substs.size ());
- for (const auto &p : substs)
- trait_substs.push_back (p.clone ());
- }
-
- TraitReference (TraitReference const &other)
- : hir_trait_ref (other.hir_trait_ref), item_refs (other.item_refs),
- super_traits (other.super_traits)
- {
- trait_substs.clear ();
- trait_substs.reserve (other.trait_substs.size ());
- for (const auto &p : other.trait_substs)
- trait_substs.push_back (p.clone ());
- }
-
- TraitReference &operator= (TraitReference const &other)
- {
- hir_trait_ref = other.hir_trait_ref;
- item_refs = other.item_refs;
- super_traits = other.super_traits;
-
- trait_substs.clear ();
- trait_substs.reserve (other.trait_substs.size ());
- for (const auto &p : other.trait_substs)
- trait_substs.push_back (p.clone ());
-
- return *this;
- }
-
- TraitReference (TraitReference &&other) = default;
- TraitReference &operator= (TraitReference &&other) = default;
-
- static TraitReference error ()
- {
- return TraitReference (nullptr, {}, {}, {});
- }
-
- bool is_error () const { return hir_trait_ref == nullptr; }
-
- static TraitReference &error_node ()
- {
- static TraitReference trait_error_node = TraitReference::error ();
- return trait_error_node;
- }
-
- Location get_locus () const { return hir_trait_ref->get_locus (); }
-
- std::string get_name () const
- {
- rust_assert (!is_error ());
- return hir_trait_ref->get_name ();
- }
-
- std::string as_string () const
- {
- if (is_error ())
- return "<trait-ref-error-node>";
-
- std::string item_buf;
- for (auto &item : item_refs)
- {
- item_buf += item.as_string () + ", ";
- }
- return "HIR Trait: " + get_name () + "->"
- + hir_trait_ref->get_mappings ().as_string () + " [" + item_buf
- + "]";
- }
-
- const HIR::Trait *get_hir_trait_ref () const { return hir_trait_ref; }
-
- const Analysis::NodeMapping &get_mappings () const
- {
- return hir_trait_ref->get_mappings ();
- }
-
- DefId get_defid () const { return get_mappings ().get_defid (); }
-
- bool lookup_hir_trait_item (const HIR::TraitItem &item,
- TraitItemReference **ref)
- {
- return lookup_trait_item (item.trait_identifier (), ref);
- }
-
- bool lookup_trait_item (const std::string &ident, TraitItemReference **ref)
- {
- for (auto &item : item_refs)
- {
- if (ident.compare (item.get_identifier ()) == 0)
- {
- *ref = &item;
- return true;
- }
- }
- return false;
- }
-
- bool lookup_trait_item_by_type (const std::string &ident,
- TraitItemReference::TraitItemType type,
- TraitItemReference **ref)
- {
- for (auto &item : item_refs)
- {
- if (item.get_trait_item_type () != type)
- continue;
-
- if (ident.compare (item.get_identifier ()) == 0)
- {
- *ref = &item;
- return true;
- }
- }
- return false;
- }
-
- bool lookup_trait_item_by_type (const std::string &ident,
- TraitItemReference::TraitItemType type,
- const TraitItemReference **ref) const
- {
- for (auto &item : item_refs)
- {
- if (item.get_trait_item_type () != type)
- continue;
-
- if (ident.compare (item.get_identifier ()) == 0)
- {
- *ref = &item;
- return true;
- }
- }
- return false;
- }
-
- bool lookup_hir_trait_item (const HIR::TraitItem &item,
- const TraitItemReference **ref) const
- {
- return lookup_trait_item (item.trait_identifier (), ref);
- }
-
- bool lookup_trait_item (const std::string &ident,
- const TraitItemReference **ref) const
- {
- for (auto &item : item_refs)
- {
- if (ident.compare (item.get_identifier ()) == 0)
- {
- *ref = &item;
- return true;
- }
- }
-
- // lookup super traits
- for (const auto &super_trait : super_traits)
- {
- bool found = super_trait->lookup_trait_item (ident, ref);
- if (found)
- return true;
- }
-
- return false;
- }
-
- const TraitItemReference *
- lookup_trait_item (const std::string &ident,
- TraitItemReference::TraitItemType type) const
- {
- for (auto &item : item_refs)
- {
- if (item.get_trait_item_type () != type)
- continue;
-
- if (ident.compare (item.get_identifier ()) == 0)
- return &item;
- }
-
- // lookup super traits
- for (const auto &super_trait : super_traits)
- {
- const TraitItemReference *res
- = super_trait->lookup_trait_item (ident, type);
- if (!res->is_error ())
- return res;
- }
-
- return &TraitItemReference::error_node ();
- }
-
- size_t size () const { return item_refs.size (); }
-
- const std::vector<TraitItemReference> &get_trait_items () const
- {
- return item_refs;
- }
-
- void get_trait_items_and_supers (
- std::vector<const TraitItemReference *> &result) const
- {
- for (const auto &item : item_refs)
- result.push_back (&item);
-
- for (const auto &super_trait : super_traits)
- super_trait->get_trait_items_and_supers (result);
- }
-
- void on_resolved ()
- {
- for (auto &item : item_refs)
- {
- item.on_resolved ();
- }
- }
-
- void clear_associated_types ()
- {
- for (auto &item : item_refs)
- {
- bool is_assoc_type = item.get_trait_item_type ()
- == TraitItemReference::TraitItemType::TYPE;
- if (is_assoc_type)
- item.associated_type_reset ();
- }
- }
-
- bool is_equal (const TraitReference &other) const
- {
- DefId this_id = get_mappings ().get_defid ();
- DefId other_id = other.get_mappings ().get_defid ();
- return this_id == other_id;
- }
-
- const std::vector<const TraitReference *> get_super_traits () const
- {
- return super_traits;
- }
-
- bool is_object_safe (bool emit_error, Location locus) const
- {
- // https: // doc.rust-lang.org/reference/items/traits.html#object-safety
- std::vector<const TraitReference *> non_object_super_traits;
- for (auto &item : super_traits)
- {
- if (!item->is_object_safe (false, Location ()))
- non_object_super_traits.push_back (item);
- }
-
- std::vector<const Resolver::TraitItemReference *> non_object_safe_items;
- for (auto &item : get_trait_items ())
- {
- if (!item.is_object_safe ())
- non_object_safe_items.push_back (&item);
- }
-
- bool is_safe
- = non_object_super_traits.empty () && non_object_safe_items.empty ();
- if (emit_error && !is_safe)
- {
- RichLocation r (locus);
- for (auto &item : non_object_super_traits)
- r.add_range (item->get_locus ());
- for (auto &item : non_object_safe_items)
- r.add_range (item->get_locus ());
-
- rust_error_at (r, "trait bound is not object safe");
- }
-
- return is_safe;
- }
-
- bool trait_has_generics () const { return !trait_substs.empty (); }
-
- std::vector<TyTy::SubstitutionParamMapping> get_trait_substs () const
- {
- return trait_substs;
- }
-
- bool satisfies_bound (const TraitReference &reference) const
- {
- if (is_equal (reference))
- return true;
-
- for (const auto &super_trait : super_traits)
- {
- if (super_trait->satisfies_bound (reference))
- return true;
- }
-
- return false;
- }
-
-private:
- const HIR::Trait *hir_trait_ref;
- std::vector<TraitItemReference> item_refs;
- std::vector<const TraitReference *> super_traits;
- std::vector<TyTy::SubstitutionParamMapping> trait_substs;
-};
-
-class AssociatedImplTrait
-{
-public:
- AssociatedImplTrait (TraitReference *trait, HIR::ImplBlock *impl,
- TyTy::BaseType *self,
- Resolver::TypeCheckContext *context)
- : trait (trait), impl (impl), self (self), context (context)
- {}
-
- TraitReference *get_trait () { return trait; }
-
- HIR::ImplBlock *get_impl_block () { return impl; }
-
- TyTy::BaseType *get_self () { return self; }
-
- void setup_associated_types (const TyTy::BaseType *self,
- const TyTy::TypeBoundPredicate &bound);
-
- void reset_associated_types ();
-
-private:
- TraitReference *trait;
- HIR::ImplBlock *impl;
- TyTy::BaseType *self;
- Resolver::TypeCheckContext *context;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_HIR_TRAIT_REF_H
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.cc b/gcc/rust/typecheck/rust-hir-trait-reference.cc
new file mode 100644
index 0000000..a1229ad
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.cc
@@ -0,0 +1,475 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-trait-reference.h"
+
+namespace Rust {
+namespace Resolver {
+
+std::string
+TraitItemReference::as_string () const
+{
+ return "(" + trait_item_type_as_string (type) + " " + identifier + " " + ")";
+}
+
+bool
+TraitItemReference::is_error () const
+{
+ return type == ERROR;
+}
+
+bool
+TraitItemReference::is_optional () const
+{
+ return optional_flag;
+};
+
+std::string
+TraitItemReference::get_identifier () const
+{
+ return identifier;
+}
+
+TraitItemReference::TraitItemType
+TraitItemReference::get_trait_item_type () const
+{
+ return type;
+}
+
+HIR::TraitItem *
+TraitItemReference::get_hir_trait_item () const
+{
+ return hir_trait_item;
+}
+
+Location
+TraitItemReference::get_locus () const
+{
+ return locus;
+}
+
+const Analysis::NodeMapping
+TraitItemReference::get_mappings () const
+{
+ return hir_trait_item->get_mappings ();
+}
+
+TyTy::BaseType *
+TraitItemReference::get_tyty () const
+{
+ rust_assert (hir_trait_item != nullptr);
+
+ switch (type)
+ {
+ case CONST:
+ return get_type_from_constant (
+ static_cast</*const*/ HIR::TraitItemConst &> (*hir_trait_item));
+ break;
+
+ case TYPE:
+ return get_type_from_typealias (
+ static_cast</*const*/ HIR::TraitItemType &> (*hir_trait_item));
+
+ case FN:
+ return get_type_from_fn (
+ static_cast</*const*/ HIR::TraitItemFunc &> (*hir_trait_item));
+ break;
+
+ default:
+ return get_error ();
+ }
+
+ gcc_unreachable ();
+ return get_error ();
+}
+
+TyTy::ErrorType *
+TraitItemReference::get_error () const
+{
+ return new TyTy::ErrorType (get_mappings ().get_hirid ());
+}
+
+TraitReference::TraitReference (
+ const HIR::Trait *hir_trait_ref, std::vector<TraitItemReference> item_refs,
+ std::vector<const TraitReference *> super_traits,
+ std::vector<TyTy::SubstitutionParamMapping> substs)
+ : hir_trait_ref (hir_trait_ref), item_refs (item_refs),
+ super_traits (super_traits)
+{
+ trait_substs.clear ();
+ trait_substs.reserve (substs.size ());
+ for (const auto &p : substs)
+ trait_substs.push_back (p.clone ());
+}
+
+TraitReference::TraitReference (TraitReference const &other)
+ : hir_trait_ref (other.hir_trait_ref), item_refs (other.item_refs),
+ super_traits (other.super_traits)
+{
+ trait_substs.clear ();
+ trait_substs.reserve (other.trait_substs.size ());
+ for (const auto &p : other.trait_substs)
+ trait_substs.push_back (p.clone ());
+}
+
+TraitReference &
+TraitReference::operator= (TraitReference const &other)
+{
+ hir_trait_ref = other.hir_trait_ref;
+ item_refs = other.item_refs;
+ super_traits = other.super_traits;
+
+ trait_substs.clear ();
+ trait_substs.reserve (other.trait_substs.size ());
+ for (const auto &p : other.trait_substs)
+ trait_substs.push_back (p.clone ());
+
+ return *this;
+}
+
+bool
+TraitReference::is_error () const
+{
+ return hir_trait_ref == nullptr;
+}
+
+Location
+TraitReference::get_locus () const
+{
+ return hir_trait_ref->get_locus ();
+}
+
+std::string
+TraitReference::get_name () const
+{
+ rust_assert (!is_error ());
+ return hir_trait_ref->get_name ();
+}
+
+std::string
+TraitReference::as_string () const
+{
+ if (is_error ())
+ return "<trait-ref-error-node>";
+
+ std::string item_buf;
+ for (auto &item : item_refs)
+ {
+ item_buf += item.as_string () + ", ";
+ }
+ return "HIR Trait: " + get_name () + "->"
+ + hir_trait_ref->get_mappings ().as_string () + " [" + item_buf + "]";
+}
+
+const HIR::Trait *
+TraitReference::get_hir_trait_ref () const
+{
+ return hir_trait_ref;
+}
+
+const Analysis::NodeMapping &
+TraitReference::get_mappings () const
+{
+ return hir_trait_ref->get_mappings ();
+}
+
+DefId
+TraitReference::get_defid () const
+{
+ return get_mappings ().get_defid ();
+}
+
+bool
+TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item,
+ TraitItemReference **ref)
+{
+ return lookup_trait_item (item.trait_identifier (), ref);
+}
+
+bool
+TraitReference::lookup_trait_item (const std::string &ident,
+ TraitItemReference **ref)
+{
+ for (auto &item : item_refs)
+ {
+ if (ident.compare (item.get_identifier ()) == 0)
+ {
+ *ref = &item;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+TraitReference::lookup_trait_item_by_type (
+ const std::string &ident, TraitItemReference::TraitItemType type,
+ TraitItemReference **ref)
+{
+ for (auto &item : item_refs)
+ {
+ if (item.get_trait_item_type () != type)
+ continue;
+
+ if (ident.compare (item.get_identifier ()) == 0)
+ {
+ *ref = &item;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+TraitReference::lookup_trait_item_by_type (
+ const std::string &ident, TraitItemReference::TraitItemType type,
+ const TraitItemReference **ref) const
+{
+ for (auto &item : item_refs)
+ {
+ if (item.get_trait_item_type () != type)
+ continue;
+
+ if (ident.compare (item.get_identifier ()) == 0)
+ {
+ *ref = &item;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item,
+ const TraitItemReference **ref) const
+{
+ return lookup_trait_item (item.trait_identifier (), ref);
+}
+
+bool
+TraitReference::lookup_trait_item (const std::string &ident,
+ const TraitItemReference **ref) const
+{
+ for (auto &item : item_refs)
+ {
+ if (ident.compare (item.get_identifier ()) == 0)
+ {
+ *ref = &item;
+ return true;
+ }
+ }
+
+ // lookup super traits
+ for (const auto &super_trait : super_traits)
+ {
+ bool found = super_trait->lookup_trait_item (ident, ref);
+ if (found)
+ return true;
+ }
+
+ return false;
+}
+
+const TraitItemReference *
+TraitReference::lookup_trait_item (const std::string &ident,
+ TraitItemReference::TraitItemType type) const
+{
+ for (auto &item : item_refs)
+ {
+ if (item.get_trait_item_type () != type)
+ continue;
+
+ if (ident.compare (item.get_identifier ()) == 0)
+ return &item;
+ }
+
+ // lookup super traits
+ for (const auto &super_trait : super_traits)
+ {
+ const TraitItemReference *res
+ = super_trait->lookup_trait_item (ident, type);
+ if (!res->is_error ())
+ return res;
+ }
+
+ return &TraitItemReference::error_node ();
+}
+
+size_t
+TraitReference::size () const
+{
+ return item_refs.size ();
+}
+
+const std::vector<TraitItemReference> &
+TraitReference::get_trait_items () const
+{
+ return item_refs;
+}
+
+void
+TraitReference::get_trait_items_and_supers (
+ std::vector<const TraitItemReference *> &result) const
+{
+ for (const auto &item : item_refs)
+ result.push_back (&item);
+
+ for (const auto &super_trait : super_traits)
+ super_trait->get_trait_items_and_supers (result);
+}
+
+void
+TraitReference::on_resolved ()
+{
+ for (auto &item : item_refs)
+ {
+ item.on_resolved ();
+ }
+}
+
+void
+TraitReference::clear_associated_types () const
+{
+ for (const auto &item : item_refs)
+ {
+ bool is_assoc_type = item.get_trait_item_type ()
+ == TraitItemReference::TraitItemType::TYPE;
+ if (is_assoc_type)
+ item.associated_type_reset (false);
+ }
+}
+
+void
+TraitReference::clear_associated_type_projections () const
+{
+ for (const auto &item : item_refs)
+ {
+ bool is_assoc_type = item.get_trait_item_type ()
+ == TraitItemReference::TraitItemType::TYPE;
+ if (is_assoc_type)
+ item.associated_type_reset (true);
+ }
+}
+
+bool
+TraitReference::is_equal (const TraitReference &other) const
+{
+ DefId this_id = get_mappings ().get_defid ();
+ DefId other_id = other.get_mappings ().get_defid ();
+ return this_id == other_id;
+}
+
+const std::vector<const TraitReference *>
+TraitReference::get_super_traits () const
+{
+ return super_traits;
+}
+
+bool
+TraitReference::is_object_safe (bool emit_error, Location locus) const
+{
+ // https: // doc.rust-lang.org/reference/items/traits.html#object-safety
+ std::vector<const TraitReference *> non_object_super_traits;
+ for (auto &item : super_traits)
+ {
+ if (!item->is_object_safe (false, Location ()))
+ non_object_super_traits.push_back (item);
+ }
+
+ std::vector<const Resolver::TraitItemReference *> non_object_safe_items;
+ for (auto &item : get_trait_items ())
+ {
+ if (!item.is_object_safe ())
+ non_object_safe_items.push_back (&item);
+ }
+
+ bool is_safe
+ = non_object_super_traits.empty () && non_object_safe_items.empty ();
+ if (emit_error && !is_safe)
+ {
+ RichLocation r (locus);
+ for (auto &item : non_object_super_traits)
+ r.add_range (item->get_locus ());
+ for (auto &item : non_object_safe_items)
+ r.add_range (item->get_locus ());
+
+ rust_error_at (r, "trait bound is not object safe");
+ }
+
+ return is_safe;
+}
+
+bool
+TraitReference::trait_has_generics () const
+{
+ return !trait_substs.empty ();
+}
+
+std::vector<TyTy::SubstitutionParamMapping>
+TraitReference::get_trait_substs () const
+{
+ return trait_substs;
+}
+
+bool
+TraitReference::satisfies_bound (const TraitReference &reference) const
+{
+ if (is_equal (reference))
+ return true;
+
+ for (const auto &super_trait : super_traits)
+ {
+ if (super_trait->satisfies_bound (reference))
+ return true;
+ }
+
+ return false;
+}
+
+AssociatedImplTrait::AssociatedImplTrait (TraitReference *trait,
+ HIR::ImplBlock *impl,
+ TyTy::BaseType *self,
+ Resolver::TypeCheckContext *context)
+ : trait (trait), impl (impl), self (self), context (context)
+{}
+
+TraitReference *
+AssociatedImplTrait::get_trait ()
+{
+ return trait;
+}
+
+HIR::ImplBlock *
+AssociatedImplTrait::get_impl_block ()
+{
+ return impl;
+}
+
+TyTy::BaseType *
+AssociatedImplTrait::get_self ()
+{
+ return self;
+}
+const TyTy::BaseType *
+AssociatedImplTrait::get_self () const
+{
+ return self;
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h
new file mode 100644
index 0000000..d20b295
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -0,0 +1,268 @@
+// Copyright (C) 2021-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_TRAIT_REF_H
+#define RUST_HIR_TRAIT_REF_H
+
+#include "rust-hir-full.h"
+#include "rust-hir-type-check-util.h"
+#include "rust-tyty-visitor.h"
+
+namespace Rust {
+namespace Resolver {
+
+// Data Objects for the associated trait items in a structure we can work with
+// https://doc.rust-lang.org/edition-guide/rust-2018/trait-system/associated-constants.html
+class TypeCheckContext;
+class TraitItemReference
+{
+public:
+ enum TraitItemType
+ {
+ FN,
+ CONST,
+ TYPE,
+ ERROR
+ };
+
+ TraitItemReference (std::string identifier, bool optional, TraitItemType type,
+ HIR::TraitItem *hir_trait_item, TyTy::BaseType *self,
+ std::vector<TyTy::SubstitutionParamMapping> substitutions,
+ Location locus);
+
+ TraitItemReference (TraitItemReference const &other);
+
+ TraitItemReference &operator= (TraitItemReference const &other);
+
+ static TraitItemReference error ()
+ {
+ return TraitItemReference ("", false, ERROR, nullptr, nullptr, {},
+ Location ());
+ }
+
+ static TraitItemReference &error_node ()
+ {
+ static TraitItemReference error = TraitItemReference::error ();
+ return error;
+ }
+
+ bool is_error () const;
+
+ std::string as_string () const;
+
+ static std::string trait_item_type_as_string (TraitItemType ty)
+ {
+ switch (ty)
+ {
+ case FN:
+ return "FN";
+ case CONST:
+ return "CONST";
+ case TYPE:
+ return "TYPE";
+ case ERROR:
+ return "ERROR";
+ }
+ return "ERROR";
+ }
+
+ bool is_optional () const;
+
+ std::string get_identifier () const;
+
+ TraitItemType get_trait_item_type () const;
+
+ HIR::TraitItem *get_hir_trait_item () const;
+
+ Location get_locus () const;
+
+ const Analysis::NodeMapping get_mappings () const;
+
+ TyTy::BaseType *get_tyty () const;
+
+ Analysis::NodeMapping get_parent_trait_mappings () const;
+
+ // this is called when the trait is completed resolution and gives the items
+ // a chance to run their specific type resolution passes. If we call their
+ // resolution on construction it can lead to a case where the trait being
+ // resolved recursively trying to resolve the trait itself infinitely since
+ // the trait will not be stored in its own map yet
+ void on_resolved ();
+
+ void associated_type_set (TyTy::BaseType *ty) const;
+
+ void associated_type_reset (bool only_projections) const;
+
+ bool is_object_safe () const;
+
+private:
+ TyTy::ErrorType *get_error () const;
+
+ TyTy::BaseType *get_type_from_typealias (/*const*/
+ HIR::TraitItemType &type) const;
+
+ TyTy::BaseType *
+ get_type_from_constant (/*const*/ HIR::TraitItemConst &constant) const;
+
+ TyTy::BaseType *get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const;
+
+ bool is_item_resolved () const;
+ void resolve_item (HIR::TraitItemType &type);
+ void resolve_item (HIR::TraitItemConst &constant);
+ void resolve_item (HIR::TraitItemFunc &func);
+
+ std::string identifier;
+ bool optional_flag;
+ TraitItemType type;
+ HIR::TraitItem *hir_trait_item;
+ std::vector<TyTy::SubstitutionParamMapping> inherited_substitutions;
+ Location locus;
+
+ TyTy::BaseType
+ *self; // this is the implict Self TypeParam required for methods
+ Resolver::TypeCheckContext *context;
+};
+
+// this wraps up the HIR::Trait so we can do analysis on it
+
+class TraitReference
+{
+public:
+ TraitReference (const HIR::Trait *hir_trait_ref,
+ std::vector<TraitItemReference> item_refs,
+ std::vector<const TraitReference *> super_traits,
+ std::vector<TyTy::SubstitutionParamMapping> substs);
+
+ TraitReference (TraitReference const &other);
+
+ TraitReference &operator= (TraitReference const &other);
+
+ TraitReference (TraitReference &&other) = default;
+ TraitReference &operator= (TraitReference &&other) = default;
+
+ static TraitReference error ()
+ {
+ return TraitReference (nullptr, {}, {}, {});
+ }
+
+ bool is_error () const;
+
+ static TraitReference &error_node ()
+ {
+ static TraitReference trait_error_node = TraitReference::error ();
+ return trait_error_node;
+ }
+
+ Location get_locus () const;
+
+ std::string get_name () const;
+
+ std::string as_string () const;
+
+ const HIR::Trait *get_hir_trait_ref () const;
+
+ const Analysis::NodeMapping &get_mappings () const;
+
+ DefId get_defid () const;
+
+ bool lookup_hir_trait_item (const HIR::TraitItem &item,
+ TraitItemReference **ref);
+
+ bool lookup_trait_item (const std::string &ident, TraitItemReference **ref);
+
+ bool lookup_trait_item_by_type (const std::string &ident,
+ TraitItemReference::TraitItemType type,
+ TraitItemReference **ref);
+
+ bool lookup_trait_item_by_type (const std::string &ident,
+ TraitItemReference::TraitItemType type,
+ const TraitItemReference **ref) const;
+
+ bool lookup_hir_trait_item (const HIR::TraitItem &item,
+ const TraitItemReference **ref) const;
+
+ bool lookup_trait_item (const std::string &ident,
+ const TraitItemReference **ref) const;
+
+ const TraitItemReference *
+ lookup_trait_item (const std::string &ident,
+ TraitItemReference::TraitItemType type) const;
+
+ size_t size () const;
+
+ const std::vector<TraitItemReference> &get_trait_items () const;
+
+ void get_trait_items_and_supers (
+ std::vector<const TraitItemReference *> &result) const;
+
+ void on_resolved ();
+
+ void clear_associated_types () const;
+
+ void clear_associated_type_projections () const;
+
+ bool is_equal (const TraitReference &other) const;
+
+ const std::vector<const TraitReference *> get_super_traits () const;
+
+ bool is_object_safe (bool emit_error, Location locus) const;
+
+ bool trait_has_generics () const;
+
+ std::vector<TyTy::SubstitutionParamMapping> get_trait_substs () const;
+
+ bool satisfies_bound (const TraitReference &reference) const;
+
+private:
+ const HIR::Trait *hir_trait_ref;
+ std::vector<TraitItemReference> item_refs;
+ std::vector<const TraitReference *> super_traits;
+ std::vector<TyTy::SubstitutionParamMapping> trait_substs;
+};
+
+class AssociatedImplTrait
+{
+public:
+ AssociatedImplTrait (TraitReference *trait, HIR::ImplBlock *impl,
+ TyTy::BaseType *self,
+ Resolver::TypeCheckContext *context);
+
+ TraitReference *get_trait ();
+
+ HIR::ImplBlock *get_impl_block ();
+
+ TyTy::BaseType *get_self ();
+ const TyTy::BaseType *get_self () const;
+
+ TyTy::BaseType *
+ setup_associated_types (const TyTy::BaseType *self,
+ const TyTy::TypeBoundPredicate &bound);
+
+ void reset_associated_types ();
+
+private:
+ TraitReference *trait;
+ HIR::ImplBlock *impl;
+ TyTy::BaseType *self;
+ Resolver::TypeCheckContext *context;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_HIR_TRAIT_REF_H
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 2ec9b2e..2d79857 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -22,6 +22,16 @@
namespace Rust {
namespace Resolver {
+TraitItemReference
+ResolveTraitItemToRef::Resolve (
+ HIR::TraitItem &item, TyTy::BaseType *self,
+ std::vector<TyTy::SubstitutionParamMapping> substitutions)
+{
+ ResolveTraitItemToRef resolver (self, std::move (substitutions));
+ item.accept_vis (resolver);
+ return std::move (resolver.resolved);
+}
+
void
ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
{
@@ -151,6 +161,9 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
TraitQueryGuard guard (trait_id);
TyTy::BaseType *self = nullptr;
std::vector<TyTy::SubstitutionParamMapping> substitutions;
+
+ // FIXME
+ // this should use the resolve_generic_params like everywhere else
for (auto &generic_param : trait_reference->get_generic_params ())
{
switch (generic_param.get ()->get_kind ())
@@ -172,7 +185,11 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
if (typaram.get_type_representation ().compare ("Self") == 0)
{
- self = param_type;
+ rust_assert (param_type->get_kind () == TyTy::TypeKind::PARAM);
+ TyTy::ParamType *p
+ = static_cast<TyTy::ParamType *> (param_type);
+ p->set_implicit_self_trait ();
+ self = p;
}
}
break;
@@ -355,7 +372,7 @@ TraitItemReference::associated_type_set (TyTy::BaseType *ty) const
}
void
-TraitItemReference::associated_type_reset () const
+TraitItemReference::associated_type_reset (bool only_projections) const
{
rust_assert (get_trait_item_type () == TraitItemType::TYPE);
@@ -364,16 +381,27 @@ TraitItemReference::associated_type_reset () const
TyTy::PlaceholderType *placeholder
= static_cast<TyTy::PlaceholderType *> (item_ty);
- placeholder->clear_associated_type ();
+ if (!only_projections)
+ {
+ placeholder->clear_associated_type ();
+ }
+ else
+ {
+ if (!placeholder->can_resolve ())
+ return;
+
+ const TyTy::BaseType *r = placeholder->resolve ();
+ if (r->get_kind () == TyTy::TypeKind::PROJECTION)
+ {
+ placeholder->clear_associated_type ();
+ }
+ }
}
-void
+TyTy::BaseType *
AssociatedImplTrait::setup_associated_types (
const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound)
{
- if (!bound.contains_associated_types ())
- return;
-
// compute the constrained impl block generic arguments based on self and the
// higher ranked trait bound
TyTy::BaseType *receiver = self->clone ();
@@ -441,8 +469,8 @@ AssociatedImplTrait::setup_associated_types (
param_mappings[p.get_symbol ()] = a.get_tyty ()->get_ref ();
};
- TyTy::SubstitutionArgumentMappings infer_arguments (std::move (args), locus,
- param_subst_cb);
+ TyTy::SubstitutionArgumentMappings infer_arguments (std::move (args), {},
+ locus, param_subst_cb);
TyTy::BaseType *impl_self_infer
= (associated_self->needs_generic_substitutions ())
? SubstMapperInternal::Resolve (associated_self, infer_arguments)
@@ -476,6 +504,7 @@ AssociatedImplTrait::setup_associated_types (
TyTy::TyWithLocation (receiver), TyTy::TyWithLocation (impl_self_infer),
impl_predicate.get_locus ());
rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
+ TyTy::BaseType *self_result = result;
// unify the bounds arguments
std::vector<TyTy::BaseType *> hrtb_bound_arguments;
@@ -489,8 +518,9 @@ AssociatedImplTrait::setup_associated_types (
hrtb_bound_arguments.push_back (r);
}
- rust_assert (impl_trait_predicate_args.size ()
- == hrtb_bound_arguments.size ());
+ if (impl_trait_predicate_args.size () != hrtb_bound_arguments.size ())
+ return self_result;
+
for (size_t i = 0; i < impl_trait_predicate_args.size (); i++)
{
TyTy::BaseType *a = impl_trait_predicate_args.at (i);
@@ -521,7 +551,7 @@ AssociatedImplTrait::setup_associated_types (
}
TyTy::SubstitutionArgumentMappings associated_type_args (
- std::move (associated_arguments), locus);
+ std::move (associated_arguments), {}, locus);
ImplTypeIterator iter (*impl, [&] (HIR::TypeAlias &type) {
TraitItemReference *resolved_trait_item = nullptr;
@@ -543,6 +573,8 @@ AssociatedImplTrait::setup_associated_types (
resolved_trait_item->associated_type_set (substituted);
});
iter.go ();
+
+ return self_result;
}
void
@@ -593,27 +625,5 @@ TraitItemReference::is_object_safe () const
return false;
}
-// rust-hir-path-probe.h
-
-void
-PathProbeImplTrait::process_trait_impl_items_for_candidates ()
-{
- mappings->iterate_impl_items (
- [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
- // just need to check if this is an impl block for this trait the next
- // function checks the receiver
- if (!impl->has_trait_ref ())
- return true;
-
- TraitReference *resolved
- = TraitResolver::Lookup (*(impl->get_trait_ref ().get ()));
- if (!trait_reference->is_equal (*resolved))
- return true;
-
- process_impl_item_candidate (id, item, impl);
- return true;
- });
-}
-
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h
index ca23d48..da8e2c0 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.h
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h
@@ -19,9 +19,7 @@
#ifndef RUST_HIR_TRAIT_RESOLVE_H
#define RUST_HIR_TRAIT_RESOLVE_H
-#include "rust-hir-type-check-base.h"
#include "rust-hir-type-check-type.h"
-#include "rust-hir-trait-ref.h"
namespace Rust {
namespace Resolver {
@@ -32,12 +30,7 @@ class ResolveTraitItemToRef : public TypeCheckBase,
public:
static TraitItemReference
Resolve (HIR::TraitItem &item, TyTy::BaseType *self,
- std::vector<TyTy::SubstitutionParamMapping> substitutions)
- {
- ResolveTraitItemToRef resolver (self, std::move (substitutions));
- item.accept_vis (resolver);
- return std::move (resolver.resolved);
- }
+ std::vector<TyTy::SubstitutionParamMapping> substitutions);
void visit (HIR::TraitItemType &type) override;
diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h
index 4e8c583..628bba5 100644
--- a/gcc/rust/typecheck/rust-hir-type-bounds.h
+++ b/gcc/rust/typecheck/rust-hir-type-bounds.h
@@ -30,42 +30,18 @@ class TypeBoundsProbe : public TypeCheckBase
{
public:
static std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
- Probe (const TyTy::BaseType *receiver)
- {
- TypeBoundsProbe probe (receiver);
- probe.scan ();
- return probe.trait_references;
- }
+ Probe (const TyTy::BaseType *receiver);
static bool is_bound_satisfied_for_type (TyTy::BaseType *receiver,
- TraitReference *ref)
- {
- for (auto &bound : receiver->get_specified_bounds ())
- {
- const TraitReference *b = bound.get ();
- if (b->is_equal (*ref))
- return true;
- }
-
- std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
- = Probe (receiver);
- for (auto &bound : bounds)
- {
- const TraitReference *b = bound.first;
- if (b->is_equal (*ref))
- return true;
- }
-
- return false;
- }
+ TraitReference *ref);
private:
void scan ();
+ void assemble_sized_builtin ();
+ void assemble_builtin_candidate (Analysis::RustLangItem::ItemType item);
private:
- TypeBoundsProbe (const TyTy::BaseType *receiver)
- : TypeCheckBase (), receiver (receiver)
- {}
+ TypeBoundsProbe (const TyTy::BaseType *receiver);
const TyTy::BaseType *receiver;
std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> trait_references;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 85826ae..e302e27 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -22,6 +22,7 @@
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-implitem.h"
#include "rust-coercion.h"
+#include "rust-unify.h"
#include "rust-casts.h"
namespace Rust {
@@ -359,18 +360,8 @@ TypeCheckBase::unify_site (HirId id, TyTy::TyWithLocation lhs,
rust_debug ("unify_site id={%u} expected={%s} expr={%s}", id,
expected->debug_str ().c_str (), expr->debug_str ().c_str ());
- TyTy::BaseType *unified = expected->unify (expr);
- if (unified->get_kind () == TyTy::TypeKind::ERROR)
- {
- RichLocation r (unify_locus);
- r.add_range (lhs.get_locus ());
- r.add_range (rhs.get_locus ());
- rust_error_at (r, "expected %<%s%> got %<%s%>",
- expected->get_name ().c_str (),
- expr->get_name ().c_str ());
- }
-
- return unified;
+ return UnifyRules::Resolve (lhs, rhs, unify_locus, true /*commit*/,
+ true /*emit_error*/);
}
TyTy::BaseType *
@@ -492,78 +483,5 @@ TypeCheckBase::resolve_generic_params (
}
}
-bool
-TypeCheckBase::query_type (HirId reference, TyTy::BaseType **result)
-{
- if (context->query_in_progress (reference))
- return false;
-
- if (context->lookup_type (reference, result))
- return true;
-
- context->insert_query (reference);
-
- HIR::Item *item = mappings->lookup_hir_item (reference);
- if (item != nullptr)
- {
- rust_debug_loc (item->get_locus (), "resolved item {%u} to", reference);
- *result = TypeCheckItem::Resolve (*item);
- context->query_completed (reference);
- return true;
- }
-
- HirId parent_impl_id = UNKNOWN_HIRID;
- HIR::ImplItem *impl_item
- = mappings->lookup_hir_implitem (reference, &parent_impl_id);
- if (impl_item != nullptr)
- {
- HIR::ImplBlock *impl_block
- = mappings->lookup_hir_impl_block (parent_impl_id);
- rust_assert (impl_block != nullptr);
-
- // found an impl item
- rust_debug_loc (impl_item->get_locus (), "resolved impl-item {%u} to",
- reference);
-
- *result = TypeCheckItem::ResolveImplItem (*impl_block, *impl_item);
- context->query_completed (reference);
- return true;
- }
-
- // is it an impl_type?
- HIR::ImplBlock *impl_block_by_type = nullptr;
- bool found_impl_block_type
- = mappings->lookup_impl_block_type (reference, &impl_block_by_type);
- if (found_impl_block_type)
- {
- *result = TypeCheckItem::ResolveImplBlockSelf (*impl_block_by_type);
- context->query_completed (reference);
- return true;
- }
-
- // is it an extern item?
- HirId parent_extern_block_id = UNKNOWN_HIRID;
- HIR::ExternalItem *extern_item
- = mappings->lookup_hir_extern_item (reference, &parent_extern_block_id);
- if (extern_item != nullptr)
- {
- HIR::ExternBlock *block
- = mappings->lookup_hir_extern_block (parent_extern_block_id);
- rust_assert (block != nullptr);
-
- *result = TypeCheckTopLevelExternItem::Resolve (extern_item, *block);
- context->query_completed (reference);
- return true;
- }
-
- // more?
- Location possible_locus = mappings->lookup_location (reference);
- rust_debug_loc (possible_locus, "query system failed to resolve: [%u]",
- reference);
- context->query_completed (reference);
-
- return false;
-}
-
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index 3350143..b8ff2cf 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -69,8 +69,6 @@ protected:
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions);
- bool query_type (HirId reference, TyTy::BaseType **result);
-
Analysis::Mappings *mappings;
Resolver *resolver;
TypeCheckContext *context;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 5c43cc8..d4eea7a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -618,7 +618,8 @@ TypeCheckExpr::visit (HIR::RangeFromToExpr &expr)
const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified));
- TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ());
+ TyTy::SubstitutionArgumentMappings subst (subst_mappings, {},
+ expr.get_locus ());
infered = SubstMapperInternal::Resolve (adt, subst);
}
@@ -664,7 +665,8 @@ TypeCheckExpr::visit (HIR::RangeFromExpr &expr)
const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty));
- TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ());
+ TyTy::SubstitutionArgumentMappings subst (subst_mappings, {},
+ expr.get_locus ());
infered = SubstMapperInternal::Resolve (adt, subst);
}
@@ -709,7 +711,8 @@ TypeCheckExpr::visit (HIR::RangeToExpr &expr)
const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty));
- TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ());
+ TyTy::SubstitutionArgumentMappings subst (subst_mappings, {},
+ expr.get_locus ());
infered = SubstMapperInternal::Resolve (adt, subst);
}
@@ -792,7 +795,8 @@ TypeCheckExpr::visit (HIR::RangeFromToInclExpr &expr)
const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified));
- TyTy::SubstitutionArgumentMappings subst (subst_mappings, expr.get_locus ());
+ TyTy::SubstitutionArgumentMappings subst (subst_mappings, {},
+ expr.get_locus ());
infered = SubstMapperInternal::Resolve (adt, subst);
}
@@ -1091,6 +1095,7 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
return;
}
+ fn->prepare_higher_ranked_bounds ();
auto root = receiver_tyty->get_root ();
if (root->get_kind () == TyTy::TypeKind::ADT)
{
@@ -1655,6 +1660,11 @@ TypeCheckExpr::resolve_operator_overload (
TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
rust_assert (fn->is_method ());
+ fn->prepare_higher_ranked_bounds ();
+ rust_debug_loc (expr.get_locus (), "resolved operator overload to: {%u} {%s}",
+ candidate.candidate.ty->get_ref (),
+ candidate.candidate.ty->debug_str ().c_str ());
+
auto root = lhs->get_root ();
if (root->get_kind () == TyTy::TypeKind::ADT)
{
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 6f1fd41..9d9b294 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -379,16 +379,36 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
if (associated_impl_block != nullptr)
{
- // get the type of the parent Self
- HirId impl_ty_id
- = associated_impl_block->get_type ()->get_mappings ().get_hirid ();
+ // associated types
+ HirId impl_block_id
+ = associated_impl_block->get_mappings ().get_hirid ();
+
+ AssociatedImplTrait *associated = nullptr;
+ bool found_impl_trait
+ = context->lookup_associated_trait_impl (impl_block_id,
+ &associated);
TyTy::BaseType *impl_block_ty = nullptr;
- bool ok = query_type (impl_ty_id, &impl_block_ty);
- rust_assert (ok);
+ if (found_impl_trait)
+ {
+ TyTy::TypeBoundPredicate predicate (*associated->get_trait (),
+ seg.get_locus ());
+ impl_block_ty
+ = associated->setup_associated_types (prev_segment, predicate);
+ }
+ else
+ {
+ // get the type of the parent Self
+ HirId impl_ty_id = associated_impl_block->get_type ()
+ ->get_mappings ()
+ .get_hirid ();
- if (impl_block_ty->needs_generic_substitutions ())
- impl_block_ty
- = SubstMapper::InferSubst (impl_block_ty, seg.get_locus ());
+ bool ok = query_type (impl_ty_id, &impl_block_ty);
+ rust_assert (ok);
+
+ if (impl_block_ty->needs_generic_substitutions ())
+ impl_block_ty
+ = SubstMapper::InferSubst (impl_block_ty, seg.get_locus ());
+ }
prev_segment = unify_site (seg.get_mappings ().get_hirid (),
TyTy::TyWithLocation (prev_segment),
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index b017a85..fd4814c 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -387,13 +387,6 @@ TypeCheckPattern::visit (HIR::IdentifierPattern &)
}
void
-TypeCheckPattern::visit (HIR::GroupedPattern &)
-{
- // TODO
- gcc_unreachable ();
-}
-
-void
TypeCheckPattern::visit (HIR::QualifiedPathInExpression &)
{
// TODO
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.h b/gcc/rust/typecheck/rust-hir-type-check-pattern.h
index bdfc907..e755007 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.h
@@ -39,7 +39,6 @@ public:
void visit (HIR::LiteralPattern &pattern) override;
void visit (HIR::RangePattern &pattern) override;
void visit (HIR::IdentifierPattern &pattern) override;
- void visit (HIR::GroupedPattern &pattern) override;
void visit (HIR::QualifiedPathInExpression &pattern) override;
void visit (HIR::ReferencePattern &pattern) override;
void visit (HIR::SlicePattern &pattern) override;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
index 437782e..956249a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
@@ -82,7 +82,7 @@ TypeCheckStmt::visit (HIR::LetStmt &stmt)
{
infered = TyTy::TupleType::get_unit_type (stmt.get_mappings ().get_hirid ());
- const HIR::Pattern &stmt_pattern = *stmt.get_pattern ();
+ HIR::Pattern &stmt_pattern = *stmt.get_pattern ();
TyTy::BaseType *init_expr_ty = nullptr;
Location init_expr_locus;
if (stmt.has_init_expr ())
@@ -111,27 +111,25 @@ TypeCheckStmt::visit (HIR::LetStmt &stmt)
TyTy::TyWithLocation (specified_ty, specified_ty_locus),
TyTy::TyWithLocation (init_expr_ty, init_expr_locus),
stmt.get_locus ());
- context->insert_type (stmt_pattern.get_pattern_mappings (), specified_ty);
+ TypeCheckPattern::Resolve (&stmt_pattern, specified_ty);
}
else
{
// let x:i32;
if (specified_ty != nullptr)
{
- context->insert_type (stmt_pattern.get_pattern_mappings (),
- specified_ty);
+ TypeCheckPattern::Resolve (&stmt_pattern, specified_ty);
}
// let x = 123;
else if (init_expr_ty != nullptr)
{
- context->insert_type (stmt_pattern.get_pattern_mappings (),
- init_expr_ty);
+ TypeCheckPattern::Resolve (&stmt_pattern, init_expr_ty);
}
// let x;
else
{
- context->insert_type (
- stmt_pattern.get_pattern_mappings (),
+ TypeCheckPattern::Resolve (
+ &stmt_pattern,
new TyTy::InferType (
stmt_pattern.get_pattern_mappings ().get_hirid (),
TyTy::InferType::InferTypeKind::GENERAL, stmt.get_locus ()));
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index adec2f9..6d4b9b8 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -19,10 +19,11 @@
#ifndef RUST_HIR_TYPE_CHECK
#define RUST_HIR_TYPE_CHECK
+#include "rust-type-util.h"
#include "rust-hir-full-decls.h"
#include "rust-hir-map.h"
#include "rust-tyty.h"
-#include "rust-hir-trait-ref.h"
+#include "rust-hir-trait-reference.h"
#include "rust-autoderef.h"
namespace Rust {
@@ -38,37 +39,17 @@ public:
TRAIT_ITEM,
};
- TypeCheckContextItem (HIR::Function *item)
- : type (ItemType::ITEM), item (item)
- {}
+ TypeCheckContextItem (HIR::Function *item);
+ TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item);
+ TypeCheckContextItem (HIR::TraitItemFunc *trait_item);
- TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item)
- : type (ItemType::IMPL_ITEM), item (impl_block, item)
- {}
+ ItemType get_type () const;
- TypeCheckContextItem (HIR::TraitItemFunc *trait_item)
- : type (ItemType::TRAIT_ITEM), item (trait_item)
- {}
+ HIR::Function *get_item ();
- ItemType get_type () const { return type; }
+ std::pair<HIR::ImplBlock *, HIR::Function *> &get_impl_item ();
- HIR::Function *get_item ()
- {
- rust_assert (get_type () == ItemType::ITEM);
- return item.item;
- }
-
- std::pair<HIR::ImplBlock *, HIR::Function *> &get_impl_item ()
- {
- rust_assert (get_type () == ItemType::IMPL_ITEM);
- return item.impl_item;
- };
-
- HIR::TraitItemFunc *get_trait_item ()
- {
- rust_assert (get_type () == ItemType::TRAIT_ITEM);
- return item.trait_item;
- }
+ HIR::TraitItemFunc *get_trait_item ();
TyTy::FnType *get_context_type ();
@@ -79,13 +60,9 @@ private:
std::pair<HIR::ImplBlock *, HIR::Function *> impl_item;
HIR::TraitItemFunc *trait_item;
- Item (HIR::Function *item) : item (item) {}
-
- Item (HIR::ImplBlock *impl_block, HIR::Function *item)
- : impl_item ({impl_block, item})
- {}
-
- Item (HIR::TraitItemFunc *trait_item) : trait_item (trait_item) {}
+ Item (HIR::Function *item);
+ Item (HIR::ImplBlock *impl_block, HIR::Function *item);
+ Item (HIR::TraitItemFunc *trait_item);
};
ItemType type;
@@ -118,283 +95,71 @@ public:
void push_return_type (TypeCheckContextItem item,
TyTy::BaseType *return_type);
void pop_return_type ();
+ void iterate (std::function<bool (HirId, TyTy::BaseType *)> cb);
- void iterate (std::function<bool (HirId, TyTy::BaseType *)> cb)
- {
- for (auto it = resolved.begin (); it != resolved.end (); it++)
- {
- if (!cb (it->first, it->second))
- return;
- }
- }
-
- bool have_loop_context () const { return !loop_type_stack.empty (); }
-
- void push_new_loop_context (HirId id, Location locus)
- {
- TyTy::BaseType *infer_var
- = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
- locus);
- loop_type_stack.push_back (infer_var);
- }
-
- void push_new_while_loop_context (HirId id)
- {
- TyTy::BaseType *infer_var = new TyTy::ErrorType (id);
- loop_type_stack.push_back (infer_var);
- }
-
- TyTy::BaseType *peek_loop_context () { return loop_type_stack.back (); }
-
- TyTy::BaseType *pop_loop_context ()
- {
- auto back = peek_loop_context ();
- loop_type_stack.pop_back ();
- return back;
- }
-
- void swap_head_loop_context (TyTy::BaseType *val)
- {
- loop_type_stack.pop_back ();
- loop_type_stack.push_back (val);
- }
-
- void insert_trait_reference (DefId id, TraitReference &&ref)
- {
- rust_assert (trait_context.find (id) == trait_context.end ());
- trait_context.emplace (id, std::move (ref));
- }
-
- bool lookup_trait_reference (DefId id, TraitReference **ref)
- {
- auto it = trait_context.find (id);
- if (it == trait_context.end ())
- return false;
+ bool have_loop_context () const;
+ void push_new_loop_context (HirId id, Location locus);
+ void push_new_while_loop_context (HirId id);
+ TyTy::BaseType *peek_loop_context ();
+ TyTy::BaseType *pop_loop_context ();
- *ref = &it->second;
- return true;
- }
-
- void insert_receiver (HirId id, TyTy::BaseType *t)
- {
- receiver_context[id] = t;
- }
+ void swap_head_loop_context (TyTy::BaseType *val);
- bool lookup_receiver (HirId id, TyTy::BaseType **ref)
- {
- auto it = receiver_context.find (id);
- if (it == receiver_context.end ())
- return false;
+ void insert_trait_reference (DefId id, TraitReference &&ref);
+ bool lookup_trait_reference (DefId id, TraitReference **ref);
- *ref = it->second;
- return true;
- }
+ void insert_receiver (HirId id, TyTy::BaseType *t);
+ bool lookup_receiver (HirId id, TyTy::BaseType **ref);
- void insert_associated_trait_impl (HirId id, AssociatedImplTrait &&associated)
- {
- rust_assert (associated_impl_traits.find (id)
- == associated_impl_traits.end ());
- associated_impl_traits.emplace (id, std::move (associated));
- }
+ void insert_associated_trait_impl (HirId id,
+ AssociatedImplTrait &&associated);
+ bool lookup_associated_trait_impl (HirId id,
+ AssociatedImplTrait **associated);
- bool lookup_associated_trait_impl (HirId id, AssociatedImplTrait **associated)
- {
- auto it = associated_impl_traits.find (id);
- if (it == associated_impl_traits.end ())
- return false;
-
- *associated = &it->second;
- return true;
- }
-
- void insert_associated_type_mapping (HirId id, HirId mapping)
- {
- associated_type_mappings[id] = mapping;
- }
-
- void clear_associated_type_mapping (HirId id)
- {
- auto it = associated_type_mappings.find (id);
- if (it != associated_type_mappings.end ())
- associated_type_mappings.erase (it);
- }
+ void insert_associated_type_mapping (HirId id, HirId mapping);
+ void clear_associated_type_mapping (HirId id);
// lookup any associated type mappings, the out parameter of mapping is
// allowed to be nullptr which allows this interface to do a simple does exist
// check
- bool lookup_associated_type_mapping (HirId id, HirId *mapping)
- {
- auto it = associated_type_mappings.find (id);
- if (it == associated_type_mappings.end ())
- return false;
-
- if (mapping != nullptr)
- *mapping = it->second;
-
- return true;
- }
+ bool lookup_associated_type_mapping (HirId id, HirId *mapping);
void insert_associated_impl_mapping (HirId trait_id,
const TyTy::BaseType *impl_type,
- HirId impl_id)
- {
- auto it = associated_traits_to_impls.find (trait_id);
- if (it == associated_traits_to_impls.end ())
- {
- associated_traits_to_impls[trait_id] = {};
- }
-
- associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id});
- }
-
+ HirId impl_id);
bool lookup_associated_impl_mapping_for_self (HirId trait_id,
const TyTy::BaseType *self,
- HirId *mapping)
- {
- auto it = associated_traits_to_impls.find (trait_id);
- if (it == associated_traits_to_impls.end ())
- return false;
-
- for (auto &item : it->second)
- {
- if (item.first->can_eq (self, false))
- {
- *mapping = item.second;
- return true;
- }
- }
- return false;
- }
+ HirId *mapping);
void insert_autoderef_mappings (HirId id,
- std::vector<Adjustment> &&adjustments)
- {
- rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ());
- autoderef_mappings.emplace (id, std::move (adjustments));
- }
-
+ std::vector<Adjustment> &&adjustments);
bool lookup_autoderef_mappings (HirId id,
- std::vector<Adjustment> **adjustments)
- {
- auto it = autoderef_mappings.find (id);
- if (it == autoderef_mappings.end ())
- return false;
-
- *adjustments = &it->second;
- return true;
- }
+ std::vector<Adjustment> **adjustments);
void insert_cast_autoderef_mappings (HirId id,
- std::vector<Adjustment> &&adjustments)
- {
- rust_assert (cast_autoderef_mappings.find (id)
- == cast_autoderef_mappings.end ());
- cast_autoderef_mappings.emplace (id, std::move (adjustments));
- }
-
+ std::vector<Adjustment> &&adjustments);
bool lookup_cast_autoderef_mappings (HirId id,
- std::vector<Adjustment> **adjustments)
- {
- auto it = cast_autoderef_mappings.find (id);
- if (it == cast_autoderef_mappings.end ())
- return false;
+ std::vector<Adjustment> **adjustments);
- *adjustments = &it->second;
- return true;
- }
+ void insert_variant_definition (HirId id, HirId variant);
+ bool lookup_variant_definition (HirId id, HirId *variant);
- void insert_variant_definition (HirId id, HirId variant)
- {
- auto it = variants.find (id);
- rust_assert (it == variants.end ());
+ void insert_operator_overload (HirId id, TyTy::FnType *call_site);
+ bool lookup_operator_overload (HirId id, TyTy::FnType **call);
- variants[id] = variant;
- }
+ void insert_unconstrained_check_marker (HirId id, bool status);
+ bool have_checked_for_unconstrained (HirId id, bool *result);
- bool lookup_variant_definition (HirId id, HirId *variant)
- {
- auto it = variants.find (id);
- if (it == variants.end ())
- return false;
+ void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate);
+ bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result);
- *variant = it->second;
- return true;
- }
-
- void insert_operator_overload (HirId id, TyTy::FnType *call_site)
- {
- auto it = operator_overloads.find (id);
- rust_assert (it == operator_overloads.end ());
-
- operator_overloads[id] = call_site;
- }
-
- bool lookup_operator_overload (HirId id, TyTy::FnType **call)
- {
- auto it = operator_overloads.find (id);
- if (it == operator_overloads.end ())
- return false;
-
- *call = it->second;
- return true;
- }
+ void insert_query (HirId id);
+ void query_completed (HirId id);
+ bool query_in_progress (HirId id) const;
- void insert_unconstrained_check_marker (HirId id, bool status)
- {
- unconstrained[id] = status;
- }
-
- bool have_checked_for_unconstrained (HirId id, bool *result)
- {
- auto it = unconstrained.find (id);
- bool found = it != unconstrained.end ();
- if (!found)
- return false;
-
- *result = it->second;
- return true;
- }
-
- void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate)
- {
- auto it = predicates.find (id);
- rust_assert (it == predicates.end ());
-
- predicates.insert ({id, predicate});
- }
-
- bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result)
- {
- auto it = predicates.find (id);
- bool found = it != predicates.end ();
- if (!found)
- return false;
-
- *result = it->second;
- return true;
- }
-
- void insert_query (HirId id) { querys_in_progress.insert (id); }
-
- void query_completed (HirId id) { querys_in_progress.erase (id); }
-
- bool query_in_progress (HirId id) const
- {
- return querys_in_progress.find (id) != querys_in_progress.end ();
- }
-
- void insert_trait_query (DefId id) { trait_queries_in_progress.insert (id); }
-
- void trait_query_completed (DefId id)
- {
- trait_queries_in_progress.erase (id);
- }
-
- bool trait_query_in_progress (DefId id) const
- {
- return trait_queries_in_progress.find (id)
- != trait_queries_in_progress.end ();
- }
+ void insert_trait_query (DefId id);
+ void trait_query_completed (DefId id);
+ bool trait_query_in_progress (DefId id) const;
private:
TypeCheckContext ();
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc
index e1d9888..dc93857 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.cc
+++ b/gcc/rust/typecheck/rust-substitution-mapper.cc
@@ -22,6 +22,116 @@
namespace Rust {
namespace Resolver {
+SubstMapper::SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus)
+ : resolved (new TyTy::ErrorType (ref)), generics (generics), locus (locus)
+{}
+
+TyTy::BaseType *
+SubstMapper::Resolve (TyTy::BaseType *base, Location locus,
+ HIR::GenericArgs *generics)
+{
+ SubstMapper mapper (base->get_ref (), generics, locus);
+ base->accept_vis (mapper);
+ rust_assert (mapper.resolved != nullptr);
+ return mapper.resolved;
+}
+
+TyTy::BaseType *
+SubstMapper::InferSubst (TyTy::BaseType *base, Location locus)
+{
+ return SubstMapper::Resolve (base, locus, nullptr);
+}
+
+bool
+SubstMapper::have_generic_args () const
+{
+ return generics != nullptr;
+}
+
+void
+SubstMapper::visit (TyTy::FnType &type)
+{
+ TyTy::FnType *concrete = nullptr;
+ if (!have_generic_args ())
+ {
+ TyTy::BaseType *substs = type.infer_substitions (locus);
+ rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF);
+ concrete = static_cast<TyTy::FnType *> (substs);
+ }
+ else
+ {
+ TyTy::SubstitutionArgumentMappings mappings
+ = type.get_mappings_from_generic_args (*generics);
+ if (mappings.is_error ())
+ return;
+
+ concrete = type.handle_substitions (mappings);
+ }
+
+ if (concrete != nullptr)
+ resolved = concrete;
+}
+
+void
+SubstMapper::visit (TyTy::ADTType &type)
+{
+ TyTy::ADTType *concrete = nullptr;
+ if (!have_generic_args ())
+ {
+ TyTy::BaseType *substs = type.infer_substitions (locus);
+ rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
+ concrete = static_cast<TyTy::ADTType *> (substs);
+ }
+ else
+ {
+ TyTy::SubstitutionArgumentMappings mappings
+ = type.get_mappings_from_generic_args (*generics);
+ if (mappings.is_error ())
+ return;
+
+ concrete = type.handle_substitions (mappings);
+ }
+
+ if (concrete != nullptr)
+ resolved = concrete;
+}
+
+void
+SubstMapper::visit (TyTy::PlaceholderType &type)
+{
+ rust_assert (type.can_resolve ());
+ resolved = SubstMapper::Resolve (type.resolve (), locus, generics);
+}
+
+void
+SubstMapper::visit (TyTy::ProjectionType &type)
+{
+ TyTy::ProjectionType *concrete = nullptr;
+ if (!have_generic_args ())
+ {
+ TyTy::BaseType *substs = type.infer_substitions (locus);
+ rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION);
+ concrete = static_cast<TyTy::ProjectionType *> (substs);
+ }
+ else
+ {
+ TyTy::SubstitutionArgumentMappings mappings
+ = type.get_mappings_from_generic_args (*generics);
+ if (mappings.is_error ())
+ return;
+
+ concrete = type.handle_substitions (mappings);
+ }
+
+ if (concrete != nullptr)
+ resolved = concrete;
+}
+
+SubstMapperInternal::SubstMapperInternal (
+ HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
+ : resolved (new TyTy::ErrorType (ref)), mappings (mappings)
+{}
+
TyTy::BaseType *
SubstMapperInternal::Resolve (TyTy::BaseType *base,
TyTy::SubstitutionArgumentMappings &mappings)
@@ -73,5 +183,238 @@ SubstMapperInternal::mappings_are_bound (
return false;
}
+void
+SubstMapperInternal::visit (TyTy::FnType &type)
+{
+ TyTy::SubstitutionArgumentMappings adjusted
+ = type.adjust_mappings_for_this (mappings);
+ if (adjusted.is_error ())
+ return;
+
+ TyTy::BaseType *concrete = type.handle_substitions (adjusted);
+ if (concrete != nullptr)
+ resolved = concrete;
+}
+
+void
+SubstMapperInternal::visit (TyTy::ADTType &type)
+{
+ TyTy::SubstitutionArgumentMappings adjusted
+ = type.adjust_mappings_for_this (mappings);
+ if (adjusted.is_error ())
+ return;
+
+ TyTy::BaseType *concrete = type.handle_substitions (adjusted);
+ if (concrete != nullptr)
+ resolved = concrete;
+}
+
+// these don't support generic arguments but might contain a type param
+void
+SubstMapperInternal::visit (TyTy::TupleType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ReferenceType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::PointerType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ParamType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::PlaceholderType &type)
+{
+ rust_assert (type.can_resolve ());
+ if (mappings.trait_item_mode ())
+ {
+ resolved = type.resolve ();
+ }
+ else
+ {
+ resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
+ }
+}
+
+void
+SubstMapperInternal::visit (TyTy::ProjectionType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ClosureType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ArrayType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::SliceType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+// nothing to do for these
+void
+SubstMapperInternal::visit (TyTy::InferType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::FnPtr &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::BoolType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::IntType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::UintType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::FloatType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::USizeType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::ISizeType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::ErrorType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::CharType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::StrType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::NeverType &type)
+{
+ resolved = type.clone ();
+}
+void
+SubstMapperInternal::visit (TyTy::DynamicObjectType &type)
+{
+ resolved = type.clone ();
+}
+
+// SubstMapperFromExisting
+
+SubstMapperFromExisting::SubstMapperFromExisting (TyTy::BaseType *concrete,
+ TyTy::BaseType *receiver)
+ : concrete (concrete), receiver (receiver), resolved (nullptr)
+{}
+
+TyTy::BaseType *
+SubstMapperFromExisting::Resolve (TyTy::BaseType *concrete,
+ TyTy::BaseType *receiver)
+{
+ rust_assert (concrete->get_kind () == receiver->get_kind ());
+
+ SubstMapperFromExisting mapper (concrete, receiver);
+ concrete->accept_vis (mapper);
+ return mapper.resolved;
+}
+
+void
+SubstMapperFromExisting::visit (TyTy::FnType &type)
+{
+ rust_assert (type.was_substituted ());
+
+ TyTy::FnType *to_sub = static_cast<TyTy::FnType *> (receiver);
+ resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
+}
+
+void
+SubstMapperFromExisting::visit (TyTy::ADTType &type)
+{
+ rust_assert (type.was_substituted ());
+
+ TyTy::ADTType *to_sub = static_cast<TyTy::ADTType *> (receiver);
+ resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
+}
+
+void
+SubstMapperFromExisting::visit (TyTy::ClosureType &type)
+{
+ rust_assert (type.was_substituted ());
+
+ TyTy::ClosureType *to_sub = static_cast<TyTy::ClosureType *> (receiver);
+ resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
+}
+
+// GetUsedSubstArgs
+
+GetUsedSubstArgs::GetUsedSubstArgs ()
+ : args (TyTy::SubstitutionArgumentMappings::error ())
+{}
+
+TyTy::SubstitutionArgumentMappings
+GetUsedSubstArgs::From (const TyTy::BaseType *from)
+{
+ GetUsedSubstArgs mapper;
+ from->accept_vis (mapper);
+ return mapper.args;
+}
+
+void
+GetUsedSubstArgs::visit (const TyTy::FnType &type)
+{
+ args = type.get_substitution_arguments ();
+}
+
+void
+GetUsedSubstArgs::visit (const TyTy::ADTType &type)
+{
+ args = type.get_substitution_arguments ();
+}
+
+void
+GetUsedSubstArgs::visit (const TyTy::ClosureType &type)
+{
+ args = type.get_substitution_arguments ();
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index 995d9c8..43b80b3 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -29,95 +29,16 @@ class SubstMapper : public TyTy::TyVisitor
{
public:
static TyTy::BaseType *Resolve (TyTy::BaseType *base, Location locus,
- HIR::GenericArgs *generics = nullptr)
- {
- SubstMapper mapper (base->get_ref (), generics, locus);
- base->accept_vis (mapper);
- rust_assert (mapper.resolved != nullptr);
- return mapper.resolved;
- }
+ HIR::GenericArgs *generics = nullptr);
- static TyTy::BaseType *InferSubst (TyTy::BaseType *base, Location locus)
- {
- return SubstMapper::Resolve (base, locus, nullptr);
- }
+ static TyTy::BaseType *InferSubst (TyTy::BaseType *base, Location locus);
- bool have_generic_args () const { return generics != nullptr; }
+ bool have_generic_args () const;
- void visit (TyTy::FnType &type) override
- {
- TyTy::FnType *concrete = nullptr;
- if (!have_generic_args ())
- {
- TyTy::BaseType *substs = type.infer_substitions (locus);
- rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF);
- concrete = static_cast<TyTy::FnType *> (substs);
- }
- else
- {
- TyTy::SubstitutionArgumentMappings mappings
- = type.get_mappings_from_generic_args (*generics);
- if (mappings.is_error ())
- return;
-
- concrete = type.handle_substitions (mappings);
- }
-
- if (concrete != nullptr)
- resolved = concrete;
- }
-
- void visit (TyTy::ADTType &type) override
- {
- TyTy::ADTType *concrete = nullptr;
- if (!have_generic_args ())
- {
- TyTy::BaseType *substs = type.infer_substitions (locus);
- rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
- concrete = static_cast<TyTy::ADTType *> (substs);
- }
- else
- {
- TyTy::SubstitutionArgumentMappings mappings
- = type.get_mappings_from_generic_args (*generics);
- if (mappings.is_error ())
- return;
-
- concrete = type.handle_substitions (mappings);
- }
-
- if (concrete != nullptr)
- resolved = concrete;
- }
-
- void visit (TyTy::PlaceholderType &type) override
- {
- rust_assert (type.can_resolve ());
- resolved = SubstMapper::Resolve (type.resolve (), locus, generics);
- }
-
- void visit (TyTy::ProjectionType &type) override
- {
- TyTy::ProjectionType *concrete = nullptr;
- if (!have_generic_args ())
- {
- TyTy::BaseType *substs = type.infer_substitions (locus);
- rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION);
- concrete = static_cast<TyTy::ProjectionType *> (substs);
- }
- else
- {
- TyTy::SubstitutionArgumentMappings mappings
- = type.get_mappings_from_generic_args (*generics);
- if (mappings.is_error ())
- return;
-
- concrete = type.handle_substitions (mappings);
- }
-
- if (concrete != nullptr)
- resolved = concrete;
- }
+ void visit (TyTy::FnType &type) override;
+ void visit (TyTy::ADTType &type) override;
+ void visit (TyTy::PlaceholderType &type) override;
+ void visit (TyTy::ProjectionType &type) override;
// nothing to do for these
void visit (TyTy::InferType &) override { gcc_unreachable (); }
@@ -142,9 +63,7 @@ public:
void visit (TyTy::ClosureType &) override { gcc_unreachable (); }
private:
- SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus)
- : resolved (new TyTy::ErrorType (ref)), generics (generics), locus (locus)
- {}
+ SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus);
TyTy::BaseType *resolved;
HIR::GenericArgs *generics;
@@ -160,106 +79,33 @@ public:
static bool mappings_are_bound (TyTy::BaseType *ty,
TyTy::SubstitutionArgumentMappings &mappings);
- void visit (TyTy::FnType &type) override
- {
- TyTy::SubstitutionArgumentMappings adjusted
- = type.adjust_mappings_for_this (mappings);
- if (adjusted.is_error ())
- return;
-
- TyTy::BaseType *concrete = type.handle_substitions (adjusted);
- if (concrete != nullptr)
- resolved = concrete;
- }
-
- void visit (TyTy::ADTType &type) override
- {
- TyTy::SubstitutionArgumentMappings adjusted
- = type.adjust_mappings_for_this (mappings);
- if (adjusted.is_error ())
- return;
-
- TyTy::BaseType *concrete = type.handle_substitions (adjusted);
- if (concrete != nullptr)
- resolved = concrete;
- }
-
- // these don't support generic arguments but might contain a type param
- void visit (TyTy::TupleType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::ReferenceType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::PointerType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::ParamType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::PlaceholderType &type) override
- {
- rust_assert (type.can_resolve ());
- if (mappings.trait_item_mode ())
- {
- resolved = type.resolve ();
- }
- else
- {
- resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
- }
- }
-
- void visit (TyTy::ProjectionType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::ClosureType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::ArrayType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- void visit (TyTy::SliceType &type) override
- {
- resolved = type.handle_substitions (mappings);
- }
-
- // nothing to do for these
- void visit (TyTy::InferType &type) override { resolved = type.clone (); }
- void visit (TyTy::FnPtr &type) override { resolved = type.clone (); }
- void visit (TyTy::BoolType &type) override { resolved = type.clone (); }
- void visit (TyTy::IntType &type) override { resolved = type.clone (); }
- void visit (TyTy::UintType &type) override { resolved = type.clone (); }
- void visit (TyTy::FloatType &type) override { resolved = type.clone (); }
- void visit (TyTy::USizeType &type) override { resolved = type.clone (); }
- void visit (TyTy::ISizeType &type) override { resolved = type.clone (); }
- void visit (TyTy::ErrorType &type) override { resolved = type.clone (); }
- void visit (TyTy::CharType &type) override { resolved = type.clone (); }
- void visit (TyTy::StrType &type) override { resolved = type.clone (); }
- void visit (TyTy::NeverType &type) override { resolved = type.clone (); }
- void visit (TyTy::DynamicObjectType &type) override
- {
- resolved = type.clone ();
- }
+ void visit (TyTy::FnType &type) override;
+ void visit (TyTy::ADTType &type) override;
+ void visit (TyTy::TupleType &type) override;
+ void visit (TyTy::ReferenceType &type) override;
+ void visit (TyTy::PointerType &type) override;
+ void visit (TyTy::ParamType &type) override;
+ void visit (TyTy::PlaceholderType &type) override;
+ void visit (TyTy::ProjectionType &type) override;
+ void visit (TyTy::ClosureType &type) override;
+ void visit (TyTy::ArrayType &type) override;
+ void visit (TyTy::SliceType &type) override;
+ void visit (TyTy::InferType &type) override;
+ void visit (TyTy::FnPtr &type) override;
+ void visit (TyTy::BoolType &type) override;
+ void visit (TyTy::IntType &type) override;
+ void visit (TyTy::UintType &type) override;
+ void visit (TyTy::FloatType &type) override;
+ void visit (TyTy::USizeType &type) override;
+ void visit (TyTy::ISizeType &type) override;
+ void visit (TyTy::ErrorType &type) override;
+ void visit (TyTy::CharType &type) override;
+ void visit (TyTy::StrType &type) override;
+ void visit (TyTy::NeverType &type) override;
+ void visit (TyTy::DynamicObjectType &type) override;
private:
- SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
- : resolved (new TyTy::ErrorType (ref)), mappings (mappings)
- {}
+ SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings);
TyTy::BaseType *resolved;
TyTy::SubstitutionArgumentMappings &mappings;
@@ -269,38 +115,11 @@ class SubstMapperFromExisting : public TyTy::TyVisitor
{
public:
static TyTy::BaseType *Resolve (TyTy::BaseType *concrete,
- TyTy::BaseType *receiver)
- {
- rust_assert (concrete->get_kind () == receiver->get_kind ());
-
- SubstMapperFromExisting mapper (concrete, receiver);
- concrete->accept_vis (mapper);
- return mapper.resolved;
- }
+ TyTy::BaseType *receiver);
- void visit (TyTy::FnType &type) override
- {
- rust_assert (type.was_substituted ());
-
- TyTy::FnType *to_sub = static_cast<TyTy::FnType *> (receiver);
- resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
- }
-
- void visit (TyTy::ADTType &type) override
- {
- rust_assert (type.was_substituted ());
-
- TyTy::ADTType *to_sub = static_cast<TyTy::ADTType *> (receiver);
- resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
- }
-
- void visit (TyTy::ClosureType &type) override
- {
- rust_assert (type.was_substituted ());
-
- TyTy::ClosureType *to_sub = static_cast<TyTy::ClosureType *> (receiver);
- resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
- }
+ void visit (TyTy::FnType &type) override;
+ void visit (TyTy::ADTType &type) override;
+ void visit (TyTy::ClosureType &type) override;
void visit (TyTy::InferType &) override { gcc_unreachable (); }
void visit (TyTy::TupleType &) override { gcc_unreachable (); }
@@ -325,40 +144,21 @@ public:
void visit (TyTy::DynamicObjectType &) override { gcc_unreachable (); }
private:
- SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver)
- : concrete (concrete), receiver (receiver), resolved (nullptr)
- {}
+ SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver);
TyTy::BaseType *concrete;
TyTy::BaseType *receiver;
-
TyTy::BaseType *resolved;
};
class GetUsedSubstArgs : public TyTy::TyConstVisitor
{
public:
- static TyTy::SubstitutionArgumentMappings From (const TyTy::BaseType *from)
- {
- GetUsedSubstArgs mapper;
- from->accept_vis (mapper);
- return mapper.args;
- }
-
- void visit (const TyTy::FnType &type) override
- {
- args = type.get_substitution_arguments ();
- }
-
- void visit (const TyTy::ADTType &type) override
- {
- args = type.get_substitution_arguments ();
- }
+ static TyTy::SubstitutionArgumentMappings From (const TyTy::BaseType *from);
- void visit (const TyTy::ClosureType &type) override
- {
- args = type.get_substitution_arguments ();
- }
+ void visit (const TyTy::FnType &type) override;
+ void visit (const TyTy::ADTType &type) override;
+ void visit (const TyTy::ClosureType &type) override;
void visit (const TyTy::InferType &) override {}
void visit (const TyTy::TupleType &) override {}
@@ -383,7 +183,7 @@ public:
void visit (const TyTy::DynamicObjectType &) override {}
private:
- GetUsedSubstArgs () : args (TyTy::SubstitutionArgumentMappings::error ()) {}
+ GetUsedSubstArgs ();
TyTy::SubstitutionArgumentMappings args;
};
diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc
deleted file mode 100644
index 886842b..0000000
--- a/gcc/rust/typecheck/rust-tyctx.cc
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright (C) 2020-2023 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-hir-type-check.h"
-
-namespace Rust {
-namespace Resolver {
-
-TypeCheckContext *
-TypeCheckContext::get ()
-{
- static TypeCheckContext *instance;
- if (instance == nullptr)
- instance = new TypeCheckContext ();
-
- return instance;
-}
-
-TypeCheckContext::TypeCheckContext () {}
-
-TypeCheckContext::~TypeCheckContext () {}
-
-bool
-TypeCheckContext::lookup_builtin (NodeId id, TyTy::BaseType **type)
-{
- auto ref_it = node_id_refs.find (id);
- if (ref_it == node_id_refs.end ())
- return false;
-
- auto it = resolved.find (ref_it->second);
- if (it == resolved.end ())
- return false;
-
- *type = it->second;
- return true;
-}
-
-bool
-TypeCheckContext::lookup_builtin (std::string name, TyTy::BaseType **type)
-{
- for (auto &builtin : builtins)
- {
- if (name.compare (builtin->as_string ()) == 0)
- {
- *type = builtin.get ();
- return true;
- }
- }
- return false;
-}
-
-void
-TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::BaseType *type)
-{
- node_id_refs[ref] = id;
- resolved[id] = type;
- builtins.push_back (std::unique_ptr<TyTy::BaseType> (type));
-}
-
-void
-TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings,
- TyTy::BaseType *type)
-{
- rust_assert (type != nullptr);
- NodeId ref = mappings.get_nodeid ();
- HirId id = mappings.get_hirid ();
- node_id_refs[ref] = id;
- resolved[id] = type;
-}
-
-void
-TypeCheckContext::insert_implicit_type (TyTy::BaseType *type)
-{
- rust_assert (type != nullptr);
- resolved[type->get_ref ()] = type;
-}
-
-void
-TypeCheckContext::insert_implicit_type (HirId id, TyTy::BaseType *type)
-{
- rust_assert (type != nullptr);
- resolved[id] = type;
-}
-
-bool
-TypeCheckContext::lookup_type (HirId id, TyTy::BaseType **type) const
-{
- auto it = resolved.find (id);
- if (it == resolved.end ())
- return false;
-
- *type = it->second;
- return true;
-}
-
-void
-TypeCheckContext::insert_type_by_node_id (NodeId ref, HirId id)
-{
- rust_assert (node_id_refs.find (ref) == node_id_refs.end ());
- node_id_refs[ref] = id;
-}
-
-bool
-TypeCheckContext::lookup_type_by_node_id (NodeId ref, HirId *id)
-{
- auto it = node_id_refs.find (ref);
- if (it == node_id_refs.end ())
- return false;
-
- *id = it->second;
- return true;
-}
-
-TyTy::BaseType *
-TypeCheckContext::peek_return_type ()
-{
- rust_assert (!return_type_stack.empty ());
- return return_type_stack.back ().second;
-}
-
-void
-TypeCheckContext::push_return_type (TypeCheckContextItem item,
- TyTy::BaseType *return_type)
-{
- return_type_stack.push_back ({std::move (item), return_type});
-}
-
-void
-TypeCheckContext::pop_return_type ()
-{
- rust_assert (!return_type_stack.empty ());
- return_type_stack.pop_back ();
-}
-
-TypeCheckContextItem &
-TypeCheckContext::peek_context ()
-{
- rust_assert (!return_type_stack.empty ());
- return return_type_stack.back ().first;
-}
-
-// TypeCheckContextItem
-
-TyTy::FnType *
-TypeCheckContextItem::get_context_type ()
-{
- auto &context = *TypeCheckContext::get ();
-
- HirId reference = UNKNOWN_HIRID;
- switch (get_type ())
- {
- case ITEM:
- reference = get_item ()->get_mappings ().get_hirid ();
- break;
-
- case IMPL_ITEM:
- reference = get_impl_item ().second->get_mappings ().get_hirid ();
- break;
-
- case TRAIT_ITEM:
- reference = get_trait_item ()->get_mappings ().get_hirid ();
- break;
- }
-
- rust_assert (reference != UNKNOWN_HIRID);
-
- TyTy::BaseType *lookup = nullptr;
- bool ok = context.lookup_type (reference, &lookup);
- rust_assert (ok);
- rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
- return static_cast<TyTy::FnType *> (lookup);
-}
-
-} // namespace Resolver
-} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc
new file mode 100644
index 0000000..4e38826
--- /dev/null
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -0,0 +1,108 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-type-util.h"
+#include "rust-diagnostics.h"
+#include "rust-hir-type-check.h"
+#include "rust-name-resolver.h"
+#include "rust-hir-visitor.h"
+#include "rust-hir-map.h"
+#include "rust-hir-type-check-item.h"
+#include "rust-hir-type-check-implitem.h"
+
+namespace Rust {
+namespace Resolver {
+
+bool
+query_type (HirId reference, TyTy::BaseType **result)
+{
+ Analysis::Mappings *mappings = Analysis::Mappings::get ();
+ TypeCheckContext *context = TypeCheckContext::get ();
+
+ if (context->query_in_progress (reference))
+ return false;
+
+ if (context->lookup_type (reference, result))
+ return true;
+
+ context->insert_query (reference);
+
+ HIR::Item *item = mappings->lookup_hir_item (reference);
+ if (item != nullptr)
+ {
+ rust_debug_loc (item->get_locus (), "resolved item {%u} to", reference);
+ *result = TypeCheckItem::Resolve (*item);
+ context->query_completed (reference);
+ return true;
+ }
+
+ HirId parent_impl_id = UNKNOWN_HIRID;
+ HIR::ImplItem *impl_item
+ = mappings->lookup_hir_implitem (reference, &parent_impl_id);
+ if (impl_item != nullptr)
+ {
+ HIR::ImplBlock *impl_block
+ = mappings->lookup_hir_impl_block (parent_impl_id);
+ rust_assert (impl_block != nullptr);
+
+ // found an impl item
+ rust_debug_loc (impl_item->get_locus (), "resolved impl-item {%u} to",
+ reference);
+
+ *result = TypeCheckItem::ResolveImplItem (*impl_block, *impl_item);
+ context->query_completed (reference);
+ return true;
+ }
+
+ // is it an impl_type?
+ HIR::ImplBlock *impl_block_by_type = nullptr;
+ bool found_impl_block_type
+ = mappings->lookup_impl_block_type (reference, &impl_block_by_type);
+ if (found_impl_block_type)
+ {
+ *result = TypeCheckItem::ResolveImplBlockSelf (*impl_block_by_type);
+ context->query_completed (reference);
+ return true;
+ }
+
+ // is it an extern item?
+ HirId parent_extern_block_id = UNKNOWN_HIRID;
+ HIR::ExternalItem *extern_item
+ = mappings->lookup_hir_extern_item (reference, &parent_extern_block_id);
+ if (extern_item != nullptr)
+ {
+ HIR::ExternBlock *block
+ = mappings->lookup_hir_extern_block (parent_extern_block_id);
+ rust_assert (block != nullptr);
+
+ *result = TypeCheckTopLevelExternItem::Resolve (extern_item, *block);
+ context->query_completed (reference);
+ return true;
+ }
+
+ // more?
+ Location possible_locus = mappings->lookup_location (reference);
+ rust_debug_loc (possible_locus, "query system failed to resolve: [%u]",
+ reference);
+ context->query_completed (reference);
+
+ return false;
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-type-util.h b/gcc/rust/typecheck/rust-type-util.h
new file mode 100644
index 0000000..a3f9efc
--- /dev/null
+++ b/gcc/rust/typecheck/rust-type-util.h
@@ -0,0 +1,38 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_TYPE_UTIL
+#define RUST_TYPE_UTIL
+
+#include "rust-mapping-common.h"
+
+namespace Rust {
+
+namespace TyTy {
+class BaseType;
+}
+
+namespace Resolver {
+
+extern bool
+query_type (HirId reference, TyTy::BaseType **result);
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_TYPE_UTIL
diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc
new file mode 100644
index 0000000..27ff969
--- /dev/null
+++ b/gcc/rust/typecheck/rust-typecheck-context.cc
@@ -0,0 +1,569 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-type-check.h"
+
+namespace Rust {
+namespace Resolver {
+
+TypeCheckContext *
+TypeCheckContext::get ()
+{
+ static TypeCheckContext *instance;
+ if (instance == nullptr)
+ instance = new TypeCheckContext ();
+
+ return instance;
+}
+
+TypeCheckContext::TypeCheckContext () {}
+
+TypeCheckContext::~TypeCheckContext () {}
+
+bool
+TypeCheckContext::lookup_builtin (NodeId id, TyTy::BaseType **type)
+{
+ auto ref_it = node_id_refs.find (id);
+ if (ref_it == node_id_refs.end ())
+ return false;
+
+ auto it = resolved.find (ref_it->second);
+ if (it == resolved.end ())
+ return false;
+
+ *type = it->second;
+ return true;
+}
+
+bool
+TypeCheckContext::lookup_builtin (std::string name, TyTy::BaseType **type)
+{
+ for (auto &builtin : builtins)
+ {
+ if (name.compare (builtin->as_string ()) == 0)
+ {
+ *type = builtin.get ();
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::BaseType *type)
+{
+ node_id_refs[ref] = id;
+ resolved[id] = type;
+ builtins.push_back (std::unique_ptr<TyTy::BaseType> (type));
+}
+
+void
+TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings,
+ TyTy::BaseType *type)
+{
+ rust_assert (type != nullptr);
+ NodeId ref = mappings.get_nodeid ();
+ HirId id = mappings.get_hirid ();
+ node_id_refs[ref] = id;
+ resolved[id] = type;
+}
+
+void
+TypeCheckContext::insert_implicit_type (TyTy::BaseType *type)
+{
+ rust_assert (type != nullptr);
+ resolved[type->get_ref ()] = type;
+}
+
+void
+TypeCheckContext::insert_implicit_type (HirId id, TyTy::BaseType *type)
+{
+ rust_assert (type != nullptr);
+ resolved[id] = type;
+}
+
+bool
+TypeCheckContext::lookup_type (HirId id, TyTy::BaseType **type) const
+{
+ auto it = resolved.find (id);
+ if (it == resolved.end ())
+ return false;
+
+ *type = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_type_by_node_id (NodeId ref, HirId id)
+{
+ rust_assert (node_id_refs.find (ref) == node_id_refs.end ());
+ node_id_refs[ref] = id;
+}
+
+bool
+TypeCheckContext::lookup_type_by_node_id (NodeId ref, HirId *id)
+{
+ auto it = node_id_refs.find (ref);
+ if (it == node_id_refs.end ())
+ return false;
+
+ *id = it->second;
+ return true;
+}
+
+TyTy::BaseType *
+TypeCheckContext::peek_return_type ()
+{
+ rust_assert (!return_type_stack.empty ());
+ return return_type_stack.back ().second;
+}
+
+void
+TypeCheckContext::push_return_type (TypeCheckContextItem item,
+ TyTy::BaseType *return_type)
+{
+ return_type_stack.push_back ({std::move (item), return_type});
+}
+
+void
+TypeCheckContext::pop_return_type ()
+{
+ rust_assert (!return_type_stack.empty ());
+ return_type_stack.pop_back ();
+}
+
+TypeCheckContextItem &
+TypeCheckContext::peek_context ()
+{
+ rust_assert (!return_type_stack.empty ());
+ return return_type_stack.back ().first;
+}
+
+void
+TypeCheckContext::iterate (std::function<bool (HirId, TyTy::BaseType *)> cb)
+{
+ for (auto it = resolved.begin (); it != resolved.end (); it++)
+ {
+ if (!cb (it->first, it->second))
+ return;
+ }
+}
+
+bool
+TypeCheckContext::have_loop_context () const
+{
+ return !loop_type_stack.empty ();
+}
+
+void
+TypeCheckContext::push_new_loop_context (HirId id, Location locus)
+{
+ TyTy::BaseType *infer_var
+ = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, locus);
+ loop_type_stack.push_back (infer_var);
+}
+
+void
+TypeCheckContext::push_new_while_loop_context (HirId id)
+{
+ TyTy::BaseType *infer_var = new TyTy::ErrorType (id);
+ loop_type_stack.push_back (infer_var);
+}
+
+TyTy::BaseType *
+TypeCheckContext::peek_loop_context ()
+{
+ return loop_type_stack.back ();
+}
+
+TyTy::BaseType *
+TypeCheckContext::pop_loop_context ()
+{
+ auto back = peek_loop_context ();
+ loop_type_stack.pop_back ();
+ return back;
+}
+
+void
+TypeCheckContext::swap_head_loop_context (TyTy::BaseType *val)
+{
+ loop_type_stack.pop_back ();
+ loop_type_stack.push_back (val);
+}
+
+void
+TypeCheckContext::insert_trait_reference (DefId id, TraitReference &&ref)
+{
+ rust_assert (trait_context.find (id) == trait_context.end ());
+ trait_context.emplace (id, std::move (ref));
+}
+
+bool
+TypeCheckContext::lookup_trait_reference (DefId id, TraitReference **ref)
+{
+ auto it = trait_context.find (id);
+ if (it == trait_context.end ())
+ return false;
+
+ *ref = &it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_receiver (HirId id, TyTy::BaseType *t)
+{
+ receiver_context[id] = t;
+}
+
+bool
+TypeCheckContext::lookup_receiver (HirId id, TyTy::BaseType **ref)
+{
+ auto it = receiver_context.find (id);
+ if (it == receiver_context.end ())
+ return false;
+
+ *ref = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_associated_trait_impl (
+ HirId id, AssociatedImplTrait &&associated)
+{
+ rust_assert (associated_impl_traits.find (id)
+ == associated_impl_traits.end ());
+ associated_impl_traits.emplace (id, std::move (associated));
+}
+
+bool
+TypeCheckContext::lookup_associated_trait_impl (
+ HirId id, AssociatedImplTrait **associated)
+{
+ auto it = associated_impl_traits.find (id);
+ if (it == associated_impl_traits.end ())
+ return false;
+
+ *associated = &it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_associated_type_mapping (HirId id, HirId mapping)
+{
+ associated_type_mappings[id] = mapping;
+}
+
+void
+TypeCheckContext::clear_associated_type_mapping (HirId id)
+{
+ auto it = associated_type_mappings.find (id);
+ if (it != associated_type_mappings.end ())
+ associated_type_mappings.erase (it);
+}
+
+// lookup any associated type mappings, the out parameter of mapping is
+// allowed to be nullptr which allows this interface to do a simple does exist
+// check
+bool
+TypeCheckContext::lookup_associated_type_mapping (HirId id, HirId *mapping)
+{
+ auto it = associated_type_mappings.find (id);
+ if (it == associated_type_mappings.end ())
+ return false;
+
+ if (mapping != nullptr)
+ *mapping = it->second;
+
+ return true;
+}
+
+void
+TypeCheckContext::insert_associated_impl_mapping (
+ HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id)
+{
+ auto it = associated_traits_to_impls.find (trait_id);
+ if (it == associated_traits_to_impls.end ())
+ {
+ associated_traits_to_impls[trait_id] = {};
+ }
+
+ associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id});
+}
+
+bool
+TypeCheckContext::lookup_associated_impl_mapping_for_self (
+ HirId trait_id, const TyTy::BaseType *self, HirId *mapping)
+{
+ auto it = associated_traits_to_impls.find (trait_id);
+ if (it == associated_traits_to_impls.end ())
+ return false;
+
+ for (auto &item : it->second)
+ {
+ if (item.first->can_eq (self, false))
+ {
+ *mapping = item.second;
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+TypeCheckContext::insert_autoderef_mappings (
+ HirId id, std::vector<Adjustment> &&adjustments)
+{
+ rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ());
+ autoderef_mappings.emplace (id, std::move (adjustments));
+}
+
+bool
+TypeCheckContext::lookup_autoderef_mappings (
+ HirId id, std::vector<Adjustment> **adjustments)
+{
+ auto it = autoderef_mappings.find (id);
+ if (it == autoderef_mappings.end ())
+ return false;
+
+ *adjustments = &it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_cast_autoderef_mappings (
+ HirId id, std::vector<Adjustment> &&adjustments)
+{
+ rust_assert (cast_autoderef_mappings.find (id)
+ == cast_autoderef_mappings.end ());
+ cast_autoderef_mappings.emplace (id, std::move (adjustments));
+}
+
+bool
+TypeCheckContext::lookup_cast_autoderef_mappings (
+ HirId id, std::vector<Adjustment> **adjustments)
+{
+ auto it = cast_autoderef_mappings.find (id);
+ if (it == cast_autoderef_mappings.end ())
+ return false;
+
+ *adjustments = &it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_variant_definition (HirId id, HirId variant)
+{
+ auto it = variants.find (id);
+ rust_assert (it == variants.end ());
+
+ variants[id] = variant;
+}
+
+bool
+TypeCheckContext::lookup_variant_definition (HirId id, HirId *variant)
+{
+ auto it = variants.find (id);
+ if (it == variants.end ())
+ return false;
+
+ *variant = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_operator_overload (HirId id, TyTy::FnType *call_site)
+{
+ auto it = operator_overloads.find (id);
+ rust_assert (it == operator_overloads.end ());
+
+ operator_overloads[id] = call_site;
+}
+
+bool
+TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call)
+{
+ auto it = operator_overloads.find (id);
+ if (it == operator_overloads.end ())
+ return false;
+
+ *call = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status)
+{
+ unconstrained[id] = status;
+}
+
+bool
+TypeCheckContext::have_checked_for_unconstrained (HirId id, bool *result)
+{
+ auto it = unconstrained.find (id);
+ bool found = it != unconstrained.end ();
+ if (!found)
+ return false;
+
+ *result = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_resolved_predicate (HirId id,
+ TyTy::TypeBoundPredicate predicate)
+{
+ auto it = predicates.find (id);
+ rust_assert (it == predicates.end ());
+
+ predicates.insert ({id, predicate});
+}
+
+bool
+TypeCheckContext::lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result)
+{
+ auto it = predicates.find (id);
+ bool found = it != predicates.end ();
+ if (!found)
+ return false;
+
+ *result = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::insert_query (HirId id)
+{
+ querys_in_progress.insert (id);
+}
+
+void
+TypeCheckContext::query_completed (HirId id)
+{
+ querys_in_progress.erase (id);
+}
+
+bool
+TypeCheckContext::query_in_progress (HirId id) const
+{
+ return querys_in_progress.find (id) != querys_in_progress.end ();
+}
+
+void
+TypeCheckContext::insert_trait_query (DefId id)
+{
+ trait_queries_in_progress.insert (id);
+}
+
+void
+TypeCheckContext::trait_query_completed (DefId id)
+{
+ trait_queries_in_progress.erase (id);
+}
+
+bool
+TypeCheckContext::trait_query_in_progress (DefId id) const
+{
+ return trait_queries_in_progress.find (id)
+ != trait_queries_in_progress.end ();
+}
+
+// TypeCheckContextItem
+
+TypeCheckContextItem::Item::Item (HIR::Function *item) : item (item) {}
+
+TypeCheckContextItem::Item::Item (HIR::ImplBlock *impl_block,
+ HIR::Function *item)
+ : impl_item ({impl_block, item})
+{}
+
+TypeCheckContextItem::Item::Item (HIR::TraitItemFunc *trait_item)
+ : trait_item (trait_item)
+{}
+
+TypeCheckContextItem::TypeCheckContextItem (HIR::Function *item)
+ : type (ItemType::ITEM), item (item)
+{}
+
+TypeCheckContextItem::TypeCheckContextItem (HIR::ImplBlock *impl_block,
+ HIR::Function *item)
+ : type (ItemType::IMPL_ITEM), item (impl_block, item)
+{}
+
+TypeCheckContextItem::TypeCheckContextItem (HIR::TraitItemFunc *trait_item)
+ : type (ItemType::TRAIT_ITEM), item (trait_item)
+{}
+
+HIR::Function *
+TypeCheckContextItem::get_item ()
+{
+ rust_assert (get_type () == ItemType::ITEM);
+ return item.item;
+}
+
+std::pair<HIR::ImplBlock *, HIR::Function *> &
+TypeCheckContextItem::get_impl_item ()
+{
+ rust_assert (get_type () == ItemType::IMPL_ITEM);
+ return item.impl_item;
+}
+
+HIR::TraitItemFunc *
+TypeCheckContextItem::get_trait_item ()
+{
+ rust_assert (get_type () == ItemType::TRAIT_ITEM);
+ return item.trait_item;
+}
+
+TypeCheckContextItem::ItemType
+TypeCheckContextItem::get_type () const
+{
+ return type;
+}
+
+TyTy::FnType *
+TypeCheckContextItem::get_context_type ()
+{
+ auto &context = *TypeCheckContext::get ();
+
+ HirId reference = UNKNOWN_HIRID;
+ switch (get_type ())
+ {
+ case ITEM:
+ reference = get_item ()->get_mappings ().get_hirid ();
+ break;
+
+ case IMPL_ITEM:
+ reference = get_impl_item ().second->get_mappings ().get_hirid ();
+ break;
+
+ case TRAIT_ITEM:
+ reference = get_trait_item ()->get_mappings ().get_hirid ();
+ break;
+ }
+
+ rust_assert (reference != UNKNOWN_HIRID);
+
+ TyTy::BaseType *lookup = nullptr;
+ bool ok = context.lookup_type (reference, &lookup);
+ rust_assert (ok);
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
+ return static_cast<TyTy::FnType *> (lookup);
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index 20a81ad..76d2eef 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -23,6 +23,41 @@
namespace Rust {
namespace Resolver {
+TypeBoundsProbe::TypeBoundsProbe (const TyTy::BaseType *receiver)
+ : TypeCheckBase (), receiver (receiver)
+{}
+
+std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
+TypeBoundsProbe::Probe (const TyTy::BaseType *receiver)
+{
+ TypeBoundsProbe probe (receiver);
+ probe.scan ();
+ return probe.trait_references;
+}
+
+bool
+TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver,
+ TraitReference *ref)
+{
+ for (auto &bound : receiver->get_specified_bounds ())
+ {
+ const TraitReference *b = bound.get ();
+ if (b->is_equal (*ref))
+ return true;
+ }
+
+ std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
+ = Probe (receiver);
+ for (auto &bound : bounds)
+ {
+ const TraitReference *b = bound.first;
+ if (b->is_equal (*ref))
+ return true;
+ }
+
+ return false;
+}
+
void
TypeBoundsProbe::scan ()
{
@@ -57,6 +92,75 @@ TypeBoundsProbe::scan ()
if (!trait_ref->is_error ())
trait_references.push_back ({trait_ref, path.second});
}
+
+ // marker traits...
+ assemble_sized_builtin ();
+}
+
+void
+TypeBoundsProbe::assemble_sized_builtin ()
+{
+ const TyTy::BaseType *raw = receiver->destructure ();
+
+ // does this thing actually implement sized?
+ switch (raw->get_kind ())
+ {
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ 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:
+ assemble_builtin_candidate (Analysis::RustLangItem::SIZED);
+ break;
+
+ // not-sure about this.... FIXME
+ case TyTy::INFER:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ break;
+ }
+}
+
+void
+TypeBoundsProbe::assemble_builtin_candidate (
+ Analysis::RustLangItem::ItemType lang_item)
+{
+ DefId id;
+ bool found_lang_item = mappings->lookup_lang_item (lang_item, &id);
+ if (!found_lang_item)
+ return;
+
+ HIR::Item *item = mappings->lookup_defid (id);
+ if (item == nullptr)
+ return;
+
+ rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
+ HIR::Trait *trait = static_cast<HIR::Trait *> (item);
+ const TyTy::BaseType *raw = receiver->destructure ();
+
+ // assemble the reference
+ TraitReference *trait_ref = TraitResolver::Resolve (*trait);
+ trait_references.push_back ({trait_ref, mappings->lookup_builtin_marker ()});
+
+ rust_debug ("Added builtin lang_item: %s for %s",
+ Analysis::RustLangItem::ToString (lang_item).c_str (),
+ raw->get_name ().c_str ());
}
TraitReference *
@@ -101,7 +205,8 @@ TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path)
= static_cast<HIR::TypePathSegmentFunction *> (final_seg.get ());
auto &fn = final_function_seg->get_function_path ();
- // we need to make implicit generic args which must be an implicit Tuple
+ // we need to make implicit generic args which must be an implicit
+ // Tuple
auto crate_num = mappings->get_current_crate ();
HirId implicit_args_id = mappings->get_next_hir_id ();
Analysis::NodeMapping mapping (crate_num,
@@ -145,11 +250,10 @@ TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path)
break;
}
- // FIXME
- // I think this should really be just be if the !args.is_empty() because
- // someone might wrongly apply generic arguments where they should not and
- // they will be missing error diagnostics
- if (predicate.requires_generic_args ())
+ // we try to apply generic arguments when they are non empty and or when the
+ // predicate requires them so that we get the relevant Foo expects x number
+ // arguments but got zero see test case rust/compile/traits12.rs
+ if (!args.is_empty () || predicate.requires_generic_args ())
{
// this is applying generic arguments to a trait reference
predicate.apply_generic_arguments (&args);
@@ -222,7 +326,7 @@ TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
}
used_arguments
- = SubstitutionArgumentMappings (copied_arg_mappings,
+ = SubstitutionArgumentMappings (copied_arg_mappings, {},
other.used_arguments.get_locus ());
}
@@ -258,7 +362,7 @@ TypeBoundPredicate::operator= (const TypeBoundPredicate &other)
}
used_arguments
- = SubstitutionArgumentMappings (copied_arg_mappings,
+ = SubstitutionArgumentMappings (copied_arg_mappings, {},
other.used_arguments.get_locus ());
return *this;
@@ -331,6 +435,19 @@ TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args)
if (ok && arg.get_tyty () != nullptr)
sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ());
}
+
+ // associated argument mappings
+ for (auto &it : subst_mappings.get_binding_args ())
+ {
+ std::string identifier = it.first;
+ TyTy::BaseType *type = it.second;
+
+ TypeBoundPredicateItem item = lookup_associated_item (identifier);
+ rust_assert (!item.is_error ());
+
+ const auto item_ref = item.get_raw_item ();
+ item_ref->associated_type_set (type);
+ }
}
bool
@@ -352,6 +469,30 @@ TypeBoundPredicate::lookup_associated_item (const std::string &search) const
return TypeBoundPredicateItem (this, trait_item_ref);
}
+TypeBoundPredicateItem::TypeBoundPredicateItem (
+ const TypeBoundPredicate *parent,
+ const Resolver::TraitItemReference *trait_item_ref)
+ : parent (parent), trait_item_ref (trait_item_ref)
+{}
+
+TypeBoundPredicateItem
+TypeBoundPredicateItem::error ()
+{
+ return TypeBoundPredicateItem (nullptr, nullptr);
+}
+
+bool
+TypeBoundPredicateItem::is_error () const
+{
+ return parent == nullptr || trait_item_ref == nullptr;
+}
+
+const TypeBoundPredicate *
+TypeBoundPredicateItem::get_parent () const
+{
+ return parent;
+}
+
TypeBoundPredicateItem
TypeBoundPredicate::lookup_associated_item (
const Resolver::TraitItemReference *ref) const
@@ -389,7 +530,8 @@ TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
adjusted_mappings.push_back (std::move (arg));
}
- SubstitutionArgumentMappings adjusted (adjusted_mappings, gargs.get_locus (),
+ SubstitutionArgumentMappings adjusted (adjusted_mappings, {},
+ gargs.get_locus (),
gargs.get_subst_cb (),
true /* trait-mode-flag */);
return Resolver::SubstMapperInternal::Resolve (trait_item_tyty, adjusted);
@@ -407,7 +549,7 @@ TypeBoundPredicate::is_error () const
BaseType *
TypeBoundPredicate::handle_substitions (
- SubstitutionArgumentMappings subst_mappings)
+ SubstitutionArgumentMappings &subst_mappings)
{
for (auto &sub : get_substs ())
{
@@ -421,6 +563,19 @@ TypeBoundPredicate::handle_substitions (
p->set_ty_ref (s->get_ty_ref ());
}
+ // associated argument mappings
+ for (auto &it : subst_mappings.get_binding_args ())
+ {
+ std::string identifier = it.first;
+ TyTy::BaseType *type = it.second;
+
+ TypeBoundPredicateItem item = lookup_associated_item (identifier);
+ rust_assert (!item.is_error ());
+
+ const auto item_ref = item.get_raw_item ();
+ item_ref->associated_type_set (type);
+ }
+
// FIXME more error handling at some point
// used_arguments = subst_mappings;
// error_flag |= used_arguments.is_error ();
@@ -440,6 +595,13 @@ TypeBoundPredicate::requires_generic_args () const
bool
TypeBoundPredicate::contains_associated_types () const
{
+ return get_num_associated_bindings () > 0;
+}
+
+size_t
+TypeBoundPredicate::get_num_associated_bindings () const
+{
+ size_t count = 0;
auto trait_ref = get ();
for (const auto &trait_item : trait_ref->get_trait_items ())
{
@@ -447,9 +609,45 @@ TypeBoundPredicate::contains_associated_types () const
= trait_item.get_trait_item_type ()
== Resolver::TraitItemReference::TraitItemType::TYPE;
if (is_associated_type)
- return true;
+ count++;
}
- return false;
+ return count;
+}
+
+TypeBoundPredicateItem
+TypeBoundPredicate::lookup_associated_type (const std::string &search)
+{
+ TypeBoundPredicateItem item = lookup_associated_item (search);
+
+ // only need to check that it is infact an associated type because other
+ // wise if it was not found it will just be an error node anyway
+ if (!item.is_error ())
+ {
+ const auto raw = item.get_raw_item ();
+ if (raw->get_trait_item_type ()
+ != Resolver::TraitItemReference::TraitItemType::TYPE)
+ return TypeBoundPredicateItem::error ();
+ }
+ return item;
+}
+
+std::vector<TypeBoundPredicateItem>
+TypeBoundPredicate::get_associated_type_items ()
+{
+ std::vector<TypeBoundPredicateItem> items;
+ auto trait_ref = get ();
+ for (const auto &trait_item : trait_ref->get_trait_items ())
+ {
+ bool is_associated_type
+ = trait_item.get_trait_item_type ()
+ == Resolver::TraitItemReference::TraitItemType::TYPE;
+ if (is_associated_type)
+ {
+ TypeBoundPredicateItem item (this, &trait_item);
+ items.push_back (std::move (item));
+ }
+ }
+ return items;
}
// trait item reference
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.h b/gcc/rust/typecheck/rust-tyty-bounds.h
new file mode 100644
index 0000000..6240480
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-bounds.h
@@ -0,0 +1,88 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_TYTY_BOUNDS_H
+#define RUST_TYTY_BOUNDS_H
+
+#include "rust-location.h"
+
+namespace Rust {
+
+namespace Resolver {
+class TraitReference;
+class TraitItemReference;
+class AssociatedImplTrait;
+} // namespace Resolver
+
+namespace TyTy {
+
+class BaseType;
+class TypeBoundPredicate;
+class TypeBoundPredicateItem
+{
+public:
+ TypeBoundPredicateItem (const TypeBoundPredicate *parent,
+ const Resolver::TraitItemReference *trait_item_ref);
+
+ static TypeBoundPredicateItem error ();
+
+ bool is_error () const;
+
+ BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
+
+ const Resolver::TraitItemReference *get_raw_item () const;
+
+ bool needs_implementation () const;
+
+ const TypeBoundPredicate *get_parent () const;
+
+ Location get_locus () const;
+
+private:
+ const TypeBoundPredicate *parent;
+ const Resolver::TraitItemReference *trait_item_ref;
+};
+
+class TypeBoundsMappings
+{
+protected:
+ TypeBoundsMappings (std::vector<TypeBoundPredicate> specified_bounds);
+
+public:
+ std::vector<TypeBoundPredicate> &get_specified_bounds ();
+
+ const std::vector<TypeBoundPredicate> &get_specified_bounds () const;
+
+ size_t num_specified_bounds () const;
+
+ std::string raw_bounds_as_string () const;
+
+ std::string bounds_as_string () const;
+
+ std::string raw_bounds_as_name () const;
+
+protected:
+ void add_bound (TypeBoundPredicate predicate);
+
+ std::vector<TypeBoundPredicate> specified_bounds;
+};
+
+} // namespace TyTy
+} // namespace Rust
+
+#endif // RUST_TYTY_BOUNDS_H
diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc
index d520b59..f0846ae 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -85,7 +85,6 @@ TypeCheckCallExpr::visit (ADTType &type)
void
TypeCheckCallExpr::visit (FnType &type)
{
- type.monomorphize ();
if (call.num_params () != type.num_params ())
{
if (type.is_varadic ())
@@ -123,7 +122,7 @@ TypeCheckCallExpr::visit (FnType &type)
return;
}
- // it might be a varadic function
+ // it might be a variadic function
if (i < type.num_params ())
{
auto fnparam = type.param_at (i);
@@ -141,11 +140,63 @@ TypeCheckCallExpr::visit (FnType &type)
argument->get_locus ());
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
{
- rust_error_at (argument->get_locus (),
- "Type Resolution failure on parameter");
return;
}
}
+ else
+ {
+ switch (argument_expr_tyty->get_kind ())
+ {
+ case TyTy::TypeKind::ERROR:
+ return;
+ case TyTy::TypeKind::INT: {
+ auto &int_ty
+ = static_cast<TyTy::IntType &> (*argument_expr_tyty);
+ if ((int_ty.get_int_kind () == TyTy::IntType::IntKind::I8)
+ || (int_ty.get_int_kind () == TyTy::IntType::IntKind::I16))
+ {
+ rust_error_at (arg_locus,
+ "expected %<c_int%> variadic argument");
+ return;
+ }
+ break;
+ }
+ case TyTy::TypeKind::UINT: {
+ auto &uint_ty
+ = static_cast<TyTy::UintType &> (*argument_expr_tyty);
+ if ((uint_ty.get_uint_kind () == TyTy::UintType::UintKind::U8)
+ || (uint_ty.get_uint_kind ()
+ == TyTy::UintType::UintKind::U16))
+ {
+ rust_error_at (arg_locus,
+ "expected %<c_uint%> variadic argument");
+ return;
+ }
+ break;
+ }
+ case TyTy::TypeKind::FLOAT: {
+ if (static_cast<TyTy::FloatType &> (*argument_expr_tyty)
+ .get_float_kind ()
+ == TyTy::FloatType::FloatKind::F32)
+ {
+ rust_error_at (arg_locus,
+ "expected %<c_double%> variadic argument");
+ return;
+ }
+ break;
+ }
+ case TyTy::TypeKind::BOOL:
+ rust_error_at (arg_locus, "expected %<c_int%> variadic argument");
+ return;
+ case TyTy::TypeKind::FNDEF:
+ rust_error_at (arg_locus,
+ "unexpected function definition type as variadic "
+ "argument - cast to function pointer");
+ return;
+ default:
+ break;
+ }
+ }
i++;
}
@@ -194,8 +245,6 @@ TypeCheckCallExpr::visit (FnPtr &type)
TyWithLocation (argument_expr_tyty, arg_locus), argument->get_locus ());
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
{
- rust_error_at (argument->get_locus (),
- "Type Resolution failure on parameter");
return;
}
@@ -302,7 +351,6 @@ TypeCheckMethodCallExpr::check (FnType &type)
TyWithLocation (argument_expr_tyty, arg_locus), arg_locus);
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
{
- rust_error_at (arg_locus, "Type Resolution failure on parameter");
return new ErrorType (type.get_ref ());
}
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
deleted file mode 100644
index cfe2692..0000000
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ /dev/null
@@ -1,1406 +0,0 @@
-// Copyright (C) 2020-2023 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_TYTY_RULES
-#define RUST_TYTY_RULES
-
-#include "rust-diagnostics.h"
-#include "rust-tyty.h"
-#include "rust-tyty-visitor.h"
-#include "rust-hir-map.h"
-#include "rust-hir-type-check.h"
-
-namespace Rust {
-namespace TyTy {
-
-/* Rules specify how to unify two Ty. For example, the result of unifying the
- two tuples (u64, A) and (B, i64) would be (u64, i64).
-
- Performing a unification requires a double dispatch. To illustrate, suppose
- we want to unify `ty1` and `ty2`. Here's what it looks like:
- 1. The caller calls `ty1.unify(ty2)`. This is the first dispatch.
- 2. `ty1` creates a rule specific to its type(e.g. TupleRules).
- 3. The rule calls `ty2.accept_vis(rule)`. This is the second dispatch.
- 4. `ty2` calls `rule.visit(*this)`, which will method-overload to the
- correct implementation at compile time.
-
- The nice thing about Rules is that they seperate unification logic from the
- representation of Ty. To support unifying a new Ty, implement its
- `accept_vis` and `unify` method to pass the unification request to Rules.
- Then, create a new `XXXRules` class and implement one `visit` method for
- every Ty it can unify with. */
-class BaseRules : public TyVisitor
-{
-public:
- virtual ~BaseRules () {}
-
- /* Unify two ty. Returns a pointer to the newly-created unified ty, or nullptr
- if the two types cannot be unified. The caller is responsible for releasing
- the memory of the returned ty.
-
- This method is meant to be used internally by Ty. If you're trying to unify
- two ty, you can simply call `unify` on ty themselves. */
- virtual BaseType *unify (BaseType *other)
- {
- if (other->get_kind () == TypeKind::PARAM)
- {
- ParamType *p = static_cast<ParamType *> (other);
- other = p->resolve ();
- }
- else if (other->get_kind () == TypeKind::PLACEHOLDER)
- {
- PlaceholderType *p = static_cast<PlaceholderType *> (other);
- if (p->can_resolve ())
- {
- other = p->resolve ();
- return get_base ()->unify (other);
- }
- }
- else if (other->get_kind () == TypeKind::PROJECTION)
- {
- ProjectionType *p = static_cast<ProjectionType *> (other);
- other = p->get ();
- return get_base ()->unify (other);
- }
-
- other->accept_vis (*this);
- if (resolved->get_kind () == TyTy::TypeKind::ERROR)
- return resolved;
-
- resolved->append_reference (get_base ()->get_ref ());
- resolved->append_reference (other->get_ref ());
- for (auto ref : get_base ()->get_combined_refs ())
- resolved->append_reference (ref);
- for (auto ref : other->get_combined_refs ())
- resolved->append_reference (ref);
-
- other->append_reference (resolved->get_ref ());
- other->append_reference (get_base ()->get_ref ());
- get_base ()->append_reference (resolved->get_ref ());
- get_base ()->append_reference (other->get_ref ());
-
- bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER;
- bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER;
- bool results_is_non_general_infer_var
- = (result_is_infer_var
- && (static_cast<InferType *> (resolved))->get_infer_kind ()
- != TyTy::InferType::GENERAL);
- if (result_resolved || results_is_non_general_infer_var)
- {
- for (auto &ref : resolved->get_combined_refs ())
- {
- TyTy::BaseType *ref_tyty = nullptr;
- bool ok = context->lookup_type (ref, &ref_tyty);
- if (!ok)
- continue;
-
- // if any of the types are inference variables lets fix them
- if (ref_tyty->get_kind () == TyTy::TypeKind::INFER)
- {
- context->insert_type (
- Analysis::NodeMapping (mappings->get_current_crate (),
- UNKNOWN_NODEID, ref,
- UNKNOWN_LOCAL_DEFID),
- resolved->clone ());
- }
- }
- }
- return resolved;
- }
-
- virtual void visit (TupleType &) override {}
-
- virtual void visit (ADTType &) override {}
-
- virtual void visit (InferType &) override {}
-
- virtual void visit (FnType &) override {}
-
- virtual void visit (FnPtr &) override {}
-
- virtual void visit (ArrayType &) override {}
-
- virtual void visit (SliceType &) override {}
-
- virtual void visit (BoolType &) override {}
-
- virtual void visit (IntType &) override {}
-
- virtual void visit (UintType &) override {}
-
- virtual void visit (USizeType &) override {}
-
- virtual void visit (ISizeType &) override {}
-
- virtual void visit (FloatType &) override {}
-
- virtual void visit (ErrorType &) override {}
-
- virtual void visit (CharType &) override {}
-
- virtual void visit (ReferenceType &) override {}
-
- virtual void visit (PointerType &) override {}
-
- virtual void visit (ParamType &) override {}
-
- virtual void visit (StrType &) override {}
-
- virtual void visit (NeverType &) override {}
-
- virtual void visit (PlaceholderType &) override {}
-
- virtual void visit (ProjectionType &) override {}
-
- virtual void visit (DynamicObjectType &) override {}
-
- virtual void visit (ClosureType &) override {}
-
-protected:
- BaseRules (BaseType *base)
- : mappings (Analysis::Mappings::get ()),
- context (Resolver::TypeCheckContext::get ()),
- resolved (new ErrorType (base->get_ref (), base->get_ref ()))
- {}
-
- Analysis::Mappings *mappings;
- Resolver::TypeCheckContext *context;
-
- /* Temporary storage for the result of a unification.
- We could return the result directly instead of storing it in the rule
- object, but that involves modifying the visitor pattern to accommodate
- the return value, which is too complex. */
- BaseType *resolved;
-
-private:
- /* Returns a pointer to the ty that created this rule. */
- virtual BaseType *get_base () = 0;
-};
-
-class InferRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- InferRules (InferType *base) : BaseRules (base), base (base) {}
-
- void visit (BoolType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (IntType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (UintType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (USizeType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (ISizeType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (FloatType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (ArrayType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (SliceType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (ADTType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (TupleType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (InferType &type) override
- {
- switch (base->get_infer_kind ())
- {
- case InferType::InferTypeKind::GENERAL:
- resolved = type.clone ();
- return;
-
- case InferType::InferTypeKind::INTEGRAL: {
- if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
- {
- resolved = type.clone ();
- return;
- }
- else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
- {
- resolved = base->clone ();
- return;
- }
- }
- break;
-
- case InferType::InferTypeKind::FLOAT: {
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- resolved = type.clone ();
- return;
- }
- else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
- {
- resolved = base->clone ();
- return;
- }
- }
- break;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (CharType &type) override
- {
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
- }
-
- void visit (ReferenceType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (PointerType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (ParamType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (DynamicObjectType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
- void visit (ClosureType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseRules::visit (type);
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- InferType *base;
-};
-
-class FnRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- FnRules (FnType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (FnType &type) override
- {
- if (base->num_params () != type.num_params ())
- {
- BaseRules::visit (type);
- return;
- }
-
- for (size_t i = 0; i < base->num_params (); i++)
- {
- auto a = base->param_at (i).second;
- auto b = type.param_at (i).second;
-
- auto unified_param = a->unify (b);
- if (unified_param == nullptr)
- {
- BaseRules::visit (type);
- return;
- }
- }
-
- auto unified_return
- = base->get_return_type ()->unify (type.get_return_type ());
- if (unified_return == nullptr)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- FnType *base;
-};
-
-class FnptrRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- FnptrRules (FnPtr *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (FnPtr &type) override
- {
- auto this_ret_type = base->get_return_type ();
- auto other_ret_type = type.get_return_type ();
- auto unified_result = this_ret_type->unify (other_ret_type);
- if (unified_result == nullptr
- || unified_result->get_kind () == TypeKind::ERROR)
- {
- BaseRules::visit (type);
- return;
- }
-
- if (base->num_params () != type.num_params ())
- {
- BaseRules::visit (type);
- return;
- }
-
- for (size_t i = 0; i < base->num_params (); i++)
- {
- auto this_param = base->param_at (i);
- auto other_param = type.param_at (i);
- auto unified_param = this_param->unify (other_param);
- if (unified_param == nullptr
- || unified_param->get_kind () == TypeKind::ERROR)
- {
- BaseRules::visit (type);
- return;
- }
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (FnType &type) override
- {
- auto this_ret_type = base->get_return_type ();
- auto other_ret_type = type.get_return_type ();
- auto unified_result = this_ret_type->unify (other_ret_type);
- if (unified_result == nullptr
- || unified_result->get_kind () == TypeKind::ERROR)
- {
- BaseRules::visit (type);
- return;
- }
-
- if (base->num_params () != type.num_params ())
- {
- BaseRules::visit (type);
- return;
- }
-
- for (size_t i = 0; i < base->num_params (); i++)
- {
- auto this_param = base->param_at (i);
- auto other_param = type.param_at (i).second;
- auto unified_param = this_param->unify (other_param);
- if (unified_param == nullptr
- || unified_param->get_kind () == TypeKind::ERROR)
- {
- BaseRules::visit (type);
- return;
- }
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- FnPtr *base;
-};
-
-class ClosureRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- ClosureRules (ClosureType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (ClosureType &type) override
- {
- if (base->get_def_id () != type.get_def_id ())
- {
- BaseRules::visit (type);
- return;
- }
-
- TyTy::BaseType *args_res
- = base->get_parameters ().unify (&type.get_parameters ());
- if (args_res == nullptr || args_res->get_kind () == TypeKind::ERROR)
- {
- BaseRules::visit (type);
- return;
- }
-
- TyTy::BaseType *res
- = base->get_result_type ().unify (&type.get_result_type ());
- if (res == nullptr || res->get_kind () == TypeKind::ERROR)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ClosureType *base;
-};
-
-class ArrayRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- ArrayRules (ArrayType *base) : BaseRules (base), base (base) {}
-
- void visit (ArrayType &type) override
- {
- // check base type
- auto base_resolved
- = base->get_element_type ()->unify (type.get_element_type ());
- if (base_resolved == nullptr)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved
- = new ArrayType (type.get_ref (), type.get_ty_ref (),
- type.get_ident ().locus, type.get_capacity_expr (),
- TyVar (base_resolved->get_ref ()));
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ArrayType *base;
-};
-
-class SliceRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- SliceRules (SliceType *base) : BaseRules (base), base (base) {}
-
- void visit (SliceType &type) override
- {
- // check base type
- auto base_resolved
- = base->get_element_type ()->unify (type.get_element_type ());
- if (base_resolved == nullptr)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = new SliceType (type.get_ref (), type.get_ty_ref (),
- type.get_ident ().locus,
- TyVar (base_resolved->get_ref ()));
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- SliceType *base;
-};
-
-class BoolRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- BoolRules (BoolType *base) : BaseRules (base), base (base) {}
-
- void visit (BoolType &type) override
- {
- resolved = new BoolType (type.get_ref (), type.get_ty_ref ());
- }
-
- void visit (InferType &type) override
- {
- switch (type.get_infer_kind ())
- {
- case InferType::InferTypeKind::GENERAL:
- resolved = base->clone ();
- break;
-
- default:
- BaseRules::visit (type);
- break;
- }
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- BoolType *base;
-};
-
-class IntRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- IntRules (IntType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- // cant assign a float inference variable
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (IntType &type) override
- {
- if (type.get_int_kind () != base->get_int_kind ())
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved
- = new IntType (type.get_ref (), type.get_ty_ref (), type.get_int_kind ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- IntType *base;
-};
-
-class UintRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- UintRules (UintType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- // cant assign a float inference variable
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (UintType &type) override
- {
- if (type.get_uint_kind () != base->get_uint_kind ())
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = new UintType (type.get_ref (), type.get_ty_ref (),
- type.get_uint_kind ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- UintType *base;
-};
-
-class FloatRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- FloatRules (FloatType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (FloatType &type) override
- {
- if (type.get_float_kind () != base->get_float_kind ())
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = new FloatType (type.get_ref (), type.get_ty_ref (),
- type.get_float_kind ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- FloatType *base;
-};
-
-class ADTRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- ADTRules (ADTType *base) : BaseRules (base), base (base) {}
-
- void visit (ADTType &type) override
- {
- if (base->get_adt_kind () != type.get_adt_kind ())
- {
- BaseRules::visit (type);
- return;
- }
-
- if (base->get_identifier ().compare (type.get_identifier ()) != 0)
- {
- BaseRules::visit (type);
- return;
- }
-
- if (base->number_of_variants () != type.number_of_variants ())
- {
- BaseRules::visit (type);
- return;
- }
-
- for (size_t i = 0; i < type.number_of_variants (); ++i)
- {
- TyTy::VariantDef *a = base->get_variants ().at (i);
- TyTy::VariantDef *b = type.get_variants ().at (i);
-
- if (a->num_fields () != b->num_fields ())
- {
- BaseRules::visit (type);
- return;
- }
-
- for (size_t j = 0; j < a->num_fields (); j++)
- {
- TyTy::StructFieldType *base_field = a->get_field_at_index (j);
- TyTy::StructFieldType *other_field = b->get_field_at_index (j);
-
- TyTy::BaseType *this_field_ty = base_field->get_field_type ();
- TyTy::BaseType *other_field_ty = other_field->get_field_type ();
-
- BaseType *unified_ty = this_field_ty->unify (other_field_ty);
- if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
- return;
- }
- }
-
- // generic args for the unit-struct case
- if (type.is_unit () && base->is_unit ())
- {
- rust_assert (type.get_num_substitutions ()
- == base->get_num_substitutions ());
-
- for (size_t i = 0; i < type.get_num_substitutions (); i++)
- {
- auto &a = base->get_substs ().at (i);
- auto &b = type.get_substs ().at (i);
-
- auto pa = a.get_param_ty ();
- auto pb = b.get_param_ty ();
-
- auto res = pa->unify (pb);
- if (res->get_kind () == TyTy::TypeKind::ERROR)
- {
- return;
- }
- }
- }
-
- resolved = type.clone ();
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ADTType *base;
-};
-
-class TupleRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- TupleRules (TupleType *base) : BaseRules (base), base (base) {}
-
- void visit (TupleType &type) override
- {
- if (base->num_fields () != type.num_fields ())
- {
- BaseRules::visit (type);
- return;
- }
-
- std::vector<TyVar> fields;
- for (size_t i = 0; i < base->num_fields (); i++)
- {
- BaseType *bo = base->get_field (i);
- BaseType *fo = type.get_field (i);
-
- BaseType *unified_ty = bo->unify (fo);
- if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
- return;
-
- fields.push_back (TyVar (unified_ty->get_ref ()));
- }
-
- resolved = new TyTy::TupleType (type.get_ref (), type.get_ty_ref (),
- type.get_ident ().locus, fields);
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- TupleType *base;
-};
-
-class USizeRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- USizeRules (USizeType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- // cant assign a float inference variable
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (USizeType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- USizeType *base;
-};
-
-class ISizeRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- ISizeRules (ISizeType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- // cant assign a float inference variable
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (ISizeType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- ISizeType *base;
-};
-
-class CharRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- CharRules (CharType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (CharType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- CharType *base;
-};
-
-class ReferenceRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- ReferenceRules (ReferenceType *base) : BaseRules (base), base (base) {}
-
- void visit (ReferenceType &type) override
- {
- auto base_type = base->get_base ();
- auto other_base_type = type.get_base ();
-
- TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
- if (base_resolved == nullptr
- || base_resolved->get_kind () == TypeKind::ERROR)
- {
- BaseRules::visit (type);
- return;
- }
-
- // rust is permissive about mutablity here you can always go from mutable to
- // immutable but not the otherway round
- bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
- if (!mutability_ok)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = new ReferenceType (base->get_ref (), base->get_ty_ref (),
- TyVar (base_resolved->get_ref ()),
- base->mutability ());
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ReferenceType *base;
-};
-
-class PointerRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- PointerRules (PointerType *base) : BaseRules (base), base (base) {}
-
- void visit (PointerType &type) override
- {
- auto base_type = base->get_base ();
- auto other_base_type = type.get_base ();
-
- TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
- if (base_resolved == nullptr
- || base_resolved->get_kind () == TypeKind::ERROR)
- {
- BaseRules::visit (type);
- return;
- }
-
- // rust is permissive about mutablity here you can always go from mutable to
- // immutable but not the otherway round
- bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
- if (!mutability_ok)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = new PointerType (base->get_ref (), base->get_ty_ref (),
- TyVar (base_resolved->get_ref ()),
- base->mutability ());
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- PointerType *base;
-};
-
-class ParamRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- ParamRules (ParamType *base) : BaseRules (base), base (base) {}
-
- // param types are a placeholder we shouldn't have cases where we unify
- // against it. eg: struct foo<T> { a: T }; When we invoke it we can do either:
- //
- // foo<i32>{ a: 123 }.
- // Then this enforces the i32 type to be referenced on the
- // field via an hirid.
- //
- // rust also allows for a = foo{a:123}; Where we can use an Inference Variable
- // to handle the typing of the struct
- BaseType *unify (BaseType *other) override final
- {
- if (!base->can_resolve ())
- return BaseRules::unify (other);
-
- auto lookup = base->resolve ();
- return lookup->unify (other);
- }
-
- void visit (ParamType &type) override
- {
- if (base->get_symbol ().compare (type.get_symbol ()) != 0)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = type.clone ();
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ParamType *base;
-};
-
-class StrRules : public BaseRules
-{
- // FIXME we will need a enum for the StrType like ByteBuf etc..
- using Rust::TyTy::BaseRules::visit;
-
-public:
- StrRules (StrType *base) : BaseRules (base), base (base) {}
-
- void visit (StrType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- StrType *base;
-};
-
-class NeverRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- NeverRules (NeverType *base) : BaseRules (base), base (base) {}
-
- void visit (NeverType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- NeverType *base;
-};
-
-class PlaceholderRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- PlaceholderRules (PlaceholderType *base) : BaseRules (base), base (base) {}
-
- BaseType *unify (BaseType *other) override final
- {
- if (!base->can_resolve ())
- return BaseRules::unify (other);
-
- BaseType *lookup = base->resolve ();
- return lookup->unify (other);
- }
-
- void visit (PlaceholderType &type) override
- {
- if (base->get_symbol ().compare (type.get_symbol ()) != 0)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = type.clone ();
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- PlaceholderType *base;
-};
-
-class DynamicRules : public BaseRules
-{
- using Rust::TyTy::BaseRules::visit;
-
-public:
- DynamicRules (DynamicObjectType *base) : BaseRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- }
-
- void visit (DynamicObjectType &type) override
- {
- if (base->num_specified_bounds () != type.num_specified_bounds ())
- {
- BaseRules::visit (type);
- return;
- }
-
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- if (!base->bounds_compatible (type, ref_locus, true))
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- DynamicObjectType *base;
-};
-
-} // namespace TyTy
-} // namespace Rust
-
-#endif // RUST_TYTY_RULES
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
new file mode 100644
index 0000000..d2f6cf6
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -0,0 +1,1048 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-tyty-subst.h"
+#include "rust-hir-full.h"
+#include "rust-tyty.h"
+#include "rust-hir-type-check.h"
+#include "rust-substitution-mapper.h"
+#include "rust-hir-type-check-type.h"
+
+namespace Rust {
+namespace TyTy {
+
+SubstitutionParamMapping::SubstitutionParamMapping (
+ const HIR::TypeParam &generic, ParamType *param)
+ : generic (generic), param (param)
+{}
+
+SubstitutionParamMapping::SubstitutionParamMapping (
+ const SubstitutionParamMapping &other)
+ : generic (other.generic), param (other.param)
+{}
+
+std::string
+SubstitutionParamMapping::as_string () const
+{
+ if (param == nullptr)
+ return "nullptr";
+
+ return param->get_name ();
+}
+
+SubstitutionParamMapping
+SubstitutionParamMapping::clone () const
+{
+ return SubstitutionParamMapping (generic,
+ static_cast<ParamType *> (param->clone ()));
+}
+
+ParamType *
+SubstitutionParamMapping::get_param_ty ()
+{
+ return param;
+}
+
+const ParamType *
+SubstitutionParamMapping::get_param_ty () const
+{
+ return param;
+}
+
+const HIR::TypeParam &
+SubstitutionParamMapping::get_generic_param () const
+{
+ return generic;
+}
+
+bool
+SubstitutionParamMapping::needs_substitution () const
+{
+ return !(get_param_ty ()->is_concrete ());
+}
+
+Location
+SubstitutionParamMapping::get_param_locus () const
+{
+ return generic.get_locus ();
+}
+
+bool
+SubstitutionParamMapping::param_has_default_ty () const
+{
+ return generic.has_type ();
+}
+
+BaseType *
+SubstitutionParamMapping::get_default_ty () const
+{
+ TyVar var (generic.get_type_mappings ().get_hirid ());
+ return var.get_tyty ();
+}
+
+bool
+SubstitutionParamMapping::need_substitution () const
+{
+ if (!param->can_resolve ())
+ return true;
+
+ auto resolved = param->resolve ();
+ return !resolved->is_concrete ();
+}
+
+bool
+SubstitutionParamMapping::fill_param_ty (
+ SubstitutionArgumentMappings &subst_mappings, Location locus)
+{
+ SubstitutionArg arg = SubstitutionArg::error ();
+ bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
+ if (!ok)
+ return true;
+
+ TyTy::BaseType &type = *arg.get_tyty ();
+ if (type.get_kind () == TyTy::TypeKind::INFER)
+ {
+ type.inherit_bounds (*param);
+ }
+
+ if (type.get_kind () == TypeKind::PARAM)
+ {
+ // delete param;
+ param = static_cast<ParamType *> (type.clone ());
+ }
+ else
+ {
+ // check the substitution is compatible with bounds
+ 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 (!param->bounds_compatible (type, locus, true))
+ return false;
+ }
+
+ // recursively pass this down to all HRTB's
+ for (auto &bound : param->get_specified_bounds ())
+ bound.handle_substitions (subst_mappings);
+
+ param->set_ty_ref (type.get_ref ());
+ subst_mappings.on_param_subst (*param, arg);
+ }
+
+ return true;
+}
+
+void
+SubstitutionParamMapping::override_context ()
+{
+ if (!param->can_resolve ())
+ return;
+
+ auto mappings = Analysis::Mappings::get ();
+ auto context = Resolver::TypeCheckContext::get ();
+
+ context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
+ UNKNOWN_NODEID,
+ param->get_ref (),
+ UNKNOWN_LOCAL_DEFID),
+ param->resolve ());
+}
+
+SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param,
+ BaseType *argument)
+ : param (param), argument (argument)
+{}
+
+SubstitutionArg::SubstitutionArg (const SubstitutionArg &other)
+ : param (other.param), argument (other.argument)
+{}
+
+SubstitutionArg &
+SubstitutionArg::operator= (const SubstitutionArg &other)
+{
+ param = other.param;
+ argument = other.argument;
+ return *this;
+}
+
+BaseType *
+SubstitutionArg::get_tyty ()
+{
+ return argument;
+}
+
+const BaseType *
+SubstitutionArg::get_tyty () const
+{
+ return argument;
+}
+
+const SubstitutionParamMapping *
+SubstitutionArg::get_param_mapping () const
+{
+ return param;
+}
+
+SubstitutionArg
+SubstitutionArg::error ()
+{
+ return SubstitutionArg (nullptr, nullptr);
+}
+
+bool
+SubstitutionArg::is_error () const
+{
+ return param == nullptr || argument == nullptr;
+}
+
+bool
+SubstitutionArg::is_conrete () const
+{
+ if (argument == nullptr)
+ return false;
+
+ if (argument->get_kind () == TyTy::TypeKind::PARAM)
+ return false;
+
+ return argument->is_concrete ();
+}
+
+std::string
+SubstitutionArg::as_string () const
+{
+ return param->as_string ()
+ + (argument != nullptr ? ":" + argument->as_string () : "");
+}
+
+// SubstitutionArgumentMappings
+
+SubstitutionArgumentMappings::SubstitutionArgumentMappings (
+ std::vector<SubstitutionArg> mappings,
+ std::map<std::string, BaseType *> binding_args, Location locus,
+ ParamSubstCb param_subst_cb, bool trait_item_flag)
+ : mappings (mappings), binding_args (binding_args), locus (locus),
+ param_subst_cb (param_subst_cb), trait_item_flag (trait_item_flag)
+{}
+
+SubstitutionArgumentMappings::SubstitutionArgumentMappings (
+ const SubstitutionArgumentMappings &other)
+ : mappings (other.mappings), binding_args (other.binding_args),
+ locus (other.locus), param_subst_cb (nullptr),
+ trait_item_flag (other.trait_item_flag)
+{}
+
+SubstitutionArgumentMappings &
+SubstitutionArgumentMappings::operator= (
+ const SubstitutionArgumentMappings &other)
+{
+ mappings = other.mappings;
+ binding_args = other.binding_args;
+ locus = other.locus;
+ param_subst_cb = nullptr;
+ trait_item_flag = other.trait_item_flag;
+
+ return *this;
+}
+
+SubstitutionArgumentMappings
+SubstitutionArgumentMappings::error ()
+{
+ return SubstitutionArgumentMappings ({}, {}, Location (), nullptr, false);
+}
+
+bool
+SubstitutionArgumentMappings::is_error () const
+{
+ return mappings.size () == 0;
+}
+
+bool
+SubstitutionArgumentMappings::get_argument_for_symbol (
+ const ParamType *param_to_find, SubstitutionArg *argument)
+{
+ for (auto &mapping : mappings)
+ {
+ const SubstitutionParamMapping *param = mapping.get_param_mapping ();
+ const ParamType *p = param->get_param_ty ();
+
+ if (p->get_symbol ().compare (param_to_find->get_symbol ()) == 0)
+ {
+ *argument = mapping;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+SubstitutionArgumentMappings::get_argument_at (size_t index,
+ SubstitutionArg *argument)
+{
+ if (index > mappings.size ())
+ return false;
+
+ *argument = mappings.at (index);
+ return true;
+}
+
+bool
+SubstitutionArgumentMappings::is_concrete () const
+{
+ for (auto &mapping : mappings)
+ {
+ if (!mapping.is_conrete ())
+ return false;
+ }
+ return true;
+}
+
+Location
+SubstitutionArgumentMappings::get_locus () const
+{
+ return locus;
+}
+
+size_t
+SubstitutionArgumentMappings::size () const
+{
+ return mappings.size ();
+}
+
+bool
+SubstitutionArgumentMappings::is_empty () const
+{
+ return size () == 0;
+}
+
+std::vector<SubstitutionArg> &
+SubstitutionArgumentMappings::get_mappings ()
+{
+ return mappings;
+}
+
+const std::vector<SubstitutionArg> &
+SubstitutionArgumentMappings::get_mappings () const
+{
+ return mappings;
+}
+
+std::map<std::string, BaseType *> &
+SubstitutionArgumentMappings::get_binding_args ()
+{
+ return binding_args;
+}
+
+const std::map<std::string, BaseType *> &
+SubstitutionArgumentMappings::get_binding_args () const
+{
+ return binding_args;
+}
+
+std::string
+SubstitutionArgumentMappings::as_string () const
+{
+ std::string buffer;
+ for (auto &mapping : mappings)
+ {
+ buffer += mapping.as_string () + ", ";
+ }
+ return "<" + buffer + ">";
+}
+
+void
+SubstitutionArgumentMappings::on_param_subst (const ParamType &p,
+ const SubstitutionArg &a) const
+{
+ if (param_subst_cb == nullptr)
+ return;
+
+ param_subst_cb (p, a);
+}
+
+ParamSubstCb
+SubstitutionArgumentMappings::get_subst_cb () const
+{
+ return param_subst_cb;
+}
+
+bool
+SubstitutionArgumentMappings::trait_item_mode () const
+{
+ return trait_item_flag;
+}
+
+// SubstitutionRef
+
+SubstitutionRef::SubstitutionRef (
+ std::vector<SubstitutionParamMapping> substitutions,
+ SubstitutionArgumentMappings arguments)
+ : substitutions (substitutions), used_arguments (arguments)
+{}
+
+bool
+SubstitutionRef::has_substitutions () const
+{
+ return substitutions.size () > 0;
+}
+
+std::string
+SubstitutionRef::subst_as_string () const
+{
+ std::string buffer;
+ for (size_t i = 0; i < substitutions.size (); i++)
+ {
+ const SubstitutionParamMapping &sub = substitutions.at (i);
+ buffer += sub.as_string ();
+
+ if ((i + 1) < substitutions.size ())
+ buffer += ", ";
+ }
+
+ return buffer.empty () ? "" : "<" + buffer + ">";
+}
+
+bool
+SubstitutionRef::supports_associated_bindings () const
+{
+ return get_num_associated_bindings () > 0;
+}
+
+size_t
+SubstitutionRef::get_num_associated_bindings () const
+{
+ return 0;
+}
+
+TypeBoundPredicateItem
+SubstitutionRef::lookup_associated_type (const std::string &search)
+{
+ return TypeBoundPredicateItem::error ();
+}
+
+size_t
+SubstitutionRef::get_num_substitutions () const
+{
+ return substitutions.size ();
+}
+
+std::vector<SubstitutionParamMapping> &
+SubstitutionRef::get_substs ()
+{
+ return substitutions;
+}
+
+const std::vector<SubstitutionParamMapping> &
+SubstitutionRef::get_substs () const
+{
+ return substitutions;
+}
+
+std::vector<SubstitutionParamMapping>
+SubstitutionRef::clone_substs () const
+{
+ std::vector<SubstitutionParamMapping> clone;
+
+ for (auto &sub : substitutions)
+ clone.push_back (sub.clone ());
+
+ return clone;
+}
+
+void
+SubstitutionRef::override_context ()
+{
+ for (auto &sub : substitutions)
+ {
+ sub.override_context ();
+ }
+}
+
+bool
+SubstitutionRef::needs_substitution () const
+{
+ for (auto &sub : substitutions)
+ {
+ if (sub.need_substitution ())
+ return true;
+ }
+ return false;
+}
+
+bool
+SubstitutionRef::was_substituted () const
+{
+ return !needs_substitution ();
+}
+
+SubstitutionArgumentMappings &
+SubstitutionRef::get_substitution_arguments ()
+{
+ return used_arguments;
+}
+
+const SubstitutionArgumentMappings &
+SubstitutionRef::get_substitution_arguments () const
+{
+ return used_arguments;
+}
+
+size_t
+SubstitutionRef::num_required_substitutions () const
+{
+ size_t n = 0;
+ for (auto &p : substitutions)
+ {
+ if (p.needs_substitution ())
+ n++;
+ }
+ return n;
+}
+
+size_t
+SubstitutionRef::min_required_substitutions () const
+{
+ size_t n = 0;
+ for (auto &p : substitutions)
+ {
+ if (p.needs_substitution () && !p.param_has_default_ty ())
+ n++;
+ }
+ return n;
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::get_used_arguments () const
+{
+ return used_arguments;
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
+{
+ std::map<std::string, BaseType *> binding_arguments;
+ if (args.get_binding_args ().size () > 0)
+ {
+ if (supports_associated_bindings ())
+ {
+ if (args.get_binding_args ().size () > get_num_associated_bindings ())
+ {
+ RichLocation r (args.get_locus ());
+
+ rust_error_at (r,
+ "generic item takes at most %lu type binding "
+ "arguments but %lu were supplied",
+ (unsigned long) get_num_associated_bindings (),
+ (unsigned long) args.get_binding_args ().size ());
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ for (auto &binding : args.get_binding_args ())
+ {
+ BaseType *resolved
+ = Resolver::TypeCheckType::Resolve (binding.get_type ().get ());
+ if (resolved == nullptr
+ || resolved->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (binding.get_locus (),
+ "failed to resolve type arguments");
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ // resolve to relevant binding
+ auto binding_item
+ = lookup_associated_type (binding.get_identifier ());
+ if (binding_item.is_error ())
+ {
+ rust_error_at (binding.get_locus (),
+ "unknown associated type binding: %s",
+ binding.get_identifier ().c_str ());
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ binding_arguments[binding.get_identifier ()] = resolved;
+ }
+ }
+ else
+ {
+ RichLocation r (args.get_locus ());
+ for (auto &binding : args.get_binding_args ())
+ r.add_range (binding.get_locus ());
+
+ rust_error_at (r, "associated type bindings are not allowed here");
+ return SubstitutionArgumentMappings::error ();
+ }
+ }
+
+ // for inherited arguments
+ size_t offs = used_arguments.size ();
+ if (args.get_type_args ().size () + offs > substitutions.size ())
+ {
+ RichLocation r (args.get_locus ());
+ r.add_range (substitutions.front ().get_param_locus ());
+
+ rust_error_at (
+ r,
+ "generic item takes at most %lu type arguments but %lu were supplied",
+ (unsigned long) substitutions.size (),
+ (unsigned long) args.get_type_args ().size ());
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ if (args.get_type_args ().size () + offs < min_required_substitutions ())
+ {
+ RichLocation r (args.get_locus ());
+ r.add_range (substitutions.front ().get_param_locus ());
+
+ rust_error_at (
+ r,
+ "generic item takes at least %lu type arguments but %lu were supplied",
+ (unsigned long) (min_required_substitutions () - offs),
+ (unsigned long) args.get_type_args ().size ());
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
+ for (auto &arg : args.get_type_args ())
+ {
+ BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ());
+ if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (args.get_locus (), "failed to resolve type arguments");
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ SubstitutionArg subst_arg (&substitutions.at (offs), resolved);
+ offs++;
+ mappings.push_back (std::move (subst_arg));
+ }
+
+ // we must need to fill out defaults
+ size_t left_over
+ = num_required_substitutions () - min_required_substitutions ();
+ if (left_over > 0)
+ {
+ for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
+ {
+ SubstitutionParamMapping &param = substitutions.at (offs);
+ rust_assert (param.param_has_default_ty ());
+
+ BaseType *resolved = param.get_default_ty ();
+ if (resolved->get_kind () == TypeKind::ERROR)
+ return SubstitutionArgumentMappings::error ();
+
+ // this resolved default might already contain default parameters
+ if (resolved->contains_type_parameters ())
+ {
+ SubstitutionArgumentMappings intermediate (mappings,
+ binding_arguments,
+ args.get_locus ());
+ resolved = Resolver::SubstMapperInternal::Resolve (resolved,
+ intermediate);
+
+ if (resolved->get_kind () == TypeKind::ERROR)
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ SubstitutionArg subst_arg (&param, resolved);
+ mappings.push_back (std::move (subst_arg));
+ }
+ }
+
+ return SubstitutionArgumentMappings (mappings, binding_arguments,
+ args.get_locus ());
+}
+
+BaseType *
+SubstitutionRef::infer_substitions (Location locus)
+{
+ std::vector<SubstitutionArg> args;
+ std::map<std::string, BaseType *> argument_mappings;
+ for (auto &p : get_substs ())
+ {
+ if (p.needs_substitution ())
+ {
+ const std::string &symbol = p.get_param_ty ()->get_symbol ();
+ auto it = argument_mappings.find (symbol);
+ bool have_mapping = it != argument_mappings.end ();
+
+ if (have_mapping)
+ {
+ args.push_back (SubstitutionArg (&p, it->second));
+ }
+ else
+ {
+ TyVar infer_var = TyVar::get_implicit_infer_var (locus);
+ args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
+ argument_mappings[symbol] = infer_var.get_tyty ();
+ }
+ }
+ else
+ {
+ args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
+ }
+ }
+
+ // FIXME do we need to add inference variables to all the possible bindings?
+ // it might just lead to inference variable hell not 100% sure if rustc does
+ // this i think the language might needs this to be explicitly set
+
+ SubstitutionArgumentMappings infer_arguments (std::move (args),
+ {} /* binding_arguments */,
+ locus);
+ return handle_substitions (infer_arguments);
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::adjust_mappings_for_this (
+ SubstitutionArgumentMappings &mappings)
+{
+ std::vector<SubstitutionArg> resolved_mappings;
+ for (size_t i = 0; i < substitutions.size (); i++)
+ {
+ auto &subst = substitutions.at (i);
+
+ SubstitutionArg arg = SubstitutionArg::error ();
+ if (mappings.size () == substitutions.size ())
+ {
+ mappings.get_argument_at (i, &arg);
+ }
+ else
+ {
+ if (subst.needs_substitution ())
+ {
+ // get from passed in mappings
+ mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
+ }
+ else
+ {
+ // we should already have this somewhere
+ used_arguments.get_argument_for_symbol (subst.get_param_ty (),
+ &arg);
+ }
+ }
+
+ bool ok = !arg.is_error ();
+ if (ok)
+ {
+ SubstitutionArg adjusted (&subst, arg.get_tyty ());
+ resolved_mappings.push_back (std::move (adjusted));
+ }
+ }
+
+ if (resolved_mappings.empty ())
+ return SubstitutionArgumentMappings::error ();
+
+ return SubstitutionArgumentMappings (resolved_mappings,
+ mappings.get_binding_args (),
+ mappings.get_locus (),
+ mappings.get_subst_cb (),
+ mappings.trait_item_mode ());
+}
+
+bool
+SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
+{
+ std::vector<SubstitutionArg> resolved_mappings;
+ for (size_t i = 0; i < substitutions.size (); i++)
+ {
+ auto &subst = substitutions.at (i);
+
+ SubstitutionArg arg = SubstitutionArg::error ();
+ if (mappings.size () == substitutions.size ())
+ {
+ mappings.get_argument_at (i, &arg);
+ }
+ else
+ {
+ if (subst.needs_substitution ())
+ {
+ // get from passed in mappings
+ mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
+ }
+ else
+ {
+ // we should already have this somewhere
+ used_arguments.get_argument_for_symbol (subst.get_param_ty (),
+ &arg);
+ }
+ }
+
+ bool ok = !arg.is_error ();
+ if (ok)
+ {
+ SubstitutionArg adjusted (&subst, arg.get_tyty ());
+ resolved_mappings.push_back (std::move (adjusted));
+ }
+ }
+
+ return !resolved_mappings.empty ();
+}
+
+// this function assumes that the mappings being passed are for the same type as
+// this new substitution reference so ordering matters here
+SubstitutionArgumentMappings
+SubstitutionRef::solve_mappings_from_receiver_for_self (
+ SubstitutionArgumentMappings &mappings) const
+{
+ std::vector<SubstitutionArg> resolved_mappings;
+
+ rust_assert (mappings.size () == get_num_substitutions ());
+ for (size_t i = 0; i < get_num_substitutions (); i++)
+ {
+ const SubstitutionParamMapping &param_mapping = substitutions.at (i);
+ SubstitutionArg &arg = mappings.get_mappings ().at (i);
+
+ if (param_mapping.needs_substitution ())
+ {
+ SubstitutionArg adjusted (&param_mapping, arg.get_tyty ());
+ resolved_mappings.push_back (std::move (adjusted));
+ }
+ }
+
+ return SubstitutionArgumentMappings (resolved_mappings,
+ mappings.get_binding_args (),
+ mappings.get_locus ());
+}
+
+SubstitutionArgumentMappings
+SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref,
+ SubstitutionRef &to)
+{
+ rust_assert (!ref.needs_substitution ());
+ rust_assert (needs_substitution ());
+ rust_assert (get_num_substitutions () == ref.get_num_substitutions ());
+
+ Location locus = used_arguments.get_locus ();
+ std::vector<SubstitutionArg> resolved_mappings;
+
+ std::map<HirId, std::pair<ParamType *, BaseType *>> substs;
+ for (size_t i = 0; i < get_num_substitutions (); i++)
+ {
+ SubstitutionParamMapping &a = substitutions.at (i);
+ SubstitutionParamMapping &b = ref.substitutions.at (i);
+
+ if (a.need_substitution ())
+ {
+ const BaseType *root = a.get_param_ty ()->resolve ()->get_root ();
+ rust_assert (root->get_kind () == TyTy::TypeKind::PARAM);
+ const ParamType *p = static_cast<const TyTy::ParamType *> (root);
+
+ substs[p->get_ty_ref ()] = {static_cast<ParamType *> (p->clone ()),
+ b.get_param_ty ()->resolve ()};
+ }
+ }
+
+ for (auto it = substs.begin (); it != substs.end (); it++)
+ {
+ HirId param_id = it->first;
+ BaseType *arg = it->second.second;
+
+ const SubstitutionParamMapping *associate_param = nullptr;
+ for (SubstitutionParamMapping &p : to.substitutions)
+ {
+ if (p.get_param_ty ()->get_ty_ref () == param_id)
+ {
+ associate_param = &p;
+ break;
+ }
+ }
+
+ rust_assert (associate_param != nullptr);
+ SubstitutionArg argument (associate_param, arg);
+ resolved_mappings.push_back (std::move (argument));
+ }
+
+ return SubstitutionArgumentMappings (resolved_mappings, {}, locus);
+}
+
+Resolver::AssociatedImplTrait *
+SubstitutionRef::lookup_associated_impl (const SubstitutionParamMapping &subst,
+ const TypeBoundPredicate &bound,
+ const TyTy::BaseType *binding,
+ bool *error_flag) const
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ const Resolver::TraitReference *specified_bound_ref = bound.get ();
+
+ // setup any associated type mappings for the specified bonds and this
+ // type
+ auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
+ std::vector<Resolver::AssociatedImplTrait *> associated_impl_traits;
+ for (auto &probed_bound : candidates)
+ {
+ const Resolver::TraitReference *bound_trait_ref = probed_bound.first;
+ const HIR::ImplBlock *associated_impl = probed_bound.second;
+
+ HirId impl_block_id = associated_impl->get_mappings ().get_hirid ();
+ Resolver::AssociatedImplTrait *associated = nullptr;
+ bool found_impl_trait
+ = context->lookup_associated_trait_impl (impl_block_id, &associated);
+ if (found_impl_trait)
+ {
+ bool found_trait = specified_bound_ref->is_equal (*bound_trait_ref);
+ bool found_self = associated->get_self ()->can_eq (binding, false);
+ if (found_trait && found_self)
+ {
+ associated_impl_traits.push_back (associated);
+ }
+ }
+ }
+
+ if (associated_impl_traits.empty ())
+ return nullptr;
+
+ // This code is important when you look at slices for example when
+ // you have a slice such as:
+ //
+ // let slice = &array[1..3]
+ //
+ // the higher ranked bounds will end up having an Index trait
+ // implementation for Range<usize> so we need this code to resolve
+ // that we have an integer inference variable that needs to become
+ // a usize
+ //
+ // The other complicated issue is that we might have an intrinsic
+ // which requires the :Clone or Copy bound but the libcore adds
+ // implementations for all the integral types so when there are
+ // multiple candidates we need to resolve to the default
+ // implementation for that type otherwise its an error for
+ // ambiguous type bounds
+
+ // if we have a non-general inference variable we need to be
+ // careful about the selection here
+ bool is_infer_var = binding->get_kind () == TyTy::TypeKind::INFER;
+ bool is_integer_infervar
+ = is_infer_var
+ && static_cast<const TyTy::InferType *> (binding)->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL;
+ bool is_float_infervar
+ = is_infer_var
+ && static_cast<const TyTy::InferType *> (binding)->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::FLOAT;
+
+ Resolver::AssociatedImplTrait *associate_impl_trait = nullptr;
+ if (associated_impl_traits.size () == 1)
+ {
+ // just go for it
+ associate_impl_trait = associated_impl_traits.at (0);
+ }
+ else if (is_integer_infervar)
+ {
+ TyTy::BaseType *type = nullptr;
+ bool ok = context->lookup_builtin ("i32", &type);
+ rust_assert (ok);
+
+ for (auto &impl : associated_impl_traits)
+ {
+ bool found = impl->get_self ()->is_equal (*type);
+ if (found)
+ {
+ associate_impl_trait = impl;
+ break;
+ }
+ }
+ }
+ else if (is_float_infervar)
+ {
+ TyTy::BaseType *type = nullptr;
+ bool ok = context->lookup_builtin ("f64", &type);
+ rust_assert (ok);
+
+ for (auto &impl : associated_impl_traits)
+ {
+ bool found = impl->get_self ()->is_equal (*type);
+ if (found)
+ {
+ associate_impl_trait = impl;
+ break;
+ }
+ }
+ }
+
+ if (associate_impl_trait == nullptr)
+ {
+ // go for the first one? or error out?
+ auto &mappings = *Analysis::Mappings::get ();
+ const auto &type_param = subst.get_generic_param ();
+ const auto *trait_ref = bound.get ();
+
+ RichLocation r (type_param.get_locus ());
+ r.add_range (bound.get_locus ());
+ r.add_range (mappings.lookup_location (binding->get_ref ()));
+
+ rust_error_at (r, "ambiguous type bound for trait %s and type %s",
+ trait_ref->get_name ().c_str (),
+ binding->get_name ().c_str ());
+
+ *error_flag = true;
+ return nullptr;
+ }
+
+ return associate_impl_trait;
+}
+
+void
+SubstitutionRef::prepare_higher_ranked_bounds ()
+{
+ for (const auto &subst : get_substs ())
+ {
+ const TyTy::ParamType *pty = subst.get_param_ty ();
+ for (const auto &bound : pty->get_specified_bounds ())
+ {
+ const auto ref = bound.get ();
+ ref->clear_associated_type_projections ();
+ }
+ }
+}
+
+bool
+SubstitutionRef::monomorphize ()
+{
+ for (const auto &subst : get_substs ())
+ {
+ const TyTy::ParamType *pty = subst.get_param_ty ();
+
+ if (!pty->can_resolve ())
+ continue;
+
+ const TyTy::BaseType *binding = pty->resolve ();
+ if (binding->get_kind () == TyTy::TypeKind::PARAM)
+ continue;
+
+ for (const auto &bound : pty->get_specified_bounds ())
+ {
+ bool error_flag = false;
+ auto associated
+ = lookup_associated_impl (subst, bound, binding, &error_flag);
+ if (associated != nullptr)
+ {
+ associated->setup_associated_types (binding, bound);
+ }
+
+ if (error_flag)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace TyTy
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h
new file mode 100644
index 0000000..365fdb6
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -0,0 +1,327 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_TYTY_SUBST_H
+#define RUST_TYTY_SUBST_H
+
+#include "rust-system.h"
+#include "rust-location.h"
+#include "rust-hir-full-decls.h"
+#include "rust-tyty-bounds.h"
+
+namespace Rust {
+namespace TyTy {
+
+class BaseType;
+class ParamType;
+class SubstitutionArgumentMappings;
+class SubstitutionParamMapping
+{
+public:
+ SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param);
+
+ SubstitutionParamMapping (const SubstitutionParamMapping &other);
+
+ std::string as_string () const;
+
+ bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
+ Location locus);
+
+ SubstitutionParamMapping clone () const;
+
+ ParamType *get_param_ty ();
+
+ const ParamType *get_param_ty () const;
+
+ 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
+ void override_context ();
+
+ bool needs_substitution () const;
+
+ Location get_param_locus () const;
+
+ bool param_has_default_ty () const;
+
+ BaseType *get_default_ty () const;
+
+ bool need_substitution () const;
+
+private:
+ const HIR::TypeParam &generic;
+ ParamType *param;
+};
+
+class SubstitutionArg
+{
+public:
+ SubstitutionArg (const SubstitutionParamMapping *param, BaseType *argument);
+
+ // FIXME
+ // the copy constructors need removed - they are unsafe see
+ // TypeBoundPredicate
+ SubstitutionArg (const SubstitutionArg &other);
+
+ SubstitutionArg &operator= (const SubstitutionArg &other);
+
+ BaseType *get_tyty ();
+
+ const BaseType *get_tyty () const;
+
+ const SubstitutionParamMapping *get_param_mapping () const;
+
+ static SubstitutionArg error ();
+
+ bool is_error () const;
+
+ bool is_conrete () const;
+
+ std::string as_string () const;
+
+private:
+ const SubstitutionParamMapping *param;
+ BaseType *argument;
+};
+
+typedef std::function<void (const ParamType &, const SubstitutionArg &)>
+ ParamSubstCb;
+class SubstitutionArgumentMappings
+{
+public:
+ SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
+ std::map<std::string, BaseType *> binding_args,
+ Location locus,
+ ParamSubstCb param_subst_cb = nullptr,
+ bool trait_item_flag = false);
+
+ SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other);
+ SubstitutionArgumentMappings &
+ operator= (const SubstitutionArgumentMappings &other);
+
+ SubstitutionArgumentMappings (SubstitutionArgumentMappings &&other) = default;
+ SubstitutionArgumentMappings &operator= (SubstitutionArgumentMappings &&other)
+ = default;
+
+ static SubstitutionArgumentMappings error ();
+
+ bool is_error () const;
+
+ bool get_argument_for_symbol (const ParamType *param_to_find,
+ SubstitutionArg *argument);
+
+ bool get_argument_at (size_t index, SubstitutionArg *argument);
+
+ // is_concrete means if the used args is non error, ie: non empty this will
+ // verify if actual real types have been put in place of are they still
+ // ParamTy
+ bool is_concrete () const;
+
+ Location get_locus () const;
+
+ size_t size () const;
+
+ bool is_empty () const;
+
+ std::vector<SubstitutionArg> &get_mappings ();
+
+ const std::vector<SubstitutionArg> &get_mappings () const;
+
+ std::map<std::string, BaseType *> &get_binding_args ();
+
+ const std::map<std::string, BaseType *> &get_binding_args () const;
+
+ std::string as_string () const;
+
+ void on_param_subst (const ParamType &p, const SubstitutionArg &a) const;
+
+ ParamSubstCb get_subst_cb () const;
+
+ bool trait_item_mode () const;
+
+private:
+ std::vector<SubstitutionArg> mappings;
+ std::map<std::string, BaseType *> binding_args;
+ Location locus;
+ ParamSubstCb param_subst_cb;
+ bool trait_item_flag;
+};
+
+class SubstitutionRef
+{
+public:
+ SubstitutionRef (std::vector<SubstitutionParamMapping> substitutions,
+ SubstitutionArgumentMappings arguments);
+
+ bool has_substitutions () const;
+
+ std::string subst_as_string () const;
+
+ bool supports_associated_bindings () const;
+
+ // this is overridden in TypeBoundPredicate
+ // which support bindings we don't add them directly to the SubstitutionRef
+ // base class because this class represents the fn<X: Foo, Y: Bar>. The only
+ // construct which supports associated types
+ virtual size_t get_num_associated_bindings () const;
+
+ // this is overridden in TypeBoundPredicate
+ virtual TypeBoundPredicateItem
+ lookup_associated_type (const std::string &search);
+
+ size_t get_num_substitutions () const;
+
+ std::vector<SubstitutionParamMapping> &get_substs ();
+
+ const std::vector<SubstitutionParamMapping> &get_substs () const;
+
+ std::vector<SubstitutionParamMapping> clone_substs () const;
+
+ void override_context ();
+
+ bool needs_substitution () const;
+
+ bool was_substituted () const;
+
+ SubstitutionArgumentMappings &get_substitution_arguments ();
+ const SubstitutionArgumentMappings &get_substitution_arguments () const;
+
+ // this is the count of type params that are not substituted fuly
+ size_t num_required_substitutions () const;
+
+ // this is the count of type params that need substituted taking into account
+ // possible defaults
+ size_t min_required_substitutions () const;
+
+ // We are trying to subst <i32, f32> into Struct Foo<X,Y> {}
+ // in the case of Foo<i32,f32>{...}
+ //
+ // the substitions we have here define X,Y but the arguments have no bindings
+ // so its a matter of ordering
+ SubstitutionArgumentMappings
+ get_mappings_from_generic_args (HIR::GenericArgs &args);
+
+ // Recursive substitutions
+ // Foo <A,B> { a:A, b: B}; Bar <X,Y,Z>{a:X, b: Foo<Y,Z>}
+ //
+ // we have bindings for X Y Z and need to propagate the binding Y,Z into Foo
+ // Which binds to A,B
+ SubstitutionArgumentMappings
+ adjust_mappings_for_this (SubstitutionArgumentMappings &mappings);
+
+ // Are the mappings here actually bound to this type. For example imagine the
+ // case:
+ //
+ // struct Foo<T>(T);
+ // impl<T> Foo<T> {
+ // fn test(self) { ... }
+ // }
+ //
+ // In this case we have a generic ADT of Foo and an impl block of a generic T
+ // on Foo for the Self type. When we it comes to path resolution we can have:
+ //
+ // Foo::<i32>::test()
+ //
+ // This means the first segment of Foo::<i32> returns the ADT Foo<i32> not the
+ // Self ADT bound to the T from the impl block. This means when it comes to
+ // the next segment of test which resolves to the function we need to check
+ // wether the arguments in the struct definition of foo can be bound here
+ // before substituting the previous segments type here. This functions acts as
+ // a guard for the solve_mappings_from_receiver_for_self to handle the case
+ // where arguments are not bound. This is important for this next case:
+ //
+ // struct Baz<A, B>(A, B);
+ // impl Baz<i32, f32> {
+ // fn test<X>(a: X) -> X {
+ // a
+ // }
+ // }
+ //
+ // In this case Baz has been already substituted for the impl's Self to become
+ // ADT<i32, f32> so that the function test only has 1 generic argument of X.
+ // The path for this will be:
+ //
+ // Baz::test::<_>(123)
+ //
+ // So the first segment here will be Baz<_, _> to try and infer the arguments
+ // which will be taken from the impl's Self type in this case since it is
+ // already substituted and like the previous case the check to see if we need
+ // to inherit the previous segments generic arguments takes place but the
+ // generic arguments are not bound to this type as they have already been
+ // substituted.
+ //
+ // Its important to remember from the first example the FnType actually looks
+ // like:
+ //
+ // fn <T>test(self :Foo<T>(T))
+ //
+ // As the generic parameters are "bound" to each of the items in the impl
+ // block. So this check is about wether the arguments we have here can
+ // actually be bound to this type.
+ bool are_mappings_bound (SubstitutionArgumentMappings &mappings);
+
+ // struct Foo<A, B>(A, B);
+ //
+ // impl<T> Foo<T, f32>;
+ // -> fn test<X>(self, a: X) -> X
+ //
+ // We might invoke this via:
+ //
+ // a = Foo(123, 456f32);
+ // b = a.test::<bool>(false);
+ //
+ // we need to figure out relevant generic arguemts for self to apply to the
+ // fntype
+ SubstitutionArgumentMappings solve_mappings_from_receiver_for_self (
+ SubstitutionArgumentMappings &mappings) const;
+
+ // TODO comment
+ SubstitutionArgumentMappings
+ solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to);
+
+ // TODO comment
+ BaseType *infer_substitions (Location locus);
+
+ // this clears any possible projections from higher ranked trait bounds which
+ // could be hanging around from a previous resolution
+ void prepare_higher_ranked_bounds ();
+
+ // FIXME
+ // this is bad name for this, i think it should be something like
+ // compute-higher-ranked-bounds
+ bool monomorphize ();
+
+ // TODO comment
+ virtual BaseType *handle_substitions (SubstitutionArgumentMappings &mappings)
+ = 0;
+
+ SubstitutionArgumentMappings get_used_arguments () const;
+
+protected:
+ Resolver::AssociatedImplTrait *lookup_associated_impl (
+ const SubstitutionParamMapping &subst, const TypeBoundPredicate &bound,
+ const TyTy::BaseType *binding, bool *error_flag) const;
+
+ std::vector<SubstitutionParamMapping> substitutions;
+ SubstitutionArgumentMappings used_arguments;
+};
+
+} // namespace TyTy
+} // namespace Rust
+#endif // RUST_TYTY_SUBST_H
diff --git a/gcc/rust/typecheck/rust-tyty-util.cc b/gcc/rust/typecheck/rust-tyty-util.cc
new file mode 100644
index 0000000..32b94f0
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-util.cc
@@ -0,0 +1,116 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-type-check.h"
+#include "rust-tyty.h"
+
+namespace Rust {
+namespace TyTy {
+
+TyVar::TyVar (HirId ref) : ref (ref)
+{
+ // ensure this reference is defined within the context
+ auto context = Resolver::TypeCheckContext::get ();
+ BaseType *lookup = nullptr;
+ bool ok = context->lookup_type (ref, &lookup);
+ rust_assert (ok);
+}
+
+BaseType *
+TyVar::get_tyty () const
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ BaseType *lookup = nullptr;
+ bool ok = context->lookup_type (ref, &lookup);
+ rust_assert (ok);
+ return lookup;
+}
+
+TyVar
+TyVar::get_implicit_infer_var (Location locus)
+{
+ auto mappings = Analysis::Mappings::get ();
+ auto context = Resolver::TypeCheckContext::get ();
+
+ InferType *infer = new InferType (mappings->get_next_hir_id (),
+ InferType::InferTypeKind::GENERAL, locus);
+ context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
+ UNKNOWN_NODEID,
+ infer->get_ref (),
+ UNKNOWN_LOCAL_DEFID),
+ infer);
+ mappings->insert_location (infer->get_ref (), locus);
+
+ return TyVar (infer->get_ref ());
+}
+
+TyVar
+TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst)
+{
+ if (orig->get_kind () != TyTy::TypeKind::PARAM)
+ return TyVar (subst->get_ty_ref ());
+ else if (subst->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ TyTy::ParamType *p = static_cast<TyTy::ParamType *> (subst);
+ if (p->resolve ()->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ return TyVar (subst->get_ty_ref ());
+ }
+ }
+
+ return TyVar (subst->get_ref ());
+}
+
+TyVar
+TyVar::clone () const
+{
+ TyTy::BaseType *c = get_tyty ()->clone ();
+ return TyVar (c->get_ref ());
+}
+
+TyVar
+TyVar::monomorphized_clone () const
+{
+ auto mappings = Analysis::Mappings::get ();
+ auto context = Resolver::TypeCheckContext::get ();
+
+ // this needs a new hirid
+ TyTy::BaseType *c = get_tyty ()->monomorphized_clone ();
+ c->set_ref (mappings->get_next_hir_id ());
+
+ // insert it
+ context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
+ UNKNOWN_NODEID, c->get_ref (),
+ UNKNOWN_LOCAL_DEFID),
+ c);
+
+ return TyVar (c->get_ref ());
+}
+
+TyWithLocation::TyWithLocation (BaseType *ty, Location locus)
+ : ty (ty), locus (locus)
+{}
+
+TyWithLocation::TyWithLocation (BaseType *ty) : ty (ty)
+{
+ auto mappings = Analysis::Mappings::get ();
+ locus = mappings->lookup_location (ty->get_ref ());
+}
+
+} // namespace TyTy
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-util.h b/gcc/rust/typecheck/rust-tyty-util.h
new file mode 100644
index 0000000..6b28379
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-util.h
@@ -0,0 +1,69 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_TYTY_UTIL_H
+#define RUST_TYTY_UTIL_H
+
+#include "rust-hir-map.h"
+
+namespace Rust {
+namespace TyTy {
+
+class BaseType;
+
+// this is a placeholder for types that can change like inference variables
+class TyVar
+{
+public:
+ explicit TyVar (HirId ref);
+
+ HirId get_ref () const { return ref; }
+
+ BaseType *get_tyty () const;
+
+ TyVar clone () const;
+
+ TyVar monomorphized_clone () const;
+
+ static TyVar get_implicit_infer_var (Location locus);
+
+ static TyVar subst_covariant_var (TyTy::BaseType *orig,
+ TyTy::BaseType *subst);
+
+private:
+ HirId ref;
+};
+
+class TyWithLocation
+{
+public:
+ explicit TyWithLocation (BaseType *ty, Location locus);
+ explicit TyWithLocation (BaseType *ty);
+
+ BaseType *get_ty () const { return ty; }
+ Location get_locus () const { return locus; }
+
+private:
+ BaseType *ty;
+ Location locus;
+};
+
+} // namespace TyTy
+} // namespace Rust
+
+#endif // RUST_TYTY_UTIL_H
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 71f0de1..d0d36ac 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -17,17 +17,22 @@
// <http://www.gnu.org/licenses/>.
#include "rust-tyty.h"
-#include "rust-tyty-visitor.h"
-#include "rust-tyty-call.h"
+
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-type.h"
-#include "rust-tyty-rules.h"
-#include "rust-tyty-cmp.h"
+#include "rust-tyty-visitor.h"
+#include "rust-tyty-call.h"
#include "rust-hir-map.h"
+#include "rust-location.h"
+#include "rust-linemap.h"
+
#include "rust-substitution-mapper.h"
-#include "rust-hir-trait-ref.h"
+#include "rust-hir-trait-reference.h"
#include "rust-hir-type-bounds.h"
#include "rust-hir-trait-resolve.h"
+#include "rust-tyty-cmp.h"
+#include "rust-type-util.h"
+
#include "options.h"
namespace Rust {
@@ -146,6 +151,123 @@ is_primitive_type_kind (TypeKind kind)
}
}
+// BASE TYPE
+
+BaseType::BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
+ std::set<HirId> refs)
+ : TypeBoundsMappings ({}), kind (kind), ref (ref), ty_ref (ty_ref),
+ combined (refs), ident (ident), mappings (Analysis::Mappings::get ())
+{}
+
+BaseType::BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs)
+ : TypeBoundsMappings (specified_bounds), kind (kind), ref (ref),
+ ty_ref (ty_ref), combined (refs), ident (ident),
+ mappings (Analysis::Mappings::get ())
+{}
+
+BaseType::~BaseType () {}
+
+HirId
+BaseType::get_ref () const
+{
+ return ref;
+}
+
+void
+BaseType::set_ref (HirId id)
+{
+ if (id != ref)
+ append_reference (ref);
+ ref = id;
+}
+
+HirId
+BaseType::get_ty_ref () const
+{
+ return ty_ref;
+}
+
+void
+BaseType::set_ty_ref (HirId id)
+{
+ ty_ref = id;
+}
+
+bool
+BaseType::is_equal (const BaseType &other) const
+{
+ return get_kind () == other.get_kind ();
+}
+
+bool
+BaseType::is_unit () const
+{
+ return false;
+}
+
+TypeKind
+BaseType::get_kind () const
+{
+ return kind;
+}
+
+std::set<HirId>
+BaseType::get_combined_refs () const
+{
+ return combined;
+}
+
+void
+BaseType::append_reference (HirId id)
+{
+ combined.insert (id);
+}
+
+bool
+BaseType::supports_substitutions () const
+{
+ return false;
+}
+
+bool
+BaseType::has_subsititions_defined () const
+{
+ return false;
+}
+
+bool
+BaseType::can_substitute () const
+{
+ return supports_substitutions () && has_subsititions_defined ();
+}
+
+bool
+BaseType::needs_generic_substitutions () const
+{
+ return false;
+}
+
+bool
+BaseType::contains_type_parameters () const
+{
+ return !is_concrete ();
+}
+
+const RustIdent &
+BaseType::get_ident () const
+{
+ return ident;
+}
+
+Location
+BaseType::get_locus () const
+{
+ return ident.locus;
+}
+
+// FIXME this is missing locus
bool
BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const
{
@@ -157,12 +279,67 @@ BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const
return true;
}
+ bool satisfied = false;
auto probed = Resolver::TypeBoundsProbe::Probe (this);
for (const auto &b : probed)
{
const Resolver::TraitReference *bound = b.first;
if (bound->satisfies_bound (*query))
+ {
+ satisfied = true;
+ break;
+ }
+ }
+
+ if (!satisfied)
+ return false;
+
+ for (const auto &b : probed)
+ {
+ const Resolver::TraitReference *bound = b.first;
+ if (!bound->is_equal (*query))
+ continue;
+
+ // builtin ones have no impl-block this needs fixed and use a builtin node
+ // of somekind
+ if (b.second == nullptr)
return true;
+
+ // need to check that associated types can match as well
+ const HIR::ImplBlock &impl = *(b.second);
+ for (const auto &item : impl.get_impl_items ())
+ {
+ TyTy::BaseType *impl_item_ty = nullptr;
+ Analysis::NodeMapping i = item->get_impl_mappings ();
+ bool query_ok = Resolver::query_type (i.get_hirid (), &impl_item_ty);
+ if (!query_ok)
+ return false;
+
+ std::string item_name = item->get_impl_item_name ();
+ TypeBoundPredicateItem lookup
+ = predicate.lookup_associated_item (item_name);
+ if (lookup.is_error ())
+ return false;
+
+ const auto *item_ref = lookup.get_raw_item ();
+ TyTy::BaseType *bound_ty = item_ref->get_tyty ();
+
+ // compare the types
+ if (!bound_ty->can_eq (impl_item_ty, false))
+ {
+ RichLocation r (mappings->lookup_location (get_ref ()));
+ r.add_range (predicate.get_locus ());
+ r.add_range (mappings->lookup_location (i.get_hirid ()));
+
+ rust_error_at (
+ r, "expected %<%s%> got %<%s%>",
+ bound_ty->destructure ()->get_name ().c_str (),
+ impl_item_ty->destructure ()->get_name ().c_str ());
+ return false;
+ }
+ }
+
+ return true;
}
return false;
@@ -255,6 +432,58 @@ BaseType::get_root () const
return root;
}
+BaseType *
+BaseType::destructure ()
+{
+ int recurisve_ops = 0;
+ BaseType *x = this;
+ while (true)
+ {
+ if (recurisve_ops++ >= rust_max_recursion_depth)
+ {
+ rust_error_at (
+ Location (),
+ "%<recursion depth%> count exceeds limit of %i (use "
+ "%<frust-max-recursion-depth=%> to increase the limit)",
+ rust_max_recursion_depth);
+ return new ErrorType (get_ref ());
+ }
+
+ switch (x->get_kind ())
+ {
+ case TyTy::TypeKind::PARAM: {
+ TyTy::ParamType *p = static_cast<TyTy::ParamType *> (x);
+ TyTy::BaseType *pr = p->resolve ();
+ if (pr == x)
+ return pr;
+
+ x = pr;
+ }
+ break;
+
+ case TyTy::TypeKind::PLACEHOLDER: {
+ TyTy::PlaceholderType *p = static_cast<TyTy::PlaceholderType *> (x);
+ if (!p->can_resolve ())
+ return p;
+
+ x = p->resolve ();
+ }
+ break;
+
+ case TyTy::TypeKind::PROJECTION: {
+ TyTy::ProjectionType *p = static_cast<TyTy::ProjectionType *> (x);
+ x = p->get ();
+ }
+ break;
+
+ default:
+ return x;
+ }
+ }
+
+ return x;
+}
+
const BaseType *
BaseType::destructure () const
{
@@ -276,14 +505,20 @@ BaseType::destructure () const
{
case TyTy::TypeKind::PARAM: {
const TyTy::ParamType *p = static_cast<const TyTy::ParamType *> (x);
- x = p->resolve ();
+ const TyTy::BaseType *pr = p->resolve ();
+ if (pr == x)
+ return pr;
+
+ x = pr;
}
break;
case TyTy::TypeKind::PLACEHOLDER: {
const TyTy::PlaceholderType *p
= static_cast<const TyTy::PlaceholderType *> (x);
- rust_assert (p->can_resolve ());
+ if (!p->can_resolve ())
+ return p;
+
x = p->resolve ();
}
break;
@@ -330,94 +565,38 @@ BaseType::debug () const
debug_str ().c_str ());
}
-TyVar::TyVar (HirId ref) : ref (ref)
-{
- // ensure this reference is defined within the context
- auto context = Resolver::TypeCheckContext::get ();
- BaseType *lookup = nullptr;
- bool ok = context->lookup_type (ref, &lookup);
- rust_assert (ok);
-}
-
-BaseType *
-TyVar::get_tyty () const
-{
- auto context = Resolver::TypeCheckContext::get ();
- BaseType *lookup = nullptr;
- bool ok = context->lookup_type (ref, &lookup);
- rust_assert (ok);
- return lookup;
-}
-
-TyVar
-TyVar::get_implicit_infer_var (Location locus)
-{
- auto mappings = Analysis::Mappings::get ();
- auto context = Resolver::TypeCheckContext::get ();
-
- InferType *infer = new InferType (mappings->get_next_hir_id (),
- InferType::InferTypeKind::GENERAL, locus);
- context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
- UNKNOWN_NODEID,
- infer->get_ref (),
- UNKNOWN_LOCAL_DEFID),
- infer);
- mappings->insert_location (infer->get_ref (), locus);
-
- return TyVar (infer->get_ref ());
-}
+// InferType
-TyVar
-TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst)
-{
- if (orig->get_kind () != TyTy::TypeKind::PARAM)
- return TyVar (subst->get_ty_ref ());
- else if (subst->get_kind () == TyTy::TypeKind::PARAM)
- {
- TyTy::ParamType *p = static_cast<TyTy::ParamType *> (subst);
- if (p->resolve ()->get_kind () == TyTy::TypeKind::PARAM)
- {
- return TyVar (subst->get_ty_ref ());
- }
- }
+InferType::InferType (HirId ref, InferTypeKind infer_kind, Location locus,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::INFER,
+ {Resolver::CanonicalPath::create_empty (), locus}, refs),
+ infer_kind (infer_kind)
+{}
- return TyVar (subst->get_ref ());
-}
+InferType::InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind,
+ Location locus, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::INFER,
+ {Resolver::CanonicalPath::create_empty (), locus}, refs),
+ infer_kind (infer_kind)
+{}
-TyVar
-TyVar::clone () const
+InferType::InferTypeKind
+InferType::get_infer_kind () const
{
- TyTy::BaseType *c = get_tyty ()->clone ();
- return TyVar (c->get_ref ());
+ return infer_kind;
}
-TyVar
-TyVar::monomorphized_clone () const
+std::string
+InferType::get_name () const
{
- auto mappings = Analysis::Mappings::get ();
- auto context = Resolver::TypeCheckContext::get ();
-
- // this needs a new hirid
- TyTy::BaseType *c = get_tyty ()->monomorphized_clone ();
- c->set_ref (mappings->get_next_hir_id ());
-
- // insert it
- context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
- UNKNOWN_NODEID, c->get_ref (),
- UNKNOWN_LOCAL_DEFID),
- c);
-
- return TyVar (c->get_ref ());
+ return as_string ();
}
-TyWithLocation::TyWithLocation (BaseType *ty, Location locus)
- : ty (ty), locus (locus)
-{}
-
-TyWithLocation::TyWithLocation (BaseType *ty) : ty (ty)
+bool
+InferType::is_concrete () const
{
- auto mappings = Analysis::Mappings::get ();
- locus = mappings->lookup_location (ty->get_ref ());
+ return true;
}
void
@@ -447,13 +626,6 @@ InferType::as_string () const
return "<infer::error>";
}
-BaseType *
-InferType::unify (BaseType *other)
-{
- InferRules r (this);
- return r.unify (other);
-}
-
bool
InferType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -525,6 +697,35 @@ InferType::default_type (BaseType **type) const
return false;
}
+// ErrorType
+
+ErrorType::ErrorType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::ERROR,
+ {Resolver::CanonicalPath::create_empty (), Location ()}, refs)
+{}
+
+ErrorType::ErrorType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::ERROR,
+ {Resolver::CanonicalPath::create_empty (), Location ()}, refs)
+{}
+
+bool
+ErrorType::is_unit () const
+{
+ return true;
+}
+bool
+ErrorType::is_concrete () const
+{
+ return false;
+}
+
+std::string
+ErrorType::get_name () const
+{
+ return as_string ();
+}
+
void
ErrorType::accept_vis (TyVisitor &vis)
{
@@ -543,12 +744,6 @@ ErrorType::as_string () const
return "<tyty::error>";
}
-BaseType *
-ErrorType::unify (BaseType *other)
-{
- return this;
-}
-
bool
ErrorType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -567,6 +762,55 @@ ErrorType::monomorphized_clone () const
return clone ();
}
+// Struct Field type
+
+StructFieldType::StructFieldType (HirId ref, std::string name, BaseType *ty,
+ Location locus)
+ : ref (ref), name (name), ty (ty), locus (locus)
+{}
+
+HirId
+StructFieldType::get_ref () const
+{
+ return ref;
+}
+
+std::string
+StructFieldType::get_name () const
+{
+ return name;
+}
+
+BaseType *
+StructFieldType::get_field_type () const
+{
+ return ty;
+}
+
+void
+StructFieldType::set_field_type (BaseType *fty)
+{
+ ty = fty;
+}
+
+bool
+StructFieldType::is_concrete () const
+{
+ return ty->is_concrete ();
+}
+
+void
+StructFieldType::debug () const
+{
+ rust_debug ("%s", as_string ().c_str ());
+}
+
+Location
+StructFieldType::get_locus () const
+{
+ return locus;
+}
+
std::string
StructFieldType::as_string () const
{
@@ -604,417 +848,241 @@ StructFieldType::monomorphized_clone () const
get_field_type ()->monomorphized_clone (), locus);
}
-bool
-SubstitutionParamMapping::need_substitution () const
-{
- if (!param->can_resolve ())
- return true;
-
- auto resolved = param->resolve ();
- return !resolved->is_concrete ();
-}
+// VariantDef
-bool
-SubstitutionParamMapping::fill_param_ty (
- SubstitutionArgumentMappings &subst_mappings, Location locus)
+std::string
+VariantDef::variant_type_string (VariantType type)
{
- SubstitutionArg arg = SubstitutionArg::error ();
- bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
- if (!ok)
- return true;
-
- TyTy::BaseType &type = *arg.get_tyty ();
- if (type.get_kind () == TyTy::TypeKind::INFER)
+ switch (type)
{
- type.inherit_bounds (*param);
- }
- else
- {
- if (!param->bounds_compatible (type, locus, true))
- return false;
- }
-
- if (type.get_kind () == TypeKind::PARAM)
- {
- // delete param;
- param = static_cast<ParamType *> (type.clone ());
- }
- else
- {
- // check the substitution is compatible with bounds
- if (!param->bounds_compatible (type, locus, true))
- return false;
-
- // recursively pass this down to all HRTB's
- for (auto &bound : param->get_specified_bounds ())
- bound.handle_substitions (subst_mappings);
-
- param->set_ty_ref (type.get_ref ());
+ case NUM:
+ return "enumeral";
+ case TUPLE:
+ return "tuple";
+ case STRUCT:
+ return "struct";
}
-
- return true;
+ gcc_unreachable ();
+ return "";
}
-void
-SubstitutionParamMapping::override_context ()
-{
- if (!param->can_resolve ())
- return;
-
- auto mappings = Analysis::Mappings::get ();
- auto context = Resolver::TypeCheckContext::get ();
+VariantDef::VariantDef (HirId id, DefId defid, std::string identifier,
+ RustIdent ident, HIR::Expr *discriminant)
+ : id (id), defid (defid), identifier (identifier), ident (ident),
+ discriminant (discriminant)
- context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
- UNKNOWN_NODEID,
- param->get_ref (),
- UNKNOWN_LOCAL_DEFID),
- param->resolve ());
+{
+ type = VariantType::NUM;
+ fields = {};
}
-SubstitutionArgumentMappings
-SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
+VariantDef::VariantDef (HirId id, DefId defid, std::string identifier,
+ RustIdent ident, VariantType type,
+ HIR::Expr *discriminant,
+ std::vector<StructFieldType *> fields)
+ : id (id), defid (defid), identifier (identifier), ident (ident), type (type),
+ discriminant (discriminant), fields (fields)
{
- if (args.get_binding_args ().size () > 0)
- {
- RichLocation r (args.get_locus ());
- for (auto &binding : args.get_binding_args ())
- r.add_range (binding.get_locus ());
-
- rust_error_at (r, "associated type bindings are not allowed here");
- return SubstitutionArgumentMappings::error ();
- }
-
- // for inherited arguments
- size_t offs = used_arguments.size ();
- if (args.get_type_args ().size () + offs > substitutions.size ())
- {
- RichLocation r (args.get_locus ());
- r.add_range (substitutions.front ().get_param_locus ());
-
- rust_error_at (
- r,
- "generic item takes at most %lu type arguments but %lu were supplied",
- (unsigned long) substitutions.size (),
- (unsigned long) args.get_type_args ().size ());
- return SubstitutionArgumentMappings::error ();
- }
-
- if (args.get_type_args ().size () + offs < min_required_substitutions ())
- {
- RichLocation r (args.get_locus ());
- r.add_range (substitutions.front ().get_param_locus ());
-
- rust_error_at (
- r,
- "generic item takes at least %lu type arguments but %lu were supplied",
- (unsigned long) (min_required_substitutions () - offs),
- (unsigned long) args.get_type_args ().size ());
- return SubstitutionArgumentMappings::error ();
- }
-
- std::vector<SubstitutionArg> mappings = used_arguments.get_mappings ();
- for (auto &arg : args.get_type_args ())
- {
- BaseType *resolved = Resolver::TypeCheckType::Resolve (arg.get ());
- if (resolved == nullptr || resolved->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (args.get_locus (), "failed to resolve type arguments");
- return SubstitutionArgumentMappings::error ();
- }
+ rust_assert ((type == VariantType::NUM && fields.empty ())
+ || (type == VariantType::TUPLE || type == VariantType::STRUCT));
+}
- SubstitutionArg subst_arg (&substitutions.at (offs), resolved);
- offs++;
- mappings.push_back (std::move (subst_arg));
- }
+VariantDef::VariantDef (const VariantDef &other)
+ : id (other.id), defid (other.defid), identifier (other.identifier),
+ ident (other.ident), type (other.type), discriminant (other.discriminant),
+ fields (other.fields)
+{}
- // we must need to fill out defaults
- size_t left_over
- = num_required_substitutions () - min_required_substitutions ();
- if (left_over > 0)
- {
- for (size_t offs = mappings.size (); offs < substitutions.size (); offs++)
- {
- SubstitutionParamMapping &param = substitutions.at (offs);
- rust_assert (param.param_has_default_ty ());
+VariantDef &
+VariantDef::operator= (const VariantDef &other)
+{
+ id = other.id;
+ identifier = other.identifier;
+ type = other.type;
+ discriminant = other.discriminant;
+ fields = other.fields;
+ ident = other.ident;
- BaseType *resolved = param.get_default_ty ();
- if (resolved->get_kind () == TypeKind::ERROR)
- return SubstitutionArgumentMappings::error ();
+ return *this;
+}
- // this resolved default might already contain default parameters
- if (resolved->contains_type_parameters ())
- {
- SubstitutionArgumentMappings intermediate (mappings,
- args.get_locus ());
- resolved = Resolver::SubstMapperInternal::Resolve (resolved,
- intermediate);
+VariantDef &
+VariantDef::get_error_node ()
+{
+ static VariantDef node
+ = VariantDef (UNKNOWN_HIRID, UNKNOWN_DEFID, "",
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::unknown_location ()},
+ nullptr);
- if (resolved->get_kind () == TypeKind::ERROR)
- return SubstitutionArgumentMappings::error ();
- }
+ return node;
+}
- SubstitutionArg subst_arg (&param, resolved);
- mappings.push_back (std::move (subst_arg));
- }
- }
+bool
+VariantDef::is_error () const
+{
+ return get_id () == UNKNOWN_HIRID;
+}
- return SubstitutionArgumentMappings (mappings, args.get_locus ());
+HirId
+VariantDef::get_id () const
+{
+ return id;
}
-BaseType *
-SubstitutionRef::infer_substitions (Location locus)
+DefId
+VariantDef::get_defid () const
{
- std::vector<SubstitutionArg> args;
- std::map<std::string, BaseType *> argument_mappings;
- for (auto &p : get_substs ())
- {
- if (p.needs_substitution ())
- {
- const std::string &symbol = p.get_param_ty ()->get_symbol ();
- auto it = argument_mappings.find (symbol);
- bool have_mapping = it != argument_mappings.end ();
+ return defid;
+}
- if (have_mapping)
- {
- args.push_back (SubstitutionArg (&p, it->second));
- }
- else
- {
- TyVar infer_var = TyVar::get_implicit_infer_var (locus);
- args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
- argument_mappings[symbol] = infer_var.get_tyty ();
- }
- }
- else
- {
- args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
- }
- }
+VariantDef::VariantType
+VariantDef::get_variant_type () const
+{
+ return type;
+}
- SubstitutionArgumentMappings infer_arguments (std::move (args), locus);
- return handle_substitions (std::move (infer_arguments));
+bool
+VariantDef::is_data_variant () const
+{
+ return type != VariantType::NUM;
}
-SubstitutionArgumentMappings
-SubstitutionRef::adjust_mappings_for_this (
- SubstitutionArgumentMappings &mappings)
+bool
+VariantDef::is_dataless_variant () const
{
- std::vector<SubstitutionArg> resolved_mappings;
- for (size_t i = 0; i < substitutions.size (); i++)
- {
- auto &subst = substitutions.at (i);
+ return type == VariantType::NUM;
+}
- SubstitutionArg arg = SubstitutionArg::error ();
- if (mappings.size () == substitutions.size ())
- {
- mappings.get_argument_at (i, &arg);
- }
- else
- {
- if (subst.needs_substitution ())
- {
- // get from passed in mappings
- mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
- }
- else
- {
- // we should already have this somewhere
- used_arguments.get_argument_for_symbol (subst.get_param_ty (),
- &arg);
- }
- }
+std::string
+VariantDef::get_identifier () const
+{
+ return identifier;
+}
- bool ok = !arg.is_error ();
- if (ok)
- {
- SubstitutionArg adjusted (&subst, arg.get_tyty ());
- resolved_mappings.push_back (std::move (adjusted));
- }
- }
+size_t
+VariantDef::num_fields () const
+{
+ return fields.size ();
+}
- if (resolved_mappings.empty ())
- return SubstitutionArgumentMappings::error ();
+StructFieldType *
+VariantDef::get_field_at_index (size_t index)
+{
+ rust_assert (index < fields.size ());
+ return fields.at (index);
+}
- return SubstitutionArgumentMappings (resolved_mappings, mappings.get_locus (),
- mappings.get_subst_cb (),
- mappings.trait_item_mode ());
+std::vector<StructFieldType *> &
+VariantDef::get_fields ()
+{
+ rust_assert (type != NUM);
+ return fields;
}
bool
-SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
+VariantDef::lookup_field (const std::string &lookup,
+ StructFieldType **field_lookup, size_t *index) const
{
- std::vector<SubstitutionArg> resolved_mappings;
- for (size_t i = 0; i < substitutions.size (); i++)
+ size_t i = 0;
+ for (auto &field : fields)
{
- auto &subst = substitutions.at (i);
-
- SubstitutionArg arg = SubstitutionArg::error ();
- if (mappings.size () == substitutions.size ())
+ if (field->get_name ().compare (lookup) == 0)
{
- mappings.get_argument_at (i, &arg);
- }
- else
- {
- if (subst.needs_substitution ())
- {
- // get from passed in mappings
- mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
- }
- else
- {
- // we should already have this somewhere
- used_arguments.get_argument_for_symbol (subst.get_param_ty (),
- &arg);
- }
- }
+ if (index != nullptr)
+ *index = i;
- bool ok = !arg.is_error ();
- if (ok)
- {
- SubstitutionArg adjusted (&subst, arg.get_tyty ());
- resolved_mappings.push_back (std::move (adjusted));
+ if (field_lookup != nullptr)
+ *field_lookup = field;
+
+ return true;
}
+ i++;
}
+ return false;
+}
- return !resolved_mappings.empty ();
+HIR::Expr *
+VariantDef::get_discriminant () const
+{
+ rust_assert (discriminant != nullptr);
+ return discriminant;
}
-// this function assumes that the mappings being passed are for the same type as
-// this new substitution reference so ordering matters here
-SubstitutionArgumentMappings
-SubstitutionRef::solve_mappings_from_receiver_for_self (
- SubstitutionArgumentMappings &mappings) const
+std::string
+VariantDef::as_string () const
{
- std::vector<SubstitutionArg> resolved_mappings;
+ if (type == VariantType::NUM)
+ return identifier + " = " + discriminant->as_string ();
- rust_assert (mappings.size () == get_num_substitutions ());
- for (size_t i = 0; i < get_num_substitutions (); i++)
+ std::string buffer;
+ for (size_t i = 0; i < fields.size (); ++i)
{
- const SubstitutionParamMapping &param_mapping = substitutions.at (i);
- SubstitutionArg &arg = mappings.get_mappings ().at (i);
-
- if (param_mapping.needs_substitution ())
- {
- SubstitutionArg adjusted (&param_mapping, arg.get_tyty ());
- resolved_mappings.push_back (std::move (adjusted));
- }
+ buffer += fields.at (i)->as_string ();
+ if ((i + 1) < fields.size ())
+ buffer += ", ";
}
- return SubstitutionArgumentMappings (resolved_mappings,
- mappings.get_locus ());
+ if (type == VariantType::TUPLE)
+ return identifier + " (" + buffer + ")";
+ else
+ return identifier + " {" + buffer + "}";
}
-SubstitutionArgumentMappings
-SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref,
- SubstitutionRef &to)
+bool
+VariantDef::is_equal (const VariantDef &other) const
{
- rust_assert (!ref.needs_substitution ());
- rust_assert (needs_substitution ());
- rust_assert (get_num_substitutions () == ref.get_num_substitutions ());
-
- Location locus = used_arguments.get_locus ();
- std::vector<SubstitutionArg> resolved_mappings;
+ if (type != other.type)
+ return false;
- std::map<HirId, std::pair<ParamType *, BaseType *>> substs;
- for (size_t i = 0; i < get_num_substitutions (); i++)
- {
- SubstitutionParamMapping &a = substitutions.at (i);
- SubstitutionParamMapping &b = ref.substitutions.at (i);
+ if (identifier.compare (other.identifier) != 0)
+ return false;
- if (a.need_substitution ())
- {
- const BaseType *root = a.get_param_ty ()->resolve ()->get_root ();
- rust_assert (root->get_kind () == TyTy::TypeKind::PARAM);
- const ParamType *p = static_cast<const TyTy::ParamType *> (root);
+ if (discriminant != other.discriminant)
+ return false;
- substs[p->get_ty_ref ()] = {static_cast<ParamType *> (p->clone ()),
- b.get_param_ty ()->resolve ()};
- }
- }
+ if (fields.size () != other.fields.size ())
+ return false;
- for (auto it = substs.begin (); it != substs.end (); it++)
+ for (size_t i = 0; i < fields.size (); i++)
{
- HirId param_id = it->first;
- BaseType *arg = it->second.second;
-
- const SubstitutionParamMapping *associate_param = nullptr;
- for (SubstitutionParamMapping &p : to.substitutions)
- {
- if (p.get_param_ty ()->get_ty_ref () == param_id)
- {
- associate_param = &p;
- break;
- }
- }
-
- rust_assert (associate_param != nullptr);
- SubstitutionArg argument (associate_param, arg);
- resolved_mappings.push_back (std::move (argument));
+ if (!fields.at (i)->is_equal (*other.fields.at (i)))
+ return false;
}
- return SubstitutionArgumentMappings (resolved_mappings, locus);
+ return true;
}
-bool
-SubstitutionRef::monomorphize ()
+VariantDef *
+VariantDef::clone () const
{
- auto context = Resolver::TypeCheckContext::get ();
- for (const auto &subst : get_substs ())
- {
- const TyTy::ParamType *pty = subst.get_param_ty ();
-
- if (!pty->can_resolve ())
- continue;
-
- const TyTy::BaseType *binding = pty->resolve ();
- if (binding->get_kind () == TyTy::TypeKind::PARAM)
- continue;
+ std::vector<StructFieldType *> cloned_fields;
+ for (auto &f : fields)
+ cloned_fields.push_back ((StructFieldType *) f->clone ());
- for (const auto &bound : pty->get_specified_bounds ())
- {
- const Resolver::TraitReference *specified_bound_ref = bound.get ();
-
- // setup any associated type mappings for the specified bonds and this
- // type
- auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
+ return new VariantDef (id, defid, identifier, ident, type, discriminant,
+ cloned_fields);
+}
- Resolver::AssociatedImplTrait *associated_impl_trait = nullptr;
- for (auto &probed_bound : candidates)
- {
- const Resolver::TraitReference *bound_trait_ref
- = probed_bound.first;
- const HIR::ImplBlock *associated_impl = probed_bound.second;
-
- HirId impl_block_id
- = associated_impl->get_mappings ().get_hirid ();
- Resolver::AssociatedImplTrait *associated = nullptr;
- bool found_impl_trait
- = context->lookup_associated_trait_impl (impl_block_id,
- &associated);
- if (found_impl_trait)
- {
- bool found_trait
- = specified_bound_ref->is_equal (*bound_trait_ref);
- bool found_self
- = associated->get_self ()->can_eq (binding, false);
- if (found_trait && found_self)
- {
- associated_impl_trait = associated;
- break;
- }
- }
- }
+VariantDef *
+VariantDef::monomorphized_clone () const
+{
+ std::vector<StructFieldType *> cloned_fields;
+ for (auto &f : fields)
+ cloned_fields.push_back ((StructFieldType *) f->monomorphized_clone ());
- if (associated_impl_trait != nullptr)
- {
- associated_impl_trait->setup_associated_types (binding, bound);
- }
- }
- }
+ return new VariantDef (id, defid, identifier, ident, type, discriminant,
+ cloned_fields);
+}
- return true;
+const RustIdent &
+VariantDef::get_ident () const
+{
+ return ident;
}
+// ADTType
+
void
ADTType::accept_vis (TyVisitor &vis)
{
@@ -1042,13 +1110,6 @@ ADTType::as_string () const
return identifier + subst_as_string () + "{" + variants_buffer + "}";
}
-BaseType *
-ADTType::unify (BaseType *other)
-{
- ADTRules r (this);
- return r.unify (other);
-}
-
bool
ADTType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1181,7 +1242,7 @@ handle_substitions (SubstitutionArgumentMappings &subst_mappings,
}
ADTType *
-ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+ADTType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
{
ADTType *adt = static_cast<ADTType *> (clone ());
adt->set_ty_ref (mappings->get_next_hir_id ());
@@ -1212,6 +1273,57 @@ ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
return adt;
}
+// TupleType
+
+TupleType::TupleType (HirId ref, Location locus, std::vector<TyVar> fields,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::TUPLE,
+ {Resolver::CanonicalPath::create_empty (), locus}, refs),
+ fields (fields)
+{}
+
+TupleType::TupleType (HirId ref, HirId ty_ref, Location locus,
+ std::vector<TyVar> fields, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::TUPLE,
+ {Resolver::CanonicalPath::create_empty (), locus}, refs),
+ fields (fields)
+{}
+
+TupleType *
+TupleType::get_unit_type (HirId ref)
+{
+ return new TupleType (ref, Linemap::predeclared_location ());
+}
+
+bool
+TupleType::is_unit () const
+{
+ return this->fields.empty ();
+}
+
+size_t
+TupleType::num_fields () const
+{
+ return fields.size ();
+}
+
+bool
+TupleType::is_concrete () const
+{
+ for (size_t i = 0; i < num_fields (); i++)
+ {
+ if (!get_field (i)->is_concrete ())
+ return false;
+ }
+ return true;
+}
+
+const std::vector<TyVar> &
+TupleType::get_fields () const
+{
+ return fields;
+}
+
void
TupleType::accept_vis (TyVisitor &vis)
{
@@ -1260,13 +1372,6 @@ TupleType::get_field (size_t index) const
return fields.at (index).get_tyty ();
}
-BaseType *
-TupleType::unify (BaseType *other)
-{
- TupleRules r (this);
- return r.unify (other);
-}
-
bool
TupleType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1315,7 +1420,7 @@ TupleType::monomorphized_clone () const
}
TupleType *
-TupleType::handle_substitions (SubstitutionArgumentMappings mappings)
+TupleType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
auto mappings_table = Analysis::Mappings::get ();
@@ -1367,13 +1472,6 @@ FnType::as_string () const
return "fn" + subst_as_string () + " (" + params_str + ") -> " + ret_str;
}
-BaseType *
-FnType::unify (BaseType *other)
-{
- FnRules r (this);
- return r.unify (other);
-}
-
bool
FnType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1456,7 +1554,7 @@ FnType::monomorphized_clone () const
}
FnType *
-FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+FnType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
{
FnType *fn = static_cast<FnType *> (clone ());
fn->set_ty_ref (mappings->get_next_hir_id ());
@@ -1598,13 +1696,6 @@ FnPtr::as_string () const
return "fnptr (" + params_str + ") -> " + get_return_type ()->as_string ();
}
-BaseType *
-FnPtr::unify (BaseType *other)
-{
- FnptrRules r (this);
- return r.unify (other);
-}
-
bool
FnPtr::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1678,13 +1769,6 @@ ClosureType::as_string () const
return "|" + params_buf + "| {" + result_type.get_tyty ()->as_string () + "}";
}
-BaseType *
-ClosureType::unify (BaseType *other)
-{
- ClosureRules r (this);
- return r.unify (other);
-}
-
bool
ClosureType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1724,7 +1808,7 @@ ClosureType::monomorphized_clone () const
}
ClosureType *
-ClosureType::handle_substitions (SubstitutionArgumentMappings mappings)
+ClosureType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
gcc_unreachable ();
return nullptr;
@@ -1794,13 +1878,6 @@ ArrayType::as_string () const
return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]";
}
-BaseType *
-ArrayType::unify (BaseType *other)
-{
- ArrayRules r (this);
- return r.unify (other);
-}
-
bool
ArrayType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1844,7 +1921,7 @@ ArrayType::monomorphized_clone () const
}
ArrayType *
-ArrayType::handle_substitions (SubstitutionArgumentMappings mappings)
+ArrayType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
auto mappings_table = Analysis::Mappings::get ();
@@ -1877,13 +1954,6 @@ SliceType::as_string () const
return "[" + get_element_type ()->as_string () + "]";
}
-BaseType *
-SliceType::unify (BaseType *other)
-{
- SliceRules r (this);
- return r.unify (other);
-}
-
bool
SliceType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1927,7 +1997,7 @@ SliceType::monomorphized_clone () const
}
SliceType *
-SliceType::handle_substitions (SubstitutionArgumentMappings mappings)
+SliceType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
auto mappings_table = Analysis::Mappings::get ();
@@ -1942,6 +2012,34 @@ SliceType::handle_substitions (SubstitutionArgumentMappings mappings)
return ref;
}
+// BoolType
+
+BoolType::BoolType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::BOOL,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+BoolType::BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::BOOL,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+std::string
+BoolType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+BoolType::is_concrete () const
+{
+ return true;
+}
+
void
BoolType::accept_vis (TyVisitor &vis)
{
@@ -1960,13 +2058,6 @@ BoolType::as_string () const
return "bool";
}
-BaseType *
-BoolType::unify (BaseType *other)
-{
- BoolRules r (this);
- return r.unify (other);
-}
-
bool
BoolType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1986,6 +2077,36 @@ BoolType::monomorphized_clone () const
return clone ();
}
+// IntType
+
+IntType::IntType (HirId ref, IntKind kind, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::INT,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ int_kind (kind)
+{}
+
+IntType::IntType (HirId ref, HirId ty_ref, IntKind kind, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::INT,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ int_kind (kind)
+{}
+
+std::string
+IntType::get_name () const
+{
+ return as_string ();
+}
+
+IntType::IntKind
+IntType::get_int_kind () const
+{
+ return int_kind;
+}
+
void
IntType::accept_vis (TyVisitor &vis)
{
@@ -2018,13 +2139,6 @@ IntType::as_string () const
return "__unknown_int_type";
}
-BaseType *
-IntType::unify (BaseType *other)
-{
- IntRules r (this);
- return r.unify (other);
-}
-
bool
IntType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2055,6 +2169,43 @@ IntType::is_equal (const BaseType &other) const
return get_int_kind () == o.get_int_kind ();
}
+bool
+IntType::is_concrete () const
+{
+ return true;
+}
+
+// UintType
+
+UintType::UintType (HirId ref, UintKind kind, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::UINT,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ uint_kind (kind)
+{}
+
+UintType::UintType (HirId ref, HirId ty_ref, UintKind kind,
+ std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::UINT,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ uint_kind (kind)
+{}
+
+std::string
+UintType::get_name () const
+{
+ return as_string ();
+}
+
+UintType::UintKind
+UintType::get_uint_kind () const
+{
+ return uint_kind;
+}
+
void
UintType::accept_vis (TyVisitor &vis)
{
@@ -2087,13 +2238,6 @@ UintType::as_string () const
return "__unknown_uint_type";
}
-BaseType *
-UintType::unify (BaseType *other)
-{
- UintRules r (this);
- return r.unify (other);
-}
-
bool
UintType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2124,6 +2268,49 @@ UintType::is_equal (const BaseType &other) const
return get_uint_kind () == o.get_uint_kind ();
}
+bool
+UintType::is_concrete () const
+{
+ return true;
+}
+
+// FloatType
+
+FloatType::FloatType (HirId ref, FloatKind kind, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::FLOAT,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ float_kind (kind)
+{}
+
+FloatType::FloatType (HirId ref, HirId ty_ref, FloatKind kind,
+ std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::FLOAT,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ float_kind (kind)
+{}
+
+std::string
+FloatType::get_name () const
+{
+ return as_string ();
+}
+
+FloatType::FloatKind
+FloatType::get_float_kind () const
+{
+ return float_kind;
+}
+
+bool
+FloatType::is_concrete () const
+{
+ return true;
+}
+
void
FloatType::accept_vis (TyVisitor &vis)
{
@@ -2150,13 +2337,6 @@ FloatType::as_string () const
return "__unknown_float_type";
}
-BaseType *
-FloatType::unify (BaseType *other)
-{
- FloatRules r (this);
- return r.unify (other);
-}
-
bool
FloatType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2187,6 +2367,34 @@ FloatType::is_equal (const BaseType &other) const
return get_float_kind () == o.get_float_kind ();
}
+// UsizeType
+
+USizeType::USizeType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::USIZE,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+USizeType::USizeType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::USIZE,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+std::string
+USizeType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+USizeType::is_concrete () const
+{
+ return true;
+}
+
void
USizeType::accept_vis (TyVisitor &vis)
{
@@ -2205,13 +2413,6 @@ USizeType::as_string () const
return "usize";
}
-BaseType *
-USizeType::unify (BaseType *other)
-{
- USizeRules r (this);
- return r.unify (other);
-}
-
bool
USizeType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2231,6 +2432,34 @@ USizeType::monomorphized_clone () const
return clone ();
}
+// ISizeType
+
+ISizeType::ISizeType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::ISIZE,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+ISizeType::ISizeType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::ISIZE,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+std::string
+ISizeType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+ISizeType::is_concrete () const
+{
+ return true;
+}
+
void
ISizeType::accept_vis (TyVisitor &vis)
{
@@ -2249,13 +2478,6 @@ ISizeType::as_string () const
return "isize";
}
-BaseType *
-ISizeType::unify (BaseType *other)
-{
- ISizeRules r (this);
- return r.unify (other);
-}
-
bool
ISizeType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2275,6 +2497,34 @@ ISizeType::monomorphized_clone () const
return clone ();
}
+// Char Type
+
+CharType::CharType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::CHAR,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+CharType::CharType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::CHAR,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+bool
+CharType::is_concrete () const
+{
+ return true;
+}
+
+std::string
+CharType::get_name () const
+{
+ return as_string ();
+}
+
void
CharType::accept_vis (TyVisitor &vis)
{
@@ -2293,13 +2543,6 @@ CharType::as_string () const
return "char";
}
-BaseType *
-CharType::unify (BaseType *other)
-{
- CharRules r (this);
- return r.unify (other);
-}
-
bool
CharType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2319,6 +2562,76 @@ CharType::monomorphized_clone () const
return clone ();
}
+// Reference Type
+
+ReferenceType::ReferenceType (HirId ref, TyVar base, Mutability mut,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::REF,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ base (base), mut (mut)
+{}
+
+ReferenceType::ReferenceType (HirId ref, HirId ty_ref, TyVar base,
+ Mutability mut, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::REF,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ base (base), mut (mut)
+{}
+
+bool
+ReferenceType::is_concrete () const
+{
+ return get_base ()->is_concrete ();
+}
+
+Mutability
+ReferenceType::mutability () const
+{
+ return mut;
+}
+
+bool
+ReferenceType::is_mutable () const
+{
+ return mut == Mutability::Mut;
+}
+
+bool
+ReferenceType::is_dyn_object () const
+{
+ return is_dyn_slice_type () || is_dyn_str_type ();
+}
+
+bool
+ReferenceType::is_dyn_slice_type (const TyTy::SliceType **slice) const
+{
+ const TyTy::BaseType *element = get_base ()->destructure ();
+ if (element->get_kind () != TyTy::TypeKind::SLICE)
+ return false;
+ if (slice == nullptr)
+ return true;
+
+ *slice = static_cast<const TyTy::SliceType *> (element);
+ return true;
+}
+
+bool
+ReferenceType::is_dyn_str_type (const TyTy::StrType **str) const
+{
+ const TyTy::BaseType *element = get_base ()->destructure ();
+ if (element->get_kind () != TyTy::TypeKind::STR)
+ return false;
+ if (str == nullptr)
+ return true;
+
+ *str = static_cast<const TyTy::StrType *> (element);
+ return true;
+}
+
void
ReferenceType::accept_vis (TyVisitor &vis)
{
@@ -2345,13 +2658,6 @@ ReferenceType::get_name () const
+ get_base ()->get_name ();
}
-BaseType *
-ReferenceType::unify (BaseType *other)
-{
- ReferenceRules r (this);
- return r.unify (other);
-}
-
bool
ReferenceType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2394,7 +2700,7 @@ ReferenceType::monomorphized_clone () const
}
ReferenceType *
-ReferenceType::handle_substitions (SubstitutionArgumentMappings mappings)
+ReferenceType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
auto mappings_table = Analysis::Mappings::get ();
@@ -2409,6 +2715,82 @@ ReferenceType::handle_substitions (SubstitutionArgumentMappings mappings)
return ref;
}
+// PointerType
+
+PointerType::PointerType (HirId ref, TyVar base, Mutability mut,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::POINTER,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ base (base), mut (mut)
+{}
+
+PointerType::PointerType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
+ std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::POINTER,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ base (base), mut (mut)
+{}
+
+bool
+PointerType::is_concrete () const
+{
+ return get_base ()->is_concrete ();
+}
+
+Mutability
+PointerType::mutability () const
+{
+ return mut;
+}
+
+bool
+PointerType::is_mutable () const
+{
+ return mut == Mutability::Mut;
+}
+
+bool
+PointerType::is_const () const
+{
+ return mut == Mutability::Imm;
+}
+
+bool
+PointerType::is_dyn_object () const
+{
+ return is_dyn_slice_type () || is_dyn_str_type ();
+}
+
+bool
+PointerType::is_dyn_slice_type (const TyTy::SliceType **slice) const
+{
+ const TyTy::BaseType *element = get_base ()->destructure ();
+ if (element->get_kind () != TyTy::TypeKind::SLICE)
+ return false;
+ if (slice == nullptr)
+ return true;
+
+ *slice = static_cast<const TyTy::SliceType *> (element);
+ return true;
+}
+
+bool
+PointerType::is_dyn_str_type (const TyTy::StrType **str) const
+{
+ const TyTy::BaseType *element = get_base ()->destructure ();
+ if (element->get_kind () != TyTy::TypeKind::STR)
+ return false;
+ if (str == nullptr)
+ return true;
+
+ *str = static_cast<const TyTy::StrType *> (element);
+ return true;
+}
+
void
PointerType::accept_vis (TyVisitor &vis)
{
@@ -2435,13 +2817,6 @@ PointerType::get_name () const
+ get_base ()->get_name ();
}
-BaseType *
-PointerType::unify (BaseType *other)
-{
- PointerRules r (this);
- return r.unify (other);
-}
-
bool
PointerType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2484,7 +2859,7 @@ PointerType::monomorphized_clone () const
}
PointerType *
-PointerType::handle_substitions (SubstitutionArgumentMappings mappings)
+PointerType::handle_substitions (SubstitutionArgumentMappings &mappings)
{
auto mappings_table = Analysis::Mappings::get ();
@@ -2499,6 +2874,52 @@ PointerType::handle_substitions (SubstitutionArgumentMappings mappings)
return ref;
}
+// PARAM Type
+
+ParamType::ParamType (std::string symbol, Location locus, HirId ref,
+ HIR::GenericParam &param,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::PARAM,
+ {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+ locus},
+ specified_bounds, refs),
+ is_trait_self (false), symbol (symbol), param (param)
+{}
+
+ParamType::ParamType (bool is_trait_self, std::string symbol, Location locus,
+ HirId ref, HirId ty_ref, HIR::GenericParam &param,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::PARAM,
+ {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+ locus},
+ specified_bounds, refs),
+ is_trait_self (is_trait_self), symbol (symbol), param (param)
+{}
+
+HIR::GenericParam &
+ParamType::get_generic_param ()
+{
+ return param;
+}
+
+bool
+ParamType::can_resolve () const
+{
+ return get_ref () != get_ty_ref ();
+}
+
+bool
+ParamType::is_concrete () const
+{
+ auto r = resolve ();
+ if (r == this)
+ return false;
+
+ return r->is_concrete ();
+}
+
void
ParamType::accept_vis (TyVisitor &vis)
{
@@ -2532,13 +2953,6 @@ ParamType::get_name () const
return resolve ()->get_name ();
}
-BaseType *
-ParamType::unify (BaseType *other)
-{
- ParamRules r (this);
- return r.unify (other);
-}
-
bool
ParamType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2549,8 +2963,9 @@ ParamType::can_eq (const BaseType *other, bool emit_errors) const
BaseType *
ParamType::clone () const
{
- return new ParamType (get_symbol (), ident.locus, get_ref (), get_ty_ref (),
- param, get_specified_bounds (), get_combined_refs ());
+ return new ParamType (is_trait_self, get_symbol (), ident.locus, get_ref (),
+ get_ty_ref (), param, get_specified_bounds (),
+ get_combined_refs ());
}
BaseType *
@@ -2615,7 +3030,7 @@ ParamType::is_equal (const BaseType &other) const
}
ParamType *
-ParamType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+ParamType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
{
SubstitutionArg arg = SubstitutionArg::error ();
bool ok = subst_mappings.get_argument_for_symbol (this, &arg);
@@ -2640,6 +3055,46 @@ ParamType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
return p;
}
+void
+ParamType::set_implicit_self_trait ()
+{
+ is_trait_self = true;
+}
+
+bool
+ParamType::is_implicit_self_trait () const
+{
+ return is_trait_self;
+}
+
+// StrType
+
+StrType::StrType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::STR,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+StrType::StrType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::STR,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+std::string
+StrType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+StrType::is_concrete () const
+{
+ return true;
+}
+
BaseType *
StrType::clone () const
{
@@ -2670,13 +3125,6 @@ StrType::as_string () const
return "str";
}
-BaseType *
-StrType::unify (BaseType *other)
-{
- StrRules r (this);
- return r.unify (other);
-}
-
bool
StrType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2690,6 +3138,40 @@ StrType::is_equal (const BaseType &other) const
return get_kind () == other.get_kind ();
}
+// Never Type
+
+NeverType::NeverType (HirId ref, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::NEVER,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+NeverType::NeverType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::NEVER,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs)
+{}
+
+std::string
+NeverType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+NeverType::is_unit () const
+{
+ return true;
+}
+
+bool
+NeverType::is_concrete () const
+{
+ return true;
+}
+
void
NeverType::accept_vis (TyVisitor &vis)
{
@@ -2708,13 +3190,6 @@ NeverType::as_string () const
return "!";
}
-BaseType *
-NeverType::unify (BaseType *other)
-{
- NeverRules r (this);
- return r.unify (other);
-}
-
bool
NeverType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2736,6 +3211,52 @@ NeverType::monomorphized_clone () const
// placeholder type
+PlaceholderType::PlaceholderType (std::string symbol, HirId ref,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::PLACEHOLDER,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ symbol (symbol)
+{}
+
+PlaceholderType::PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
+ std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ symbol (symbol)
+{}
+
+std::string
+PlaceholderType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+PlaceholderType::is_unit () const
+{
+ rust_assert (can_resolve ());
+ return resolve ()->is_unit ();
+}
+
+std::string
+PlaceholderType::get_symbol () const
+{
+ return symbol;
+}
+
+bool
+PlaceholderType::is_concrete () const
+{
+ if (!can_resolve ())
+ return true;
+
+ return resolve ()->is_concrete ();
+}
+
void
PlaceholderType::accept_vis (TyVisitor &vis)
{
@@ -2755,13 +3276,6 @@ PlaceholderType::as_string () const
+ ">";
}
-BaseType *
-PlaceholderType::unify (BaseType *other)
-{
- PlaceholderRules r (this);
- return r.unify (other);
-}
-
bool
PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2835,6 +3349,78 @@ PlaceholderType::is_equal (const BaseType &other) const
// Projection type
+ProjectionType::ProjectionType (
+ HirId ref, BaseType *base, const Resolver::TraitReference *trait, DefId item,
+ std::vector<SubstitutionParamMapping> subst_refs,
+ SubstitutionArgumentMappings generic_arguments, std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::PROJECTION,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
+ base (base), trait (trait), item (item)
+{}
+
+ProjectionType::ProjectionType (
+ HirId ref, HirId ty_ref, BaseType *base,
+ const Resolver::TraitReference *trait, DefId item,
+ std::vector<SubstitutionParamMapping> subst_refs,
+ SubstitutionArgumentMappings generic_arguments, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::PROJECTION,
+ {Resolver::CanonicalPath::create_empty (),
+ Linemap::predeclared_location ()},
+ refs),
+ SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
+ base (base), trait (trait), item (item)
+{}
+
+bool
+ProjectionType::is_unit () const
+{
+ return false;
+}
+
+std::string
+ProjectionType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+ProjectionType::needs_generic_substitutions () const
+{
+ return needs_substitution ();
+}
+
+bool
+ProjectionType::supports_substitutions () const
+{
+ return true;
+}
+
+bool
+ProjectionType::has_subsititions_defined () const
+{
+ return has_substitutions ();
+}
+
+const BaseType *
+ProjectionType::get () const
+{
+ return base;
+}
+BaseType *
+ProjectionType::get ()
+{
+ return base;
+}
+
+bool
+ProjectionType::is_concrete () const
+{
+ return base->is_concrete ();
+}
+
void
ProjectionType::accept_vis (TyVisitor &vis)
{
@@ -2853,12 +3439,6 @@ ProjectionType::as_string () const
return "<Projection=" + subst_as_string () + "::" + base->as_string () + ">";
}
-BaseType *
-ProjectionType::unify (BaseType *other)
-{
- return base->unify (other);
-}
-
bool
ProjectionType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2880,7 +3460,8 @@ ProjectionType::monomorphized_clone () const
}
ProjectionType *
-ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+ProjectionType::handle_substitions (
+ SubstitutionArgumentMappings &subst_mappings)
{
// // do we really need to substitute this?
// if (base->needs_generic_substitutions () || base->contains_type_parameters
@@ -2951,6 +3532,26 @@ ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
return projection;
}
+// DynObjectType
+
+DynamicObjectType::DynamicObjectType (
+ HirId ref, RustIdent ident, std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs)
+ : BaseType (ref, ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
+{}
+
+DynamicObjectType::DynamicObjectType (
+ HirId ref, HirId ty_ref, RustIdent ident,
+ std::vector<TypeBoundPredicate> specified_bounds, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
+{}
+
+bool
+DynamicObjectType::is_concrete () const
+{
+ return true;
+}
+
void
DynamicObjectType::accept_vis (TyVisitor &vis)
{
@@ -2969,13 +3570,6 @@ DynamicObjectType::as_string () const
return "dyn [" + raw_bounds_as_string () + "]";
}
-BaseType *
-DynamicObjectType::unify (BaseType *other)
-{
- DynamicRules r (this);
- return r.unify (other);
-}
-
bool
DynamicObjectType::can_eq (const BaseType *other, bool emit_errors) const
{
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 0fd664c..64b9379 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -20,11 +20,12 @@
#define RUST_TYTY
#include "rust-hir-map.h"
-#include "rust-hir-full.h"
-#include "rust-diagnostics.h"
-#include "rust-abi.h"
#include "rust-common.h"
#include "rust-identifier.h"
+#include "rust-abi.h"
+#include "rust-tyty-bounds.h"
+#include "rust-tyty-util.h"
+#include "rust-tyty-subst.h"
namespace Rust {
@@ -76,65 +77,6 @@ public:
static std::string to_string (TypeKind kind);
};
-class BaseType;
-class TypeBoundPredicate;
-class TypeBoundPredicateItem
-{
-public:
- TypeBoundPredicateItem (const TypeBoundPredicate *parent,
- const Resolver::TraitItemReference *trait_item_ref)
- : parent (parent), trait_item_ref (trait_item_ref)
- {}
-
- static TypeBoundPredicateItem error ()
- {
- return TypeBoundPredicateItem (nullptr, nullptr);
- }
-
- bool is_error () const
- {
- return parent == nullptr || trait_item_ref == nullptr;
- }
-
- BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
-
- const Resolver::TraitItemReference *get_raw_item () const;
-
- bool needs_implementation () const;
-
- const TypeBoundPredicate *get_parent () const { return parent; }
-
- Location get_locus () const;
-
-private:
- const TypeBoundPredicate *parent;
- const Resolver::TraitItemReference *trait_item_ref;
-};
-
-class TypeBoundsMappings
-{
-protected:
- TypeBoundsMappings (std::vector<TypeBoundPredicate> specified_bounds);
-
-public:
- std::vector<TypeBoundPredicate> &get_specified_bounds ();
-
- const std::vector<TypeBoundPredicate> &get_specified_bounds () const;
-
- size_t num_specified_bounds () const;
-
- std::string raw_bounds_as_string () const;
-
- std::string bounds_as_string () const;
-
- std::string raw_bounds_as_name () const;
-
-protected:
- void add_bound (TypeBoundPredicate predicate);
-
- std::vector<TypeBoundPredicate> specified_bounds;
-};
-
extern void
set_cmp_autoderef_mode ();
extern void
@@ -145,20 +87,15 @@ class TyConstVisitor;
class BaseType : public TypeBoundsMappings
{
public:
- virtual ~BaseType () {}
+ virtual ~BaseType ();
- HirId get_ref () const { return ref; }
+ HirId get_ref () const;
- void set_ref (HirId id)
- {
- if (id != ref)
- append_reference (ref);
- ref = id;
- }
+ void set_ref (HirId id);
- HirId get_ty_ref () const { return ty_ref; }
+ HirId get_ty_ref () const;
- void set_ty_ref (HirId id) { ty_ref = id; }
+ void set_ty_ref (HirId id);
virtual void accept_vis (TyVisitor &vis) = 0;
@@ -168,11 +105,6 @@ public:
virtual std::string get_name () const = 0;
- // Unify two types. Returns a pointer to the newly-created unified ty, or
- // nullptr if the two ty cannot be unified. The caller is responsible for
- // releasing the memory of the returned ty.
- virtual BaseType *unify (BaseType *other) = 0;
-
// similar to unify but does not actually perform type unification but
// determines whether they are compatible. Consider the following
//
@@ -189,10 +121,7 @@ public:
// ty are considered equal if they're of the same kind, and
// 1. (For ADTs, arrays, tuples, refs) have the same underlying ty
// 2. (For functions) have the same signature
- virtual bool is_equal (const BaseType &other) const
- {
- return get_kind () == other.get_kind ();
- }
+ virtual bool is_equal (const BaseType &other) const;
bool satisfies_bound (const TypeBoundPredicate &predicate) const;
@@ -204,11 +133,11 @@ public:
void inherit_bounds (
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
- virtual bool is_unit () const { return false; }
+ virtual bool is_unit () const;
virtual bool is_concrete () const = 0;
- TypeKind get_kind () const { return kind; }
+ TypeKind get_kind () const;
/* Returns a pointer to a clone of this. The caller is responsible for
* releasing the memory of the returned ty. */
@@ -218,22 +147,19 @@ public:
virtual BaseType *monomorphized_clone () const = 0;
// get_combined_refs returns the chain of node refs involved in unification
- std::set<HirId> get_combined_refs () const { return combined; }
+ std::set<HirId> get_combined_refs () const;
- void append_reference (HirId id) { combined.insert (id); }
+ void append_reference (HirId id);
- virtual bool supports_substitutions () const { return false; }
+ virtual bool supports_substitutions () const;
- virtual bool has_subsititions_defined () const { return false; }
+ virtual bool has_subsititions_defined () const;
- virtual bool can_substitute () const
- {
- return supports_substitutions () && has_subsititions_defined ();
- }
+ virtual bool can_substitute () const;
- virtual bool needs_generic_substitutions () const { return false; }
+ virtual bool needs_generic_substitutions () const;
- bool contains_type_parameters () const { return !is_concrete (); }
+ bool contains_type_parameters () const;
std::string mappings_str () const;
@@ -246,26 +172,20 @@ public:
// This will get the monomorphized type from Params, Placeholders or
// Projections if available or error
+ BaseType *destructure ();
const BaseType *destructure () const;
- const RustIdent &get_ident () const { return ident; }
+ const RustIdent &get_ident () const;
- Location get_locus () const { return ident.locus; }
+ Location get_locus () const;
protected:
BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
- std::set<HirId> refs = std::set<HirId> ())
- : TypeBoundsMappings ({}), kind (kind), ref (ref), ty_ref (ty_ref),
- combined (refs), ident (ident), mappings (Analysis::Mappings::get ())
- {}
+ std::set<HirId> refs = std::set<HirId> ());
BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
std::vector<TypeBoundPredicate> specified_bounds,
- std::set<HirId> refs = std::set<HirId> ())
- : TypeBoundsMappings (specified_bounds), kind (kind), ref (ref),
- ty_ref (ty_ref), combined (refs), ident (ident),
- mappings (Analysis::Mappings::get ())
- {}
+ std::set<HirId> refs = std::set<HirId> ());
TypeKind kind;
HirId ref;
@@ -276,43 +196,6 @@ protected:
Analysis::Mappings *mappings;
};
-// this is a placeholder for types that can change like inference variables
-class TyVar
-{
-public:
- explicit TyVar (HirId ref);
-
- HirId get_ref () const { return ref; }
-
- BaseType *get_tyty () const;
-
- TyVar clone () const;
-
- TyVar monomorphized_clone () const;
-
- static TyVar get_implicit_infer_var (Location locus);
-
- static TyVar subst_covariant_var (TyTy::BaseType *orig,
- TyTy::BaseType *subst);
-
-private:
- HirId ref;
-};
-
-class TyWithLocation
-{
-public:
- explicit TyWithLocation (BaseType *ty, Location locus);
- explicit TyWithLocation (BaseType *ty);
-
- BaseType *get_ty () const { return ty; }
- Location get_locus () const { return locus; }
-
-private:
- BaseType *ty;
- Location locus;
-};
-
class InferType : public BaseType
{
public:
@@ -324,38 +207,28 @@ public:
};
InferType (HirId ref, InferTypeKind infer_kind, Location locus,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::INFER,
- {Resolver::CanonicalPath::create_empty (), locus}, refs),
- infer_kind (infer_kind)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind, Location locus,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::INFER,
- {Resolver::CanonicalPath::create_empty (), locus}, refs),
- infer_kind (infer_kind)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
-
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- InferTypeKind get_infer_kind () const { return infer_kind; }
+ InferTypeKind get_infer_kind () const;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
bool default_type (BaseType **type) const;
- bool is_concrete () const final override { return true; }
+ bool is_concrete () const final override;
private:
InferTypeKind infer_kind;
@@ -364,66 +237,46 @@ private:
class ErrorType : public BaseType
{
public:
- ErrorType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::ERROR,
- {Resolver::CanonicalPath::create_empty (), Location ()}, refs)
- {}
+ ErrorType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
- ErrorType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::ERROR,
- {Resolver::CanonicalPath::create_empty (), Location ()}, refs)
- {}
+ ErrorType (HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
- bool is_unit () const override { return true; }
+ bool is_unit () const override;
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
- bool is_concrete () const final override { return false; }
+ bool is_concrete () const final override;
};
-class SubstitutionArgumentMappings;
class ParamType : public BaseType
{
public:
ParamType (std::string symbol, Location locus, HirId ref,
HIR::GenericParam &param,
std::vector<TypeBoundPredicate> specified_bounds,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::PARAM,
- {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
- locus},
- specified_bounds, refs),
- symbol (symbol), param (param)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
- ParamType (std::string symbol, Location locus, HirId ref, HirId ty_ref,
- HIR::GenericParam &param,
+ ParamType (bool is_trait_self, std::string symbol, Location locus, HirId ref,
+ HirId ty_ref, HIR::GenericParam &param,
std::vector<TypeBoundPredicate> specified_bounds,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::PARAM,
- {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
- locus},
- specified_bounds, refs),
- symbol (symbol), param (param)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
@@ -431,9 +284,9 @@ public:
std::string get_symbol () const;
- HIR::GenericParam &get_generic_param () { return param; }
+ HIR::GenericParam &get_generic_param ();
- bool can_resolve () const { return get_ref () != get_ty_ref (); }
+ bool can_resolve () const;
BaseType *resolve () const;
@@ -441,18 +294,15 @@ public:
bool is_equal (const BaseType &other) const override;
- bool is_concrete () const override final
- {
- auto r = resolve ();
- if (r == this)
- return false;
+ bool is_concrete () const override final;
- return r->is_concrete ();
- }
+ ParamType *handle_substitions (SubstitutionArgumentMappings &mappings);
- ParamType *handle_substitions (SubstitutionArgumentMappings mappings);
+ void set_implicit_self_trait ();
+ bool is_implicit_self_trait () const;
private:
+ bool is_trait_self;
std::string symbol;
HIR::GenericParam &param;
};
@@ -460,31 +310,25 @@ private:
class StructFieldType
{
public:
- StructFieldType (HirId ref, std::string name, BaseType *ty, Location locus)
- : ref (ref), name (name), ty (ty), locus (locus)
- {}
+ StructFieldType (HirId ref, std::string name, BaseType *ty, Location locus);
- HirId get_ref () const { return ref; }
-
- std::string as_string () const;
+ HirId get_ref () const;
bool is_equal (const StructFieldType &other) const;
- std::string get_name () const { return name; }
-
- BaseType *get_field_type () const { return ty; }
+ std::string get_name () const;
- void set_field_type (BaseType *fty) { ty = fty; }
+ BaseType *get_field_type () const;
+ void set_field_type (BaseType *fty);
StructFieldType *clone () const;
-
StructFieldType *monomorphized_clone () const;
- bool is_concrete () const { return ty->is_concrete (); }
-
- void debug () const { rust_debug ("%s", as_string ().c_str ()); }
+ bool is_concrete () const;
- Location get_locus () const { return locus; }
+ void debug () const;
+ Location get_locus () const;
+ std::string as_string () const;
private:
HirId ref;
@@ -498,496 +342,44 @@ class TupleType : public BaseType
public:
TupleType (HirId ref, Location locus,
std::vector<TyVar> fields = std::vector<TyVar> (),
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::TUPLE,
- {Resolver::CanonicalPath::create_empty (), locus}, refs),
- fields (fields)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
TupleType (HirId ref, HirId ty_ref, Location locus,
std::vector<TyVar> fields = std::vector<TyVar> (),
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::TUPLE,
- {Resolver::CanonicalPath::create_empty (), locus}, refs),
- fields (fields)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
- static TupleType *get_unit_type (HirId ref)
- {
- return new TupleType (ref, Linemap::predeclared_location ());
- }
+ static TupleType *get_unit_type (HirId ref);
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
- bool is_unit () const override { return this->fields.empty (); }
+ bool is_unit () const override;
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
- size_t num_fields () const { return fields.size (); }
+ size_t num_fields () const;
BaseType *get_field (size_t index) const;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final
- {
- for (size_t i = 0; i < num_fields (); i++)
- {
- if (!get_field (i)->is_concrete ())
- return false;
- }
- return true;
- }
+ bool is_concrete () const override final;
- const std::vector<TyVar> &get_fields () const { return fields; }
+ const std::vector<TyVar> &get_fields () const;
std::string get_name () const override final;
- TupleType *handle_substitions (SubstitutionArgumentMappings mappings);
+ TupleType *handle_substitions (SubstitutionArgumentMappings &mappings);
private:
std::vector<TyVar> fields;
};
-class SubstitutionParamMapping
-{
-public:
- SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param)
- : generic (generic), param (param)
- {}
-
- SubstitutionParamMapping (const SubstitutionParamMapping &other)
- : generic (other.generic), param (other.param)
- {}
-
- std::string as_string () const
- {
- if (param == nullptr)
- return "nullptr";
-
- return param->get_name ();
- }
-
- bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
- Location locus);
-
- SubstitutionParamMapping clone () const
- {
- return SubstitutionParamMapping (generic, static_cast<ParamType *> (
- param->clone ()));
- }
-
- ParamType *get_param_ty () { return param; }
-
- const ParamType *get_param_ty () const { return param; }
-
- const HIR::TypeParam &get_generic_param () { return generic; };
-
- // 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
- void override_context ();
-
- bool needs_substitution () const
- {
- return !(get_param_ty ()->is_concrete ());
- }
-
- Location get_param_locus () const { return generic.get_locus (); }
-
- bool param_has_default_ty () const { return generic.has_type (); }
-
- BaseType *get_default_ty () const
- {
- TyVar var (generic.get_type_mappings ().get_hirid ());
- return var.get_tyty ();
- }
-
- bool need_substitution () const;
-
-private:
- const HIR::TypeParam &generic;
- ParamType *param;
-};
-
-class SubstitutionArg
-{
-public:
- SubstitutionArg (const SubstitutionParamMapping *param, BaseType *argument)
- : param (param), argument (argument)
- {}
-
- // FIXME
- // the copy constructors need removed - they are unsafe see
- // TypeBoundPredicate
- SubstitutionArg (const SubstitutionArg &other)
- : param (other.param), argument (other.argument)
- {}
-
- SubstitutionArg &operator= (const SubstitutionArg &other)
- {
- param = other.param;
- argument = other.argument;
- return *this;
- }
-
- BaseType *get_tyty () { return argument; }
-
- const BaseType *get_tyty () const { return argument; }
-
- const SubstitutionParamMapping *get_param_mapping () const { return param; }
-
- static SubstitutionArg error () { return SubstitutionArg (nullptr, nullptr); }
-
- bool is_error () const { return param == nullptr || argument == nullptr; }
-
- bool is_conrete () const
- {
- if (argument != nullptr)
- return true;
-
- if (argument->get_kind () == TyTy::TypeKind::PARAM)
- return false;
-
- return argument->is_concrete ();
- }
-
- std::string as_string () const
- {
- return param->as_string ()
- + (argument != nullptr ? ":" + argument->as_string () : "");
- }
-
-private:
- const SubstitutionParamMapping *param;
- BaseType *argument;
-};
-
-typedef std::function<void (const ParamType &, const SubstitutionArg &)>
- ParamSubstCb;
-class SubstitutionArgumentMappings
-{
-public:
- SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
- Location locus,
- ParamSubstCb param_subst_cb = nullptr,
- bool trait_item_flag = false)
- : mappings (mappings), locus (locus), param_subst_cb (param_subst_cb),
- trait_item_flag (trait_item_flag)
- {}
-
- SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other)
- : mappings (other.mappings), locus (other.locus),
- param_subst_cb (other.param_subst_cb),
- trait_item_flag (other.trait_item_flag)
- {}
-
- SubstitutionArgumentMappings &
- operator= (const SubstitutionArgumentMappings &other)
- {
- mappings = other.mappings;
- locus = other.locus;
- param_subst_cb = other.param_subst_cb;
- trait_item_flag = other.trait_item_flag;
-
- return *this;
- }
-
- SubstitutionArgumentMappings (SubstitutionArgumentMappings &&other) = default;
- SubstitutionArgumentMappings &operator= (SubstitutionArgumentMappings &&other)
- = default;
-
- static SubstitutionArgumentMappings error ()
- {
- return SubstitutionArgumentMappings ({}, Location (), nullptr, false);
- }
-
- bool is_error () const { return mappings.size () == 0; }
-
- bool get_argument_for_symbol (const ParamType *param_to_find,
- SubstitutionArg *argument)
- {
- for (auto &mapping : mappings)
- {
- const SubstitutionParamMapping *param = mapping.get_param_mapping ();
- const ParamType *p = param->get_param_ty ();
-
- if (p->get_symbol ().compare (param_to_find->get_symbol ()) == 0)
- {
- *argument = mapping;
- return true;
- }
- }
- return false;
- }
-
- bool get_argument_at (size_t index, SubstitutionArg *argument)
- {
- if (index > mappings.size ())
- return false;
-
- *argument = mappings.at (index);
- return true;
- }
-
- // is_concrete means if the used args is non error, ie: non empty this will
- // verify if actual real types have been put in place of are they still
- // ParamTy
- bool is_concrete () const
- {
- for (auto &mapping : mappings)
- {
- if (!mapping.is_conrete ())
- return false;
- }
- return true;
- }
-
- Location get_locus () const { return locus; }
-
- size_t size () const { return mappings.size (); }
-
- bool is_empty () const { return size () == 0; }
-
- std::vector<SubstitutionArg> &get_mappings () { return mappings; }
-
- const std::vector<SubstitutionArg> &get_mappings () const { return mappings; }
-
- std::string as_string () const
- {
- std::string buffer;
- for (auto &mapping : mappings)
- {
- buffer += mapping.as_string () + ", ";
- }
- return "<" + buffer + ">";
- }
-
- void on_param_subst (const ParamType &p, const SubstitutionArg &a) const
- {
- if (param_subst_cb == nullptr)
- return;
-
- param_subst_cb (p, a);
- }
-
- ParamSubstCb get_subst_cb () const { return param_subst_cb; }
-
- bool trait_item_mode () const { return trait_item_flag; }
-
-private:
- std::vector<SubstitutionArg> mappings;
- Location locus;
- ParamSubstCb param_subst_cb;
- bool trait_item_flag;
-};
-
-class SubstitutionRef
-{
-public:
- SubstitutionRef (std::vector<SubstitutionParamMapping> substitutions,
- SubstitutionArgumentMappings arguments)
- : substitutions (substitutions), used_arguments (arguments)
- {}
-
- bool has_substitutions () const { return substitutions.size () > 0; }
-
- std::string subst_as_string () const
- {
- std::string buffer;
- for (size_t i = 0; i < substitutions.size (); i++)
- {
- const SubstitutionParamMapping &sub = substitutions.at (i);
- buffer += sub.as_string ();
-
- if ((i + 1) < substitutions.size ())
- buffer += ", ";
- }
-
- return buffer.empty () ? "" : "<" + buffer + ">";
- }
-
- size_t get_num_substitutions () const { return substitutions.size (); }
-
- std::vector<SubstitutionParamMapping> &get_substs () { return substitutions; }
-
- const std::vector<SubstitutionParamMapping> &get_substs () const
- {
- return substitutions;
- }
-
- std::vector<SubstitutionParamMapping> clone_substs () const
- {
- std::vector<SubstitutionParamMapping> clone;
-
- for (auto &sub : substitutions)
- clone.push_back (sub.clone ());
-
- return clone;
- }
-
- void override_context ()
- {
- for (auto &sub : substitutions)
- {
- sub.override_context ();
- }
- }
-
- bool needs_substitution () const
- {
- for (auto &sub : substitutions)
- {
- if (sub.need_substitution ())
- return true;
- }
- return false;
- }
-
- bool was_substituted () const { return !needs_substitution (); }
-
- SubstitutionArgumentMappings get_substitution_arguments () const
- {
- return used_arguments;
- }
-
- // this is the count of type params that are not substituted fuly
- size_t num_required_substitutions () const
- {
- size_t n = 0;
- for (auto &p : substitutions)
- {
- if (p.needs_substitution ())
- n++;
- }
- return n;
- }
-
- // this is the count of type params that need substituted taking into account
- // possible defaults
- size_t min_required_substitutions () const
- {
- size_t n = 0;
- for (auto &p : substitutions)
- {
- if (p.needs_substitution () && !p.param_has_default_ty ())
- n++;
- }
- return n;
- }
-
- // We are trying to subst <i32, f32> into Struct Foo<X,Y> {}
- // in the case of Foo<i32,f32>{...}
- //
- // the substitions we have here define X,Y but the arguments have no bindings
- // so its a matter of ordering
- SubstitutionArgumentMappings
- get_mappings_from_generic_args (HIR::GenericArgs &args);
-
- // Recursive substitutions
- // Foo <A,B> { a:A, b: B}; Bar <X,Y,Z>{a:X, b: Foo<Y,Z>}
- //
- // we have bindings for X Y Z and need to propagate the binding Y,Z into Foo
- // Which binds to A,B
- SubstitutionArgumentMappings
- adjust_mappings_for_this (SubstitutionArgumentMappings &mappings);
-
- // Are the mappings here actually bound to this type. For example imagine the
- // case:
- //
- // struct Foo<T>(T);
- // impl<T> Foo<T> {
- // fn test(self) { ... }
- // }
- //
- // In this case we have a generic ADT of Foo and an impl block of a generic T
- // on Foo for the Self type. When we it comes to path resolution we can have:
- //
- // Foo::<i32>::test()
- //
- // This means the first segment of Foo::<i32> returns the ADT Foo<i32> not the
- // Self ADT bound to the T from the impl block. This means when it comes to
- // the next segment of test which resolves to the function we need to check
- // wether the arguments in the struct definition of foo can be bound here
- // before substituting the previous segments type here. This functions acts as
- // a guard for the solve_mappings_from_receiver_for_self to handle the case
- // where arguments are not bound. This is important for this next case:
- //
- // struct Baz<A, B>(A, B);
- // impl Baz<i32, f32> {
- // fn test<X>(a: X) -> X {
- // a
- // }
- // }
- //
- // In this case Baz has been already substituted for the impl's Self to become
- // ADT<i32, f32> so that the function test only has 1 generic argument of X.
- // The path for this will be:
- //
- // Baz::test::<_>(123)
- //
- // So the first segment here will be Baz<_, _> to try and infer the arguments
- // which will be taken from the impl's Self type in this case since it is
- // already substituted and like the previous case the check to see if we need
- // to inherit the previous segments generic arguments takes place but the
- // generic arguments are not bound to this type as they have already been
- // substituted.
- //
- // Its important to remember from the first example the FnType actually looks
- // like:
- //
- // fn <T>test(self :Foo<T>(T))
- //
- // As the generic parameters are "bound" to each of the items in the impl
- // block. So this check is about wether the arguments we have here can
- // actually be bound to this type.
- bool are_mappings_bound (SubstitutionArgumentMappings &mappings);
-
- // struct Foo<A, B>(A, B);
- //
- // impl<T> Foo<T, f32>;
- // -> fn test<X>(self, a: X) -> X
- //
- // We might invoke this via:
- //
- // a = Foo(123, 456f32);
- // b = a.test::<bool>(false);
- //
- // we need to figure out relevant generic arguemts for self to apply to the
- // fntype
- SubstitutionArgumentMappings solve_mappings_from_receiver_for_self (
- SubstitutionArgumentMappings &mappings) const;
-
- // TODO comment
- SubstitutionArgumentMappings
- solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to);
-
- // TODO comment
- BaseType *infer_substitions (Location locus);
-
- // TODO comment
- bool monomorphize ();
-
- // TODO comment
- virtual BaseType *handle_substitions (SubstitutionArgumentMappings mappings)
- = 0;
-
- SubstitutionArgumentMappings get_used_arguments () const
- {
- return used_arguments;
- }
-
-protected:
- std::vector<SubstitutionParamMapping> substitutions;
- SubstitutionArgumentMappings used_arguments;
-};
-
class TypeBoundPredicate : public SubstitutionRef
{
public:
@@ -1030,7 +422,7 @@ public:
// WARNING THIS WILL ALWAYS RETURN NULLPTR
BaseType *
- handle_substitions (SubstitutionArgumentMappings mappings) override final;
+ handle_substitions (SubstitutionArgumentMappings &mappings) override final;
bool is_error () const;
@@ -1040,6 +432,13 @@ public:
DefId get_id () const { return reference; }
+ std::vector<TypeBoundPredicateItem> get_associated_type_items ();
+
+ size_t get_num_associated_bindings () const override final;
+
+ TypeBoundPredicateItem
+ lookup_associated_type (const std::string &search) override final;
+
private:
DefId reference;
Location locus;
@@ -1057,185 +456,48 @@ public:
STRUCT
};
- static std::string variant_type_string (VariantType type)
- {
- switch (type)
- {
- case NUM:
- return "enumeral";
- case TUPLE:
- return "tuple";
- case STRUCT:
- return "struct";
- }
- gcc_unreachable ();
- return "";
- }
+ static std::string variant_type_string (VariantType type);
VariantDef (HirId id, DefId defid, std::string identifier, RustIdent ident,
- HIR::Expr *discriminant)
- : id (id), defid (defid), identifier (identifier), ident (ident),
- discriminant (discriminant)
-
- {
- type = VariantType::NUM;
- fields = {};
- }
+ HIR::Expr *discriminant);
VariantDef (HirId id, DefId defid, std::string identifier, RustIdent ident,
VariantType type, HIR::Expr *discriminant,
- std::vector<StructFieldType *> fields)
- : id (id), defid (defid), identifier (identifier), ident (ident),
- type (type), discriminant (discriminant), fields (fields)
- {
- rust_assert (
- (type == VariantType::NUM && fields.empty ())
- || (type == VariantType::TUPLE || type == VariantType::STRUCT));
- }
-
- VariantDef (const VariantDef &other)
- : id (other.id), defid (other.defid), identifier (other.identifier),
- ident (other.ident), type (other.type), discriminant (other.discriminant),
- fields (other.fields)
- {}
+ std::vector<StructFieldType *> fields);
- VariantDef &operator= (const VariantDef &other)
- {
- id = other.id;
- identifier = other.identifier;
- type = other.type;
- discriminant = other.discriminant;
- fields = other.fields;
- ident = other.ident;
-
- return *this;
- }
-
- static VariantDef &get_error_node ()
- {
- static VariantDef node
- = VariantDef (UNKNOWN_HIRID, UNKNOWN_DEFID, "",
- {Resolver::CanonicalPath::create_empty (),
- Linemap::unknown_location ()},
- nullptr);
+ VariantDef (const VariantDef &other);
- return node;
- }
+ VariantDef &operator= (const VariantDef &other);
- bool is_error () const { return get_id () == UNKNOWN_HIRID; }
+ static VariantDef &get_error_node ();
+ bool is_error () const;
- HirId get_id () const { return id; }
- DefId get_defid () const { return defid; }
+ HirId get_id () const;
+ DefId get_defid () const;
- VariantType get_variant_type () const { return type; }
- bool is_data_variant () const { return type != VariantType::NUM; }
- bool is_dataless_variant () const { return type == VariantType::NUM; }
+ VariantType get_variant_type () const;
+ bool is_data_variant () const;
+ bool is_dataless_variant () const;
- std::string get_identifier () const { return identifier; }
+ std::string get_identifier () const;
- size_t num_fields () const { return fields.size (); }
- StructFieldType *get_field_at_index (size_t index)
- {
- rust_assert (index < fields.size ());
- return fields.at (index);
- }
+ size_t num_fields () const;
+ StructFieldType *get_field_at_index (size_t index);
- std::vector<StructFieldType *> &get_fields ()
- {
- rust_assert (type != NUM);
- return fields;
- }
+ std::vector<StructFieldType *> &get_fields ();
bool lookup_field (const std::string &lookup, StructFieldType **field_lookup,
- size_t *index) const
- {
- size_t i = 0;
- for (auto &field : fields)
- {
- if (field->get_name ().compare (lookup) == 0)
- {
- if (index != nullptr)
- *index = i;
-
- if (field_lookup != nullptr)
- *field_lookup = field;
-
- return true;
- }
- i++;
- }
- return false;
- }
+ size_t *index) const;
- HIR::Expr *get_discriminant () const
- {
- rust_assert (discriminant != nullptr);
- return discriminant;
- }
-
- std::string as_string () const
- {
- if (type == VariantType::NUM)
- return identifier + " = " + discriminant->as_string ();
-
- std::string buffer;
- for (size_t i = 0; i < fields.size (); ++i)
- {
- buffer += fields.at (i)->as_string ();
- if ((i + 1) < fields.size ())
- buffer += ", ";
- }
-
- if (type == VariantType::TUPLE)
- return identifier + " (" + buffer + ")";
- else
- return identifier + " {" + buffer + "}";
- }
-
- bool is_equal (const VariantDef &other) const
- {
- if (type != other.type)
- return false;
-
- if (identifier.compare (other.identifier) != 0)
- return false;
-
- if (discriminant != other.discriminant)
- return false;
+ HIR::Expr *get_discriminant () const;
- if (fields.size () != other.fields.size ())
- return false;
-
- for (size_t i = 0; i < fields.size (); i++)
- {
- if (!fields.at (i)->is_equal (*other.fields.at (i)))
- return false;
- }
-
- return true;
- }
-
- VariantDef *clone () const
- {
- std::vector<StructFieldType *> cloned_fields;
- for (auto &f : fields)
- cloned_fields.push_back ((StructFieldType *) f->clone ());
-
- return new VariantDef (id, defid, identifier, ident, type, discriminant,
- cloned_fields);
- }
-
- VariantDef *monomorphized_clone () const
- {
- std::vector<StructFieldType *> cloned_fields;
- for (auto &f : fields)
- cloned_fields.push_back ((StructFieldType *) f->monomorphized_clone ());
+ std::string as_string () const;
- return new VariantDef (id, defid, identifier, ident, type, discriminant,
- cloned_fields);
- }
+ bool is_equal (const VariantDef &other) const;
+ VariantDef *clone () const;
+ VariantDef *monomorphized_clone () const;
- const RustIdent &get_ident () const { return ident; }
+ const RustIdent &get_ident () const;
private:
HirId id;
@@ -1331,7 +593,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -1415,7 +676,7 @@ public:
}
ADTType *
- handle_substitions (SubstitutionArgumentMappings mappings) override final;
+ handle_substitions (SubstitutionArgumentMappings &mappings) override final;
private:
std::string identifier;
@@ -1471,7 +732,6 @@ public:
std::string get_identifier () const { return identifier; }
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -1548,7 +808,7 @@ public:
}
FnType *
- handle_substitions (SubstitutionArgumentMappings mappings) override final;
+ handle_substitions (SubstitutionArgumentMappings &mappings) override final;
ABI get_abi () const { return abi; }
@@ -1591,7 +851,6 @@ public:
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -1671,7 +930,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final { return as_string (); }
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -1698,7 +956,7 @@ public:
}
ClosureType *
- handle_substitions (SubstitutionArgumentMappings mappings) override final;
+ handle_substitions (SubstitutionArgumentMappings &mappings) override final;
TyTy::TupleType &get_parameters () const { return *parameters; }
TyTy::BaseType &get_result_type () const { return *result_type.get_tyty (); }
@@ -1740,7 +998,6 @@ public:
std::string get_name () const override final { return as_string (); }
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -1757,7 +1014,7 @@ public:
HIR::Expr &get_capacity_expr () const { return capacity_expr; }
- ArrayType *handle_substitions (SubstitutionArgumentMappings mappings);
+ ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings);
private:
TyVar element_type;
@@ -1788,7 +1045,6 @@ public:
std::string get_name () const override final { return as_string (); }
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -1803,7 +1059,7 @@ public:
return get_element_type ()->is_concrete ();
}
- SliceType *handle_substitions (SubstitutionArgumentMappings mappings);
+ SliceType *handle_substitions (SubstitutionArgumentMappings &mappings);
private:
TyVar element_type;
@@ -1812,33 +1068,21 @@ private:
class BoolType : public BaseType
{
public:
- BoolType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::BOOL,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
-
- BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::BOOL,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
+ BoolType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+ BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
};
class IntType : public BaseType
@@ -1853,40 +1097,26 @@ public:
I128
};
- IntType (HirId ref, IntKind kind, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::INT,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- int_kind (kind)
- {}
-
+ IntType (HirId ref, IntKind kind, std::set<HirId> refs = std::set<HirId> ());
IntType (HirId ref, HirId ty_ref, IntKind kind,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::INT,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- int_kind (kind)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- IntKind get_int_kind () const { return int_kind; }
+ IntKind get_int_kind () const;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
bool is_equal (const BaseType &other) const override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
private:
IntKind int_kind;
@@ -1904,40 +1134,27 @@ public:
U128
};
- UintType (HirId ref, UintKind kind, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::UINT,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- uint_kind (kind)
- {}
-
+ UintType (HirId ref, UintKind kind,
+ std::set<HirId> refs = std::set<HirId> ());
UintType (HirId ref, HirId ty_ref, UintKind kind,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::UINT,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- uint_kind (kind)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- UintKind get_uint_kind () const { return uint_kind; }
+ UintKind get_uint_kind () const;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
bool is_equal (const BaseType &other) const override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
private:
UintKind uint_kind;
@@ -1953,40 +1170,25 @@ public:
};
FloatType (HirId ref, FloatKind kind,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::FLOAT,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- float_kind (kind)
- {}
-
+ std::set<HirId> refs = std::set<HirId> ());
FloatType (HirId ref, HirId ty_ref, FloatKind kind,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::FLOAT,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- float_kind (kind)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
+ std::string get_name () const override final;
- std::string get_name () const override final { return as_string (); }
-
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- FloatKind get_float_kind () const { return float_kind; }
+ FloatKind get_float_kind () const;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
bool is_equal (const BaseType &other) const override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
private:
FloatKind float_kind;
@@ -1995,153 +1197,91 @@ private:
class USizeType : public BaseType
{
public:
- USizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::USIZE,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
-
- USizeType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::USIZE,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
+ USizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+ USizeType (HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
+ std::string get_name () const override final;
- std::string get_name () const override final { return as_string (); }
-
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
};
class ISizeType : public BaseType
{
public:
- ISizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::ISIZE,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
-
- ISizeType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::ISIZE,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
+ ISizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+ ISizeType (HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
+ std::string get_name () const override final;
- std::string get_name () const override final { return as_string (); }
-
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
};
class CharType : public BaseType
{
public:
- CharType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::CHAR,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
-
- CharType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::CHAR,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
+ CharType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+ CharType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
+ std::string get_name () const override final;
- std::string get_name () const override final { return as_string (); }
-
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
};
class StrType : public BaseType
{
public:
- StrType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::STR,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
-
- StrType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::STR,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
+ StrType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+ StrType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
};
class ReferenceType : public BaseType
{
public:
ReferenceType (HirId ref, TyVar base, Mutability mut,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::REF,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- base (base), mut (mut)
- {}
-
+ std::set<HirId> refs = std::set<HirId> ());
ReferenceType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::REF,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- base (base), mut (mut)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
BaseType *get_base () const;
@@ -2152,7 +1292,6 @@ public:
std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -2160,45 +1299,19 @@ public:
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final
- {
- return get_base ()->is_concrete ();
- }
-
- ReferenceType *handle_substitions (SubstitutionArgumentMappings mappings);
+ bool is_concrete () const override final;
- Mutability mutability () const { return mut; }
+ ReferenceType *handle_substitions (SubstitutionArgumentMappings &mappings);
- bool is_mutable () const { return mut == Mutability::Mut; }
+ Mutability mutability () const;
- bool is_dyn_object () const
- {
- return is_dyn_slice_type () || is_dyn_str_type ();
- }
+ bool is_mutable () const;
- bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const
- {
- const TyTy::BaseType *element = get_base ()->destructure ();
- if (element->get_kind () != TyTy::TypeKind::SLICE)
- return false;
- if (slice == nullptr)
- return true;
+ bool is_dyn_object () const;
- *slice = static_cast<const TyTy::SliceType *> (element);
- return true;
- }
+ bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const;
- bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const
- {
- const TyTy::BaseType *element = get_base ()->destructure ();
- if (element->get_kind () != TyTy::TypeKind::STR)
- return false;
- if (str == nullptr)
- return true;
-
- *str = static_cast<const TyTy::StrType *> (element);
- return true;
- }
+ bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const;
private:
TyVar base;
@@ -2209,22 +1322,9 @@ class PointerType : public BaseType
{
public:
PointerType (HirId ref, TyVar base, Mutability mut,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::POINTER,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- base (base), mut (mut)
- {}
-
+ std::set<HirId> refs = std::set<HirId> ());
PointerType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::POINTER,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- base (base), mut (mut)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
BaseType *get_base () const;
@@ -2234,7 +1334,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -2242,47 +1341,17 @@ public:
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- bool is_concrete () const override final
- {
- return get_base ()->is_concrete ();
- }
-
- PointerType *handle_substitions (SubstitutionArgumentMappings mappings);
-
- Mutability mutability () const { return mut; }
-
- bool is_mutable () const { return mut == Mutability::Mut; }
-
- bool is_const () const { return mut == Mutability::Imm; }
-
- bool is_dyn_object () const
- {
- return is_dyn_slice_type () || is_dyn_str_type ();
- }
-
- bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const
- {
- const TyTy::BaseType *element = get_base ()->destructure ();
- if (element->get_kind () != TyTy::TypeKind::SLICE)
- return false;
- if (slice == nullptr)
- return true;
+ bool is_concrete () const override final;
- *slice = static_cast<const TyTy::SliceType *> (element);
- return true;
- }
+ PointerType *handle_substitions (SubstitutionArgumentMappings &mappings);
- bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const
- {
- const TyTy::BaseType *element = get_base ()->destructure ();
- if (element->get_kind () != TyTy::TypeKind::STR)
- return false;
- if (str == nullptr)
- return true;
+ Mutability mutability () const;
+ bool is_mutable () const;
+ bool is_const () const;
+ bool is_dyn_object () const;
- *str = static_cast<const TyTy::StrType *> (element);
- return true;
- }
+ bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const;
+ bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const;
private:
TyVar base;
@@ -2302,35 +1371,24 @@ private:
class NeverType : public BaseType
{
public:
- NeverType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::NEVER,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
-
- NeverType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::NEVER,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs)
- {}
+ NeverType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+ NeverType (HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
- bool is_unit () const override { return true; }
- bool is_concrete () const override final { return true; }
+ bool is_unit () const override;
+ bool is_concrete () const override final;
};
// used at the type in associated types in traits
@@ -2339,43 +1397,25 @@ class PlaceholderType : public BaseType
{
public:
PlaceholderType (std::string symbol, HirId ref,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::PLACEHOLDER,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- symbol (symbol)
- {}
-
+ std::set<HirId> refs = std::set<HirId> ());
PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- symbol (symbol)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
- bool is_unit () const override
- {
- rust_assert (can_resolve ());
- return resolve ()->is_unit ();
- }
+ bool is_unit () const override;
- std::string get_symbol () const { return symbol; }
+ std::string get_symbol () const;
void set_associated_type (HirId ref);
@@ -2387,13 +1427,7 @@ public:
bool is_equal (const BaseType &other) const override;
- bool is_concrete () const override final
- {
- if (!can_resolve ())
- return true;
-
- return resolve ()->is_concrete ();
- }
+ bool is_concrete () const override final;
private:
std::string symbol;
@@ -2407,63 +1441,42 @@ public:
std::vector<SubstitutionParamMapping> subst_refs,
SubstitutionArgumentMappings generic_arguments
= SubstitutionArgumentMappings::error (),
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::PROJECTION,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
- base (base), trait (trait), item (item)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
ProjectionType (HirId ref, HirId ty_ref, BaseType *base,
const Resolver::TraitReference *trait, DefId item,
std::vector<SubstitutionParamMapping> subst_refs,
SubstitutionArgumentMappings generic_arguments
= SubstitutionArgumentMappings::error (),
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::PROJECTION,
- {Resolver::CanonicalPath::create_empty (),
- Linemap::predeclared_location ()},
- refs),
- SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
- base (base), trait (trait), item (item)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
- std::string get_name () const override final { return as_string (); }
+ std::string get_name () const override final;
- bool is_unit () const override { return false; }
+ bool is_unit () const override;
- bool needs_generic_substitutions () const override final
- {
- return needs_substitution ();
- }
+ bool needs_generic_substitutions () const override final;
- bool supports_substitutions () const override final { return true; }
+ bool supports_substitutions () const override final;
- bool has_subsititions_defined () const override final
- {
- return has_substitutions ();
- }
+ bool has_subsititions_defined () const override final;
- const BaseType *get () const { return base; }
- BaseType *get () { return base; }
+ const BaseType *get () const;
+ BaseType *get ();
- bool is_concrete () const override final { return base->is_concrete (); }
+ bool is_concrete () const override final;
ProjectionType *
- handle_substitions (SubstitutionArgumentMappings mappings) override final;
+ handle_substitions (SubstitutionArgumentMappings &mappings) override final;
private:
BaseType *base;
@@ -2476,22 +1489,17 @@ class DynamicObjectType : public BaseType
public:
DynamicObjectType (HirId ref, RustIdent ident,
std::vector<TypeBoundPredicate> specified_bounds,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
DynamicObjectType (HirId ref, HirId ty_ref, RustIdent ident,
std::vector<TypeBoundPredicate> specified_bounds,
- std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
- {}
+ std::set<HirId> refs = std::set<HirId> ());
void accept_vis (TyVisitor &vis) override;
void accept_vis (TyConstVisitor &vis) const override;
std::string as_string () const override;
- BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
bool is_equal (const BaseType &other) const override;
@@ -2501,7 +1509,7 @@ public:
std::string get_name () const override final;
- bool is_concrete () const override final { return true; }
+ bool is_concrete () const override final;
// this returns a flat list of items including super trait bounds
const std::vector<
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
new file mode 100644
index 0000000..cbbff8c
--- /dev/null
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -0,0 +1,1651 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-unify.h"
+
+namespace Rust {
+namespace Resolver {
+
+UnifyRules::UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+ Location locus, bool commit_flag, bool emit_error)
+ : lhs (lhs), rhs (rhs), locus (locus), commit_flag (commit_flag),
+ emit_error (emit_error), mappings (*Analysis::Mappings::get ()),
+ context (*TypeCheckContext::get ())
+{}
+
+TyTy::BaseType *
+UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+ Location locus, bool commit_flag, bool emit_error)
+{
+ UnifyRules r (lhs, rhs, locus, commit_flag, emit_error);
+ TyTy::BaseType *result = r.go ();
+
+ if (r.commit_flag)
+ r.commit (result);
+
+ bool failed = result->get_kind () == TyTy::TypeKind::ERROR;
+ if (failed && r.emit_error)
+ r.emit_type_mismatch ();
+
+ return result;
+}
+
+TyTy::BaseType *
+UnifyRules::get_base ()
+{
+ return lhs.get_ty ()->destructure ();
+}
+
+TyTy::BaseType *
+UnifyRules::get_other ()
+{
+ return rhs.get_ty ()->destructure ();
+}
+
+void
+UnifyRules::commit (TyTy::BaseType *resolved)
+{
+ resolved->append_reference (get_base ()->get_ref ());
+ resolved->append_reference (get_other ()->get_ref ());
+ for (auto ref : get_base ()->get_combined_refs ())
+ resolved->append_reference (ref);
+ for (auto ref : get_other ()->get_combined_refs ())
+ resolved->append_reference (ref);
+
+ get_other ()->append_reference (resolved->get_ref ());
+ get_other ()->append_reference (get_base ()->get_ref ());
+ get_base ()->append_reference (resolved->get_ref ());
+ get_base ()->append_reference (get_other ()->get_ref ());
+
+ bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER;
+ bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER;
+ bool results_is_non_general_infer_var
+ = (result_is_infer_var
+ && (static_cast<TyTy::InferType *> (resolved))->get_infer_kind ()
+ != TyTy::InferType::GENERAL);
+ if (result_resolved || results_is_non_general_infer_var)
+ {
+ for (auto &ref : resolved->get_combined_refs ())
+ {
+ TyTy::BaseType *ref_tyty = nullptr;
+ bool ok = context.lookup_type (ref, &ref_tyty);
+ if (!ok)
+ 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 ());
+ }
+ }
+ }
+}
+
+void
+UnifyRules::emit_type_mismatch () const
+{
+ TyTy::BaseType *expected = lhs.get_ty ();
+ TyTy::BaseType *expr = rhs.get_ty ();
+
+ RichLocation r (locus);
+ r.add_range (lhs.get_locus ());
+ r.add_range (rhs.get_locus ());
+ rust_error_at (r, "expected %<%s%> got %<%s%>",
+ expected->get_name ().c_str (), expr->get_name ().c_str ());
+}
+
+TyTy::BaseType *
+UnifyRules::go ()
+{
+ TyTy::BaseType *ltype = lhs.get_ty ();
+ TyTy::BaseType *rtype = rhs.get_ty ();
+
+ ltype = lhs.get_ty ()->destructure ();
+ rtype = rhs.get_ty ()->destructure ();
+
+ rust_debug ("unify::go ltype={%s} rtype={%s}", ltype->debug_str ().c_str (),
+ rtype->debug_str ().c_str ());
+
+ // check bounds
+ if (ltype->num_specified_bounds () > 0)
+ {
+ if (!ltype->bounds_compatible (*rtype, locus, true))
+ {
+ // already emitted an error
+ emit_error = false;
+ return new TyTy::ErrorType (0);
+ }
+ }
+
+ switch (ltype->get_kind ())
+ {
+ case TyTy::INFER:
+ return expect_inference_variable (static_cast<TyTy::InferType *> (ltype),
+ rtype);
+
+ case TyTy::ADT:
+ return expect_adt (static_cast<TyTy::ADTType *> (ltype), rtype);
+
+ case TyTy::STR:
+ return expect_str (static_cast<TyTy::StrType *> (ltype), rtype);
+
+ case TyTy::REF:
+ return expect_reference (static_cast<TyTy::ReferenceType *> (ltype),
+ rtype);
+
+ case TyTy::POINTER:
+ return expect_pointer (static_cast<TyTy::PointerType *> (ltype), rtype);
+
+ case TyTy::PARAM:
+ return expect_param (static_cast<TyTy::ParamType *> (ltype), rtype);
+
+ case TyTy::ARRAY:
+ return expect_array (static_cast<TyTy::ArrayType *> (ltype), rtype);
+
+ case TyTy::SLICE:
+ return expect_slice (static_cast<TyTy::SliceType *> (ltype), rtype);
+
+ case TyTy::FNDEF:
+ return expect_fndef (static_cast<TyTy::FnType *> (ltype), rtype);
+
+ case TyTy::FNPTR:
+ return expect_fnptr (static_cast<TyTy::FnPtr *> (ltype), rtype);
+
+ case TyTy::TUPLE:
+ return expect_tuple (static_cast<TyTy::TupleType *> (ltype), rtype);
+
+ case TyTy::BOOL:
+ return expect_bool (static_cast<TyTy::BoolType *> (ltype), rtype);
+
+ case TyTy::CHAR:
+ return expect_char (static_cast<TyTy::CharType *> (ltype), rtype);
+
+ case TyTy::INT:
+ return expect_int (static_cast<TyTy::IntType *> (ltype), rtype);
+
+ case TyTy::UINT:
+ return expect_uint (static_cast<TyTy::UintType *> (ltype), rtype);
+
+ case TyTy::FLOAT:
+ return expect_float (static_cast<TyTy::FloatType *> (ltype), rtype);
+
+ case TyTy::USIZE:
+ return expect_usize (static_cast<TyTy::USizeType *> (ltype), rtype);
+
+ case TyTy::ISIZE:
+ return expect_isize (static_cast<TyTy::ISizeType *> (ltype), rtype);
+
+ case TyTy::NEVER:
+ return expect_never (static_cast<TyTy::NeverType *> (ltype), rtype);
+
+ case TyTy::PLACEHOLDER:
+ return expect_placeholder (static_cast<TyTy::PlaceholderType *> (ltype),
+ rtype);
+
+ case TyTy::PROJECTION:
+ return expect_projection (static_cast<TyTy::ProjectionType *> (ltype),
+ rtype);
+
+ case TyTy::DYNAMIC:
+ return expect_dyn (static_cast<TyTy::DynamicObjectType *> (ltype), rtype);
+
+ case TyTy::CLOSURE:
+ return expect_closure (static_cast<TyTy::ClosureType *> (ltype), rtype);
+
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
+ TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ switch (ltype->get_infer_kind ())
+ {
+ case TyTy::InferType::InferTypeKind::GENERAL:
+ return rtype->clone ();
+
+ case TyTy::InferType::InferTypeKind::INTEGRAL: {
+ bool is_valid = r->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL
+ || r->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return rtype->clone ();
+ }
+ break;
+
+ case TyTy::InferType::InferTypeKind::FLOAT: {
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT
+ || r->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return rtype->clone ();
+ }
+ break;
+ }
+ }
+ break;
+
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::ISIZE: {
+ bool is_valid = (ltype->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::GENERAL)
+ || (ltype->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL);
+ if (is_valid)
+ return rtype->clone ();
+ }
+ break;
+
+ case TyTy::FLOAT: {
+ bool is_valid = (ltype->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::GENERAL)
+ || (ltype->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::FLOAT);
+ if (is_valid)
+ return rtype->clone ();
+ }
+ break;
+
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE: {
+ bool is_valid = (ltype->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ return rtype->clone ();
+ }
+ break;
+
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::ADT: {
+ TyTy::ADTType &type = *static_cast<TyTy::ADTType *> (rtype);
+ if (ltype->get_adt_kind () != type.get_adt_kind ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ if (ltype->get_identifier ().compare (type.get_identifier ()) != 0)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ if (ltype->number_of_variants () != type.number_of_variants ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ for (size_t i = 0; i < type.number_of_variants (); ++i)
+ {
+ TyTy::VariantDef *a = ltype->get_variants ().at (i);
+ TyTy::VariantDef *b = type.get_variants ().at (i);
+
+ if (a->num_fields () != b->num_fields ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ for (size_t j = 0; j < a->num_fields (); j++)
+ {
+ TyTy::StructFieldType *base_field = a->get_field_at_index (j);
+ TyTy::StructFieldType *other_field = b->get_field_at_index (j);
+
+ TyTy::BaseType *this_field_ty = base_field->get_field_type ();
+ 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 */);
+ if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+ }
+ }
+
+ // generic args for the unit-struct case
+ if (type.is_unit () && ltype->is_unit ())
+ {
+ rust_assert (type.get_num_substitutions ()
+ == ltype->get_num_substitutions ());
+
+ for (size_t i = 0; i < type.get_num_substitutions (); i++)
+ {
+ auto &a = ltype->get_substs ().at (i);
+ auto &b = type.get_substs ().at (i);
+
+ 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 */);
+ if (res->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+ }
+ }
+
+ return type.clone ();
+ }
+ break;
+
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ 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::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::STR:
+ return rtype->clone ();
+
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ 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::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::REF: {
+ TyTy::ReferenceType &type = *static_cast<TyTy::ReferenceType *> (rtype);
+ auto base_type = ltype->get_base ();
+ 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 */);
+ if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ // rust is permissive about mutablity here you can always go from
+ // mutable to immutable but not the otherway round
+ bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true;
+ if (!mutability_ok)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ return new TyTy::ReferenceType (ltype->get_ref (), ltype->get_ty_ref (),
+ TyTy::TyVar (base_resolved->get_ref ()),
+ ltype->mutability ());
+ }
+ break;
+
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ 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::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::POINTER: {
+ TyTy::PointerType &type = *static_cast<TyTy::PointerType *> (rtype);
+ auto base_type = ltype->get_base ();
+ 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 */);
+ if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ // rust is permissive about mutablity here you can always go from
+ // mutable to immutable but not the otherway round
+ bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true;
+ if (!mutability_ok)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ return new TyTy::PointerType (ltype->get_ref (), ltype->get_ty_ref (),
+ TyTy::TyVar (base_resolved->get_ref ()),
+ ltype->mutability ());
+ }
+ break;
+
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ 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::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::PARAM: {
+ TyTy::ParamType &type = *static_cast<TyTy::ParamType *> (rtype);
+ // bool symbol_matches
+ // = ltype->get_symbol ().compare (type.get_symbol ()) == 0;
+ // // TODO
+ // // I think rustc checks a debruinj index
+ // if (symbol_matches)
+ // {
+ // return type.clone ();
+ // }
+
+ // matching symbol is not going to work when we mix symbol's and have
+ // nested generics
+
+ // bounds match? FIXME
+
+ return type.clone ();
+ }
+ break;
+
+ case TyTy::POINTER:
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ 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::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::ARRAY: {
+ TyTy::ArrayType &type = *static_cast<TyTy::ArrayType *> (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*/);
+
+ 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 ()));
+ }
+ }
+ break;
+
+ case TyTy::PARAM:
+ case TyTy::POINTER:
+ case TyTy::STR:
+ case TyTy::ADT:
+ case TyTy::REF:
+ case TyTy::SLICE:
+ 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::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::SLICE: {
+ TyTy::SliceType &type = *static_cast<TyTy::SliceType *> (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*/);
+
+ if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::SliceType (type.get_ref (), type.get_ty_ref (),
+ type.get_ident ().locus,
+ TyTy::TyVar (
+ element_unify->get_ref ()));
+ }
+ }
+ break;
+
+ 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::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::FNDEF: {
+ TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype);
+ if (ltype->num_params () != type.num_params ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ for (size_t i = 0; i < ltype->num_params (); i++)
+ {
+ auto a = ltype->param_at (i).second;
+ auto b = type.param_at (i).second;
+
+ auto unified_param
+ = UnifyRules::Resolve (TyTy::TyWithLocation (a),
+ TyTy::TyWithLocation (b), locus,
+ commit_flag, false /* emit_errors */);
+ 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 */);
+ if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNPTR:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::FNPTR: {
+ TyTy::FnPtr &type = *static_cast<TyTy::FnPtr *> (rtype);
+ if (ltype->num_params () != type.num_params ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ for (size_t i = 0; i < ltype->num_params (); i++)
+ {
+ auto a = ltype->param_at (i);
+ auto b = type.param_at (i);
+
+ auto unified_param
+ = UnifyRules::Resolve (TyTy::TyWithLocation (a),
+ TyTy::TyWithLocation (b), locus,
+ commit_flag, false /* emit_errors */);
+ 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 */);
+ if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::FNDEF: {
+ TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype);
+ auto this_ret_type = ltype->get_return_type ();
+ 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*/);
+ if (unified_result->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ if (ltype->num_params () != type.num_params ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ for (size_t i = 0; i < ltype->num_params (); i++)
+ {
+ auto this_param = ltype->param_at (i);
+ auto other_param = type.param_at (i).second;
+
+ auto unified_param
+ = UnifyRules::Resolve (TyTy::TyWithLocation (this_param),
+ TyTy::TyWithLocation (other_param), locus,
+ commit_flag, false /* emit_errors */);
+ 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:
+ case TyTy::INT:
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::TUPLE: {
+ TyTy::TupleType &type = *static_cast<TyTy::TupleType *> (rtype);
+ if (ltype->num_fields () != type.num_fields ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ std::vector<TyTy::TyVar> fields;
+ for (size_t i = 0; i < ltype->num_fields (); i++)
+ {
+ TyTy::BaseType *bo = ltype->get_field (i);
+ 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 */);
+ if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
+ return new TyTy::ErrorType (0);
+
+ fields.push_back (TyTy::TyVar (unified_ty->get_ref ()));
+ }
+
+ return new TyTy::TupleType (type.get_ref (), type.get_ty_ref (),
+ type.get_ident ().locus, fields);
+ }
+ break;
+
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::BOOL:
+ return rtype->clone ();
+
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::CHAR:
+ return rtype->clone ();
+
+ case TyTy::INT:
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
+ || r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::INT: {
+ TyTy::IntType &type = *static_cast<TyTy::IntType *> (rtype);
+ bool is_valid = ltype->get_int_kind () == type.get_int_kind ();
+ if (is_valid)
+ return new TyTy::IntType (type.get_ref (), type.get_ty_ref (),
+ type.get_int_kind ());
+ }
+ break;
+
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
+ || r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::UINT: {
+ TyTy::UintType &type = *static_cast<TyTy::UintType *> (rtype);
+ bool is_valid = ltype->get_uint_kind () == type.get_uint_kind ();
+ if (is_valid)
+ return new TyTy::UintType (type.get_ref (), type.get_ty_ref (),
+ type.get_uint_kind ());
+ }
+ break;
+
+ case TyTy::FLOAT:
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
+ || r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::FLOAT: {
+ TyTy::FloatType &type = *static_cast<TyTy::FloatType *> (rtype);
+ bool is_valid = ltype->get_float_kind () == type.get_float_kind ();
+ if (is_valid)
+ return new TyTy::FloatType (type.get_ref (), type.get_ty_ref (),
+ type.get_float_kind ());
+ }
+ break;
+
+ case TyTy::ISIZE:
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ case TyTy::FNDEF:
+ case TyTy::FNPTR:
+ case TyTy::TUPLE:
+ case TyTy::BOOL:
+ case TyTy::CHAR:
+ case TyTy::INT:
+ case TyTy::UINT:
+ case TyTy::USIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::ISIZE:
+ return rtype->clone ();
+
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ 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::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::USIZE:
+ return rtype->clone ();
+
+ case TyTy::ADT:
+ case TyTy::STR:
+ case TyTy::REF:
+ case TyTy::POINTER:
+ case TyTy::PARAM:
+ case TyTy::ARRAY:
+ case TyTy::SLICE:
+ 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::ISIZE:
+ case TyTy::NEVER:
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ case TyTy::CLOSURE:
+ case TyTy::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::NEVER:
+ return rtype->clone ();
+
+ case TyTy::PLACEHOLDER:
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ 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::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype,
+ TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::PLACEHOLDER: {
+ TyTy::PlaceholderType &type
+ = *static_cast<TyTy::PlaceholderType *> (rtype);
+ bool symbol_match
+ = ltype->get_symbol ().compare (type.get_symbol ()) == 0;
+ if (symbol_match)
+ {
+ return type.clone ();
+ }
+ }
+ break;
+
+ case TyTy::PROJECTION:
+ case TyTy::DYNAMIC:
+ 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::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_projection (TyTy::ProjectionType *ltype,
+ TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ // FIXME
+ case TyTy::PROJECTION:
+ gcc_unreachable ();
+ break;
+
+ case TyTy::DYNAMIC:
+ 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::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::DYNAMIC: {
+ TyTy::DynamicObjectType &type
+ = *static_cast<TyTy::DynamicObjectType *> (rtype);
+ if (ltype->num_specified_bounds () != type.num_specified_bounds ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ if (!ltype->bounds_compatible (type, locus, true))
+ {
+ 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::ERROR:
+ return new TyTy::ErrorType (0);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+TyTy::BaseType *
+UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype)
+{
+ switch (rtype->get_kind ())
+ {
+ case TyTy::INFER: {
+ TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
+ bool is_valid
+ = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
+ if (is_valid)
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::CLOSURE: {
+ TyTy::ClosureType &type = *static_cast<TyTy::ClosureType *> (rtype);
+ if (ltype->get_def_id () != type.get_def_id ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ TyTy::BaseType *args_res
+ = UnifyRules::Resolve (TyTy::TyWithLocation (
+ &ltype->get_parameters ()),
+ TyTy::TyWithLocation (&type.get_parameters ()),
+ locus, commit_flag, false /* emit_error */);
+ if (args_res->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ TyTy::BaseType *res = UnifyRules::Resolve (
+ TyTy::TyWithLocation (&ltype->get_result_type ()),
+ TyTy::TyWithLocation (&type.get_result_type ()), locus, commit_flag,
+ false /* emit_error */);
+ if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ return ltype->clone ();
+ }
+ break;
+
+ 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);
+ }
+ return new TyTy::ErrorType (0);
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h
new file mode 100644
index 0000000..75fb884
--- /dev/null
+++ b/gcc/rust/typecheck/rust-unify.h
@@ -0,0 +1,91 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_UNIFY
+#define RUST_UNIFY
+
+#include "rust-tyty-util.h"
+#include "rust-hir-type-check.h"
+
+namespace Rust {
+namespace Resolver {
+
+class UnifyRules
+{
+public:
+ static TyTy::BaseType *Resolve (TyTy::TyWithLocation lhs,
+ TyTy::TyWithLocation rhs, Location locus,
+ bool commit_flag, bool emit_error);
+
+protected:
+ TyTy::BaseType *expect_inference_variable (TyTy::InferType *ltype,
+ TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_reference (TyTy::ReferenceType *ltype,
+ TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_pointer (TyTy::PointerType *ltype,
+ TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_placeholder (TyTy::PlaceholderType *ltype,
+ TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_projection (TyTy::ProjectionType *ltype,
+ TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_dyn (TyTy::DynamicObjectType *ltype,
+ TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_closure (TyTy::ClosureType *ltype,
+ TyTy::BaseType *rtype);
+
+private:
+ UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+ Location locus, bool commit_flag, bool emit_error);
+
+ void emit_type_mismatch () const;
+ void commit (TyTy::BaseType *resolved);
+ TyTy::BaseType *go ();
+
+ TyTy::BaseType *get_base ();
+ TyTy::BaseType *get_other ();
+
+ TyTy::TyWithLocation lhs;
+ TyTy::TyWithLocation rhs;
+ Location locus;
+ bool commit_flag;
+ bool emit_error;
+
+ Analysis::Mappings &mappings;
+ TypeCheckContext &context;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_UNIFY
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index 33f2c93..4f63dd0 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -41,6 +41,9 @@ static const BuiltinAttrDefinition __definitions[]
{"repr", CODE_GENERATION},
{"path", EXPANSION},
{"macro_use", NAME_RESOLUTION},
+ // FIXME: This is not implemented yet, see
+ // https://github.com/Rust-GCC/gccrs/issues/1475
+ {"target_feature", CODE_GENERATION},
// From now on, these are reserved by the compiler and gated through
// #![feature(rustc_attrs)]
{"rustc_inherit_overflow_checks", CODE_GENERATION}};
@@ -764,6 +767,10 @@ void
AttributeChecker::visit (AST::SlicePattern &)
{}
+void
+AttributeChecker::visit (AST::AltPattern &)
+{}
+
// rust-stmt.h
void
AttributeChecker::visit (AST::EmptyStmt &)
diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h
index c08378c..805e3a8 100644
--- a/gcc/rust/util/rust-attributes.h
+++ b/gcc/rust/util/rust-attributes.h
@@ -242,6 +242,7 @@ private:
void visit (AST::TuplePattern &pattern);
void visit (AST::GroupedPattern &pattern);
void visit (AST::SlicePattern &pattern);
+ void visit (AST::AltPattern &pattern);
// rust-stmt.h
void visit (AST::EmptyStmt &stmt);
diff --git a/gcc/rust/rust-buffered-queue.h b/gcc/rust/util/rust-buffered-queue.h
index 20dd768..20dd768 100644
--- a/gcc/rust/rust-buffered-queue.h
+++ b/gcc/rust/util/rust-buffered-queue.h
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 1fc3203..a968704 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -96,9 +96,16 @@ static const HirId kDefaultCrateNumBegin = 0;
Mappings::Mappings ()
: crateNumItr (kDefaultCrateNumBegin), currentCrateNum (UNKNOWN_CREATENUM),
hirIdIter (kDefaultHirIdBegin), nodeIdIter (kDefaultNodeIdBegin)
-{}
+{
+ Analysis::NodeMapping node (0, 0, 0, 0);
+ builtinMarker
+ = new HIR::ImplBlock (node, {}, {}, nullptr, nullptr, HIR::WhereClause ({}),
+ Positive,
+ HIR::Visibility (HIR::Visibility::VisType::PUBLIC),
+ {}, {}, Location ());
+}
-Mappings::~Mappings () {}
+Mappings::~Mappings () { delete builtinMarker; }
Mappings *
Mappings::get ()
@@ -1035,5 +1042,11 @@ Mappings::lookup_ast_item (NodeId id, AST::Item **result)
return true;
}
+HIR::ImplBlock *
+Mappings::lookup_builtin_marker ()
+{
+ return builtinMarker;
+}
+
} // namespace Analysis
} // namespace Rust
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 13cae71..9d6affa 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -296,6 +296,8 @@ public:
void insert_ast_item (AST::Item *item);
bool lookup_ast_item (NodeId id, AST::Item **result);
+ HIR::ImplBlock *lookup_builtin_marker ();
+
private:
Mappings ();
@@ -304,6 +306,7 @@ private:
HirId hirIdIter;
NodeId nodeIdIter;
std::map<CrateNum, LocalDefId> localIdIter;
+ HIR::ImplBlock *builtinMarker;
std::map<NodeId, CrateNum> crate_node_to_crate_num;
std::map<CrateNum, AST::Crate *> ast_crate_mappings;
diff --git a/gcc/rust/util/rust-inline-visitor.h b/gcc/rust/util/rust-inline-visitor.h
index 105a67b..9240627 100644
--- a/gcc/rust/util/rust-inline-visitor.h
+++ b/gcc/rust/util/rust-inline-visitor.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2021-2022 Free Software Foundation, Inc.
+// Copyright (C) 2021-2023 Free Software Foundation, Inc.
// This file is part of GCC.
diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index ea0c91a..c5ef620 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -17,7 +17,7 @@
// <http://www.gnu.org/licenses/>.
#include "rust-system.h"
-#include "operator.h"
+#include "rust-operators.h"
namespace Rust {
namespace Analysis {
@@ -80,6 +80,12 @@ public:
FN_ONCE,
FN_ONCE_OUTPUT,
+ // markers
+ COPY,
+ CLONE,
+ SIZED,
+
+ // delimiter
UNKNOWN,
};
@@ -237,6 +243,18 @@ public:
{
return ItemType::FN_ONCE_OUTPUT;
}
+ else if (item.compare ("copy") == 0)
+ {
+ return ItemType::COPY;
+ }
+ else if (item.compare ("clone") == 0)
+ {
+ return ItemType::CLONE;
+ }
+ else if (item.compare ("sized") == 0)
+ {
+ return ItemType::SIZED;
+ }
return ItemType::UNKNOWN;
}
@@ -321,6 +339,12 @@ public:
return "fn_once";
case FN_ONCE_OUTPUT:
return "fn_once_output";
+ case COPY:
+ return "copy";
+ case CLONE:
+ return "clone";
+ case SIZED:
+ return "sized";
case UNKNOWN:
return "<UNKNOWN>";
diff --git a/gcc/rust/operator.h b/gcc/rust/util/rust-operators.h
index dab44e9..dab44e9 100644
--- a/gcc/rust/operator.h
+++ b/gcc/rust/util/rust-operators.h