aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/Make-lang.in15
-rw-r--r--gcc/rust/ast/rust-ast-builder-type.cc163
-rw-r--r--gcc/rust/ast/rust-ast-builder-type.h57
-rw-r--r--gcc/rust/ast/rust-ast-builder.cc85
-rw-r--r--gcc/rust/ast/rust-ast-builder.h43
-rw-r--r--gcc/rust/ast/rust-ast-collector.cc213
-rw-r--r--gcc/rust/ast/rust-ast-collector.h8
-rw-r--r--gcc/rust/ast/rust-ast-dump.h6
-rw-r--r--gcc/rust/ast/rust-ast-formatting.h15
-rw-r--r--gcc/rust/ast/rust-ast-full-decls.h8
-rw-r--r--gcc/rust/ast/rust-ast-visitor.cc98
-rw-r--r--gcc/rust/ast/rust-ast-visitor.h16
-rw-r--r--gcc/rust/ast/rust-ast.cc372
-rw-r--r--gcc/rust/ast/rust-ast.h82
-rw-r--r--gcc/rust/ast/rust-builtin-ast-nodes.h53
-rw-r--r--gcc/rust/ast/rust-collect-lang-items.cc24
-rw-r--r--gcc/rust/ast/rust-collect-lang-items.h3
-rw-r--r--gcc/rust/ast/rust-cond-compilation.h4
-rw-r--r--gcc/rust/ast/rust-desugar-apit.cc522
-rw-r--r--gcc/rust/ast/rust-desugar-apit.h42
-rw-r--r--gcc/rust/ast/rust-desugar-for-loops.cc69
-rw-r--r--gcc/rust/ast/rust-desugar-for-loops.h17
-rw-r--r--gcc/rust/ast/rust-desugar-question-mark.cc54
-rw-r--r--gcc/rust/ast/rust-desugar-question-mark.h16
-rw-r--r--gcc/rust/ast/rust-desugar-try-block.cc62
-rw-r--r--gcc/rust/ast/rust-desugar-try-block.h42
-rw-r--r--gcc/rust/ast/rust-desugar-while-let.cc104
-rw-r--r--gcc/rust/ast/rust-desugar-while-let.h71
-rw-r--r--gcc/rust/ast/rust-expr.h443
-rw-r--r--gcc/rust/ast/rust-expression-yeast.cc118
-rw-r--r--gcc/rust/ast/rust-expression-yeast.h52
-rw-r--r--gcc/rust/ast/rust-fmt.h7
-rw-r--r--gcc/rust/ast/rust-item.h35
-rw-r--r--gcc/rust/ast/rust-macro.h49
-rw-r--r--gcc/rust/ast/rust-path.cc21
-rw-r--r--gcc/rust/ast/rust-path.h45
-rw-r--r--gcc/rust/ast/rust-pattern.cc58
-rw-r--r--gcc/rust/ast/rust-pattern.h238
-rw-r--r--gcc/rust/ast/rust-type.h165
-rw-r--r--gcc/rust/backend/rust-compile-asm.cc105
-rw-r--r--gcc/rust/backend/rust-compile-base.cc37
-rw-r--r--gcc/rust/backend/rust-compile-base.h3
-rw-r--r--gcc/rust/backend/rust-compile-block.cc1
-rw-r--r--gcc/rust/backend/rust-compile-block.h12
-rw-r--r--gcc/rust/backend/rust-compile-context.cc28
-rw-r--r--gcc/rust/backend/rust-compile-context.h6
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc159
-rw-r--r--gcc/rust/backend/rust-compile-expr.h3
-rw-r--r--gcc/rust/backend/rust-compile-implitem.cc42
-rw-r--r--gcc/rust/backend/rust-compile-intrinsic.cc82
-rw-r--r--gcc/rust/backend/rust-compile-item.cc129
-rw-r--r--gcc/rust/backend/rust-compile-item.h8
-rw-r--r--gcc/rust/backend/rust-compile-pattern.cc456
-rw-r--r--gcc/rust/backend/rust-compile-pattern.h24
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc58
-rw-r--r--gcc/rust/backend/rust-compile-stmt.cc3
-rw-r--r--gcc/rust/backend/rust-compile-type.cc50
-rw-r--r--gcc/rust/backend/rust-compile-type.h1
-rw-r--r--gcc/rust/backend/rust-compile-var-decl.h3
-rw-r--r--gcc/rust/backend/rust-constexpr.cc193
-rw-r--r--gcc/rust/backend/rust-constexpr.h3
-rw-r--r--gcc/rust/backend/rust-mangle-v0.cc18
-rw-r--r--gcc/rust/backend/rust-mangle.h11
-rw-r--r--gcc/rust/backend/rust-tree.cc82
-rw-r--r--gcc/rust/backend/rust-tree.h183
-rw-r--r--gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h20
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc22
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h4
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h54
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h9
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc21
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h4
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-dump.cc3
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h30
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-place.h11
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-visitor.h2
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-function-collector.h4
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-check.cc3
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-ctx.h3
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc35
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-reporter.h4
-rw-r--r--gcc/rust/checks/errors/privacy/rust-reachability.cc6
-rw-r--r--gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc3
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.cc24
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.h3
-rw-r--r--gcc/rust/checks/errors/rust-feature.cc2
-rw-r--r--gcc/rust/checks/errors/rust-hir-pattern-analysis.cc142
-rw-r--r--gcc/rust/checks/errors/rust-hir-pattern-analysis.h9
-rw-r--r--gcc/rust/checks/errors/rust-readonly-check2.cc253
-rw-r--r--gcc/rust/checks/errors/rust-readonly-check2.h67
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.cc18
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.h3
-rw-r--r--gcc/rust/checks/lints/rust-lint-unused-var.cc4
-rw-r--r--gcc/rust/expand/rust-cfg-strip.cc67
-rw-r--r--gcc/rust/expand/rust-cfg-strip.h2
-rw-r--r--gcc/rust/expand/rust-derive-clone.h10
-rw-r--r--gcc/rust/expand/rust-derive-cmp-common.cc191
-rw-r--r--gcc/rust/expand/rust-derive-cmp-common.h99
-rw-r--r--gcc/rust/expand/rust-derive-copy.h8
-rw-r--r--gcc/rust/expand/rust-derive-default.cc5
-rw-r--r--gcc/rust/expand/rust-derive-eq.cc17
-rw-r--r--gcc/rust/expand/rust-derive-eq.h10
-rw-r--r--gcc/rust/expand/rust-derive-hash.cc9
-rw-r--r--gcc/rust/expand/rust-derive-hash.h10
-rw-r--r--gcc/rust/expand/rust-derive-ord.cc323
-rw-r--r--gcc/rust/expand/rust-derive-ord.h122
-rw-r--r--gcc/rust/expand/rust-derive-partial-eq.cc147
-rw-r--r--gcc/rust/expand/rust-derive-partial-eq.h29
-rw-r--r--gcc/rust/expand/rust-derive.cc36
-rw-r--r--gcc/rust/expand/rust-derive.h8
-rw-r--r--gcc/rust/expand/rust-expand-format-args.cc6
-rw-r--r--gcc/rust/expand/rust-expand-visitor.cc41
-rw-r--r--gcc/rust/expand/rust-expand-visitor.h14
-rw-r--r--gcc/rust/expand/rust-macro-builtins-asm.cc70
-rw-r--r--gcc/rust/expand/rust-macro-builtins-asm.h32
-rw-r--r--gcc/rust/expand/rust-macro-builtins-format-args.cc11
-rw-r--r--gcc/rust/expand/rust-macro-builtins-helpers.cc7
-rw-r--r--gcc/rust/expand/rust-macro-builtins-helpers.h35
-rw-r--r--gcc/rust/expand/rust-macro-builtins-offset-of.cc78
-rw-r--r--gcc/rust/expand/rust-macro-builtins.cc3
-rw-r--r--gcc/rust/expand/rust-macro-builtins.h4
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc66
-rw-r--r--gcc/rust/expand/rust-macro-substitute-ctx.cc3
-rw-r--r--gcc/rust/expand/rust-proc-macro.h6
-rw-r--r--gcc/rust/expand/rust-token-tree-desugar.cc4
-rw-r--r--gcc/rust/expand/rust-token-tree-desugar.h4
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.cc60
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h14
-rw-r--r--gcc/rust/hir/rust-ast-lower-block.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.cc91
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h7
-rw-r--r--gcc/rust/hir/rust-ast-lower-extern.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-implitem.cc22
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.cc34
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h1
-rw-r--r--gcc/rust/hir/rust-ast-lower-pattern.cc57
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.cc62
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h13
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc6
-rw-r--r--gcc/rust/hir/rust-ast-lower.h8
-rw-r--r--gcc/rust/hir/rust-hir-dump.cc126
-rw-r--r--gcc/rust/hir/rust-hir-dump.h6
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr-abstract.h5
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.cc124
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h206
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-decls.h4
-rw-r--r--gcc/rust/hir/tree/rust-hir-generic-param.h4
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.cc9
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h22
-rw-r--r--gcc/rust/hir/tree/rust-hir-path.h16
-rw-r--r--gcc/rust/hir/tree/rust-hir-pattern.h18
-rw-r--r--gcc/rust/hir/tree/rust-hir-visibility.h2
-rw-r--r--gcc/rust/hir/tree/rust-hir-visitor.cc1187
-rw-r--r--gcc/rust/hir/tree/rust-hir-visitor.h316
-rw-r--r--gcc/rust/hir/tree/rust-hir.cc64
-rw-r--r--gcc/rust/lang.opt6
-rw-r--r--gcc/rust/lex/rust-lex.cc19
-rw-r--r--gcc/rust/lex/rust-lex.h3
-rw-r--r--gcc/rust/lex/rust-token.cc11
-rw-r--r--gcc/rust/lex/rust-token.h25
-rw-r--r--gcc/rust/metadata/rust-export-metadata.cc3
-rw-r--r--gcc/rust/metadata/rust-import-archive.cc2
-rw-r--r--gcc/rust/metadata/rust-imports.h3
-rw-r--r--gcc/rust/parse/rust-cfg-parser.h7
-rw-r--r--gcc/rust/parse/rust-parse-impl-lexer.cc (renamed from gcc/rust/ast/rust-macro.cc)8
-rw-r--r--gcc/rust/parse/rust-parse-impl-macro.cc26
-rw-r--r--gcc/rust/parse/rust-parse-impl-proc-macro.cc34
-rw-r--r--gcc/rust/parse/rust-parse-impl.h627
-rw-r--r--gcc/rust/parse/rust-parse.cc46
-rw-r--r--gcc/rust/parse/rust-parse.h39
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.cc26
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.h10
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.cc38
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.cc37
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h3
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.cc57
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-stmt.h3
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.cc11
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc3
-rw-r--r--gcc/rust/resolve/rust-default-resolver.cc323
-rw-r--r--gcc/rust/resolve/rust-default-resolver.h16
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver-2.0.cc58
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver-2.0.h14
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver.cc2
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver.h2
-rw-r--r--gcc/rust/resolve/rust-finalize-imports-2.0.cc29
-rw-r--r--gcc/rust/resolve/rust-finalize-imports-2.0.h7
-rw-r--r--gcc/rust/resolve/rust-forever-stack.h15
-rw-r--r--gcc/rust/resolve/rust-forever-stack.hxx264
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.cc229
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.h13
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.cc116
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.h371
-rw-r--r--gcc/rust/resolve/rust-rib.h10
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc165
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h5
-rw-r--r--gcc/rust/rust-attribs.cc162
-rw-r--r--gcc/rust/rust-backend.h291
-rw-r--r--gcc/rust/rust-diagnostics.cc49
-rw-r--r--gcc/rust/rust-diagnostics.h21
-rw-r--r--gcc/rust/rust-gcc.cc124
-rw-r--r--gcc/rust/rust-lang.cc19
-rw-r--r--gcc/rust/rust-object-export.h13
-rw-r--r--gcc/rust/rust-session-manager.cc70
-rw-r--r--gcc/rust/rust-session-manager.h3
-rw-r--r--gcc/rust/rust-system.h6
-rw-r--r--gcc/rust/rust-target.h3
-rw-r--r--gcc/rust/typecheck/rust-autoderef.cc4
-rw-r--r--gcc/rust/typecheck/rust-casts.cc72
-rw-r--r--gcc/rust/typecheck/rust-casts.h10
-rw-r--r--gcc/rust/typecheck/rust-coercion.cc34
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.cc183
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.h35
-rw-r--r--gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h40
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.cc8
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.h16
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-reference.cc18
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-reference.h4
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.cc65
-rw-r--r--gcc/rust/typecheck/rust-hir-type-bounds.h6
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.cc128
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h7
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-enumitem.cc91
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc356
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h12
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.cc56
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.cc164
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc70
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-pattern.cc216
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.cc6
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct.cc5
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.cc107
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc36
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h55
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.cc8
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h6
-rw-r--r--gcc/rust/typecheck/rust-type-util.cc44
-rw-r--r--gcc/rust/typecheck/rust-type-util.h39
-rw-r--r--gcc/rust/typecheck/rust-typecheck-context.cc142
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc155
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.cc17
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.h1
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h39
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.cc209
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.h28
-rw-r--r--gcc/rust/typecheck/rust-tyty-util.cc34
-rw-r--r--gcc/rust/typecheck/rust-tyty-util.h4
-rw-r--r--gcc/rust/typecheck/rust-tyty-variance-analysis-private.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty-variance-analysis.cc7
-rw-r--r--gcc/rust/typecheck/rust-tyty-variance-analysis.h7
-rw-r--r--gcc/rust/typecheck/rust-tyty-visitor.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc376
-rw-r--r--gcc/rust/typecheck/rust-tyty.h125
-rw-r--r--gcc/rust/typecheck/rust-unify.cc501
-rw-r--r--gcc/rust/typecheck/rust-unify.h4
-rw-r--r--gcc/rust/util/optional.h6
-rw-r--r--gcc/rust/util/rust-abi.h6
-rw-r--r--gcc/rust/util/rust-attribute-values.h7
-rw-r--r--gcc/rust/util/rust-attributes.cc13
-rw-r--r--gcc/rust/util/rust-attributes.h2
-rw-r--r--gcc/rust/util/rust-base62.h3
-rw-r--r--gcc/rust/util/rust-canonical-path.h13
-rw-r--r--gcc/rust/util/rust-dir-owner.h3
-rw-r--r--gcc/rust/util/rust-edition.h3
-rw-r--r--gcc/rust/util/rust-ggc.cc41
-rw-r--r--gcc/rust/util/rust-ggc.h63
-rw-r--r--gcc/rust/util/rust-hir-map.cc16
-rw-r--r--gcc/rust/util/rust-hir-map.h6
-rw-r--r--gcc/rust/util/rust-punycode.h6
-rw-r--r--gcc/rust/util/rust-token-converter.cc8
-rw-r--r--gcc/rust/util/rust-token-converter.h9
-rw-r--r--gcc/rust/util/rust-unicode.h27
-rw-r--r--gcc/rust/util/rust-unwrap-segment.h9
275 files changed, 12650 insertions, 4519 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 835e113..8cdf6c9 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -73,6 +73,9 @@ GRS_OBJS = \
rust/rust-lex.o \
rust/rust-cfg-parser.o \
rust/rust-parse.o \
+ rust/rust-parse-impl-proc-macro.o \
+ rust/rust-parse-impl-macro.o \
+ rust/rust-parse-impl-lexer.o \
rust/rust-ast.o \
rust/rust-ast-formatting.o \
rust/rust-path.o \
@@ -81,6 +84,7 @@ GRS_OBJS = \
rust/rust-ast-dump.o \
rust/rust-ast-collector.o \
rust/rust-ast-visitor.o \
+ rust/rust-hir-visitor.o \
rust/rust-hir-dump.o \
rust/rust-session-manager.o \
rust/rust-compile.o \
@@ -92,14 +96,15 @@ GRS_OBJS = \
rust/rust-cfg-strip.o \
rust/rust-expand-visitor.o \
rust/rust-ast-builder.o \
- rust/rust-ast-builder-type.o \
rust/rust-derive.o \
+ rust/rust-derive-cmp-common.o \
rust/rust-derive-clone.o \
rust/rust-derive-copy.o \
rust/rust-derive-debug.o \
rust/rust-derive-default.o \
rust/rust-derive-partial-eq.o \
rust/rust-derive-eq.o \
+ rust/rust-derive-ord.o \
rust/rust-derive-hash.o \
rust/rust-proc-macro.o \
rust/rust-macro-invoc-lexer.o \
@@ -113,6 +118,7 @@ GRS_OBJS = \
rust/rust-macro-builtins-log-debug.o \
rust/rust-macro-builtins-test-bench.o \
rust/rust-macro-builtins-format-args.o \
+ rust/rust-macro-builtins-offset-of.o \
rust/rust-macro-builtins-location.o \
rust/rust-macro-builtins-include.o \
rust/rust-token-tree-desugar.o \
@@ -123,7 +129,6 @@ GRS_OBJS = \
rust/rust-keyword-values.o \
rust/rust-abi.o \
rust/rust-token-converter.o \
- rust/rust-macro.o \
rust/rust-ast-lower.o \
rust/rust-ast-lower-base.o \
rust/rust-ast-lower-pattern.o \
@@ -204,6 +209,7 @@ GRS_OBJS = \
rust/rust-lint-marklive.o \
rust/rust-lint-unused-var.o \
rust/rust-readonly-check.o \
+ rust/rust-readonly-check2.o \
rust/rust-hir-type-check-path.o \
rust/rust-unsafe-checker.o \
rust/rust-hir-pattern-analysis.o \
@@ -237,11 +243,16 @@ GRS_OBJS = \
rust/rust-punycode.o \
rust/rust-unwrap-segment.o \
rust/rust-edition.o \
+ rust/rust-ggc.o \
rust/rust-expand-format-args.o \
rust/rust-lang-item.o \
rust/rust-collect-lang-items.o \
+ rust/rust-expression-yeast.o \
rust/rust-desugar-for-loops.o \
+ rust/rust-desugar-while-let.o \
rust/rust-desugar-question-mark.o \
+ rust/rust-desugar-apit.o \
+ rust/rust-desugar-try-block.o \
$(END)
# removed object files from here
diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc
deleted file mode 100644
index 13126b4..0000000
--- a/gcc/rust/ast/rust-ast-builder-type.cc
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright (C) 2020-2024 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-ast-builder-type.h"
-#include "rust-ast-builder.h"
-#include "rust-ast-full.h"
-#include "rust-common.h"
-
-namespace Rust {
-namespace AST {
-
-ASTTypeBuilder::ASTTypeBuilder () : translated (nullptr) {}
-
-Type *
-ASTTypeBuilder::build (Type &type)
-{
- ASTTypeBuilder builder;
- type.accept_vis (builder);
- rust_assert (builder.translated != nullptr);
- return builder.translated;
-}
-
-void
-ASTTypeBuilder::visit (BareFunctionType &fntype)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (TupleType &tuple)
-{
- std::vector<std::unique_ptr<Type> > elems;
- for (auto &elem : tuple.get_elems ())
- {
- Type *t = ASTTypeBuilder::build (*elem.get ());
- std::unique_ptr<Type> ty (t);
- elems.push_back (std::move (ty));
- }
- translated = new TupleType (std::move (elems), tuple.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (TypePath &path)
-{
- std::vector<std::unique_ptr<TypePathSegment> > segments;
- for (auto &seg : path.get_segments ())
- {
- switch (seg->get_type ())
- {
- case TypePathSegment::REG: {
- const TypePathSegment &segment
- = (const TypePathSegment &) (*seg.get ());
- TypePathSegment *s
- = new TypePathSegment (segment.get_ident_segment (),
- segment.get_separating_scope_resolution (),
- segment.get_locus ());
- std::unique_ptr<TypePathSegment> sg (s);
- segments.push_back (std::move (sg));
- }
- break;
-
- case TypePathSegment::GENERIC: {
- TypePathSegmentGeneric &generic
- = (TypePathSegmentGeneric &) (*seg.get ());
-
- GenericArgs args
- = Builder::new_generic_args (generic.get_generic_args ());
- TypePathSegmentGeneric *s
- = new TypePathSegmentGeneric (generic.get_ident_segment (), false,
- std::move (args),
- generic.get_locus ());
- std::unique_ptr<TypePathSegment> sg (s);
- segments.push_back (std::move (sg));
- }
- break;
-
- case TypePathSegment::FUNCTION: {
- rust_unreachable ();
- // TODO
- // const TypePathSegmentFunction &fn
- // = (const TypePathSegmentFunction &) (*seg.get ());
- }
- break;
- }
- }
-
- translated = new TypePath (std::move (segments), path.get_locus (),
- path.has_opening_scope_resolution_op ());
-}
-
-void
-ASTTypeBuilder::visit (QualifiedPathInType &path)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (ArrayType &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (ReferenceType &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (RawPointerType &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (SliceType &type)
-{
- Type *t = ASTTypeBuilder::build (type.get_elem_type ());
- std::unique_ptr<Type> ty (t);
- translated = new SliceType (std::move (ty), type.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (InferredType &type)
-{
- translated = new InferredType (type.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (NeverType &type)
-{
- translated = new NeverType (type.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (TraitObjectTypeOneBound &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (TraitObjectType &type)
-{
- /* TODO */
-}
-
-} // namespace AST
-} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-builder-type.h b/gcc/rust/ast/rust-ast-builder-type.h
deleted file mode 100644
index b67ae3b..0000000
--- a/gcc/rust/ast/rust-ast-builder-type.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (C) 2020-2024 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_BUILDER_TYPE
-#define RUST_AST_BUILDER_TYPE
-
-#include "rust-ast-visitor.h"
-
-namespace Rust {
-namespace AST {
-
-class ASTTypeBuilder : public DefaultASTVisitor
-{
-protected:
- using DefaultASTVisitor::visit;
-
-public:
- static Type *build (Type &type);
-
- void visit (BareFunctionType &fntype) override;
- void visit (TupleType &tuple) override;
- void visit (TypePath &path) override;
- void visit (QualifiedPathInType &path) override;
- void visit (ArrayType &type) override;
- void visit (ReferenceType &type) override;
- void visit (RawPointerType &type) override;
- void visit (SliceType &type) override;
- void visit (InferredType &type) override;
- void visit (NeverType &type) override;
- void visit (TraitObjectTypeOneBound &type) override;
- void visit (TraitObjectType &type) override;
-
-private:
- ASTTypeBuilder ();
-
- Type *translated;
-};
-
-} // namespace AST
-} // namespace Rust
-
-#endif // RUST_AST_BUILDER_TYPE
diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc
index 08c52b1..ed10ce7 100644
--- a/gcc/rust/ast/rust-ast-builder.cc
+++ b/gcc/rust/ast/rust-ast-builder.cc
@@ -18,7 +18,6 @@
#include "rust-ast-builder.h"
#include "optional.h"
-#include "rust-ast-builder-type.h"
#include "rust-ast.h"
#include "rust-common.h"
#include "rust-expr.h"
@@ -29,7 +28,6 @@
#include "rust-pattern.h"
#include "rust-system.h"
#include "rust-token.h"
-#include <memory>
namespace Rust {
namespace AST {
@@ -332,6 +330,12 @@ Builder::block () const
}
std::unique_ptr<BlockExpr>
+Builder::block (std::unique_ptr<Expr> &&tail_expr) const
+{
+ return block (tl::nullopt, std::move (tail_expr));
+}
+
+std::unique_ptr<BlockExpr>
Builder::block (std::vector<std::unique_ptr<Stmt>> &&stmts,
std::unique_ptr<Expr> &&tail_expr) const
{
@@ -442,6 +446,14 @@ Builder::field_access (std::unique_ptr<Expr> &&instance,
new FieldAccessExpr (std::move (instance), field, {}, loc));
}
+std::unique_ptr<StructPatternField>
+Builder::struct_pattern_ident_pattern (std::string field_name,
+ std::unique_ptr<Pattern> &&pattern)
+{
+ return std::make_unique<StructPatternFieldIdentPat> (
+ field_name, std::move (pattern), std::vector<Attribute> (), loc);
+}
+
std::unique_ptr<Pattern>
Builder::wildcard () const
{
@@ -482,9 +494,14 @@ MatchCase
Builder::match_case (std::unique_ptr<Pattern> &&pattern,
std::unique_ptr<Expr> &&expr)
{
- return MatchCase (match_arm (std::move (pattern)), std::move (expr));
+ return match_case (match_arm (std::move (pattern)), std::move (expr));
}
+MatchCase
+Builder::match_case (MatchArm &&arm, std::unique_ptr<Expr> &&expr)
+{
+ return MatchCase (std::move (arm), std::move (expr));
+}
std::unique_ptr<Expr>
Builder::loop (std::vector<std::unique_ptr<Stmt>> &&stmts)
{
@@ -523,11 +540,14 @@ Builder::generic_type_param (
std::vector<Attribute> ());
}
-std::unique_ptr<Type>
-Builder::new_type (Type &type)
+std::unique_ptr<Stmt>
+Builder::discriminant_value (std::string binding_name, std::string instance)
{
- Type *t = ASTTypeBuilder::build (type);
- return std::unique_ptr<Type> (t);
+ auto intrinsic = ptrify (
+ path_in_expression ({"core", "intrinsics", "discriminant_value"}, true));
+
+ return let (identifier_pattern (binding_name), nullptr,
+ call (std::move (intrinsic), identifier (instance)));
}
std::unique_ptr<GenericParam>
@@ -547,6 +567,16 @@ Builder::new_lifetime_param (LifetimeParam &param)
}
std::unique_ptr<GenericParam>
+Builder::new_const_param (ConstGenericParam &param) const
+{
+ return std::make_unique<ConstGenericParam> (param.get_name (),
+ param.get_type ().clone_type (),
+ param.get_default_value (),
+ param.get_outer_attrs (),
+ param.get_locus ());
+}
+
+std::unique_ptr<GenericParam>
Builder::new_type_param (
TypeParam &param, std::vector<std::unique_ptr<TypeParamBound>> extra_bounds)
{
@@ -557,7 +587,7 @@ Builder::new_type_param (
std::unique_ptr<Type> type = nullptr;
if (param.has_type ())
- type = new_type (param.get_type ());
+ type = param.get_type ().reconstruct ();
for (auto &&extra_bound : extra_bounds)
type_param_bounds.emplace_back (std::move (extra_bound));
@@ -566,7 +596,8 @@ Builder::new_type_param (
{
switch (b->get_bound_type ())
{
- case TypeParamBound::TypeParamBoundType::TRAIT: {
+ case TypeParamBound::TypeParamBoundType::TRAIT:
+ {
const TraitBound &tb = (const TraitBound &) *b.get ();
const TypePath &path = tb.get_type_path ();
@@ -591,7 +622,8 @@ Builder::new_type_param (
{
switch (seg->get_type ())
{
- case TypePathSegment::REG: {
+ case TypePathSegment::REG:
+ {
const TypePathSegment &segment
= (const TypePathSegment &) (*seg.get ());
TypePathSegment *s = new TypePathSegment (
@@ -603,7 +635,8 @@ Builder::new_type_param (
}
break;
- case TypePathSegment::GENERIC: {
+ case TypePathSegment::GENERIC:
+ {
TypePathSegmentGeneric &generic
= (TypePathSegmentGeneric &) (*seg.get ());
@@ -617,7 +650,8 @@ Builder::new_type_param (
}
break;
- case TypePathSegment::FUNCTION: {
+ case TypePathSegment::FUNCTION:
+ {
rust_unreachable ();
// TODO
// const TypePathSegmentFunction &fn
@@ -639,7 +673,8 @@ Builder::new_type_param (
}
break;
- case TypeParamBound::TypeParamBoundType::LIFETIME: {
+ case TypeParamBound::TypeParamBoundType::LIFETIME:
+ {
const Lifetime &l = (const Lifetime &) *b.get ();
auto bl = new Lifetime (l.get_lifetime_type (),
@@ -682,7 +717,7 @@ Builder::new_generic_args (GenericArgs &args)
for (auto &binding : args.get_binding_args ())
{
Type &t = *binding.get_type_ptr ().get ();
- std::unique_ptr<Type> ty = new_type (t);
+ std::unique_ptr<Type> ty = t.reconstruct ();
GenericArgsBinding b (binding.get_identifier (), std::move (ty),
binding.get_locus ());
binding_args.push_back (std::move (b));
@@ -690,19 +725,25 @@ Builder::new_generic_args (GenericArgs &args)
for (auto &arg : args.get_generic_args ())
{
+ tl::optional<GenericArg> new_arg = tl::nullopt;
+
switch (arg.get_kind ())
{
- case GenericArg::Kind::Type: {
- std::unique_ptr<Type> ty = new_type (arg.get_type ());
- GenericArg arg = GenericArg::create_type (std::move (ty));
- }
+ case GenericArg::Kind::Type:
+ new_arg = GenericArg::create_type (arg.get_type ().reconstruct ());
break;
-
- default:
- // FIXME
- rust_unreachable ();
+ case GenericArg::Kind::Either:
+ new_arg
+ = GenericArg::create_ambiguous (arg.get_path (), arg.get_locus ());
+ break;
+ case GenericArg::Kind::Const:
+ new_arg
+ = GenericArg::create_const (arg.get_expression ().clone_expr ());
+ // FIXME: Use `reconstruct()` here, not `clone_expr()`
break;
}
+
+ generic_args.emplace_back (*new_arg);
}
return GenericArgs (std::move (lifetime_args), std::move (generic_args),
diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h
index 41ce118..843bab8 100644
--- a/gcc/rust/ast/rust-ast-builder.h
+++ b/gcc/rust/ast/rust-ast-builder.h
@@ -24,6 +24,7 @@
#include "rust-ast.h"
#include "rust-item.h"
#include "rust-operators.h"
+#include <initializer_list>
namespace Rust {
namespace AST {
@@ -51,6 +52,19 @@ vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2)
return v;
}
+template <typename T>
+std::vector<std::unique_ptr<T>>
+vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2, std::unique_ptr<T> &&t3)
+{
+ auto v = std::vector<std::unique_ptr<T>> ();
+
+ v.emplace_back (std::move (t1));
+ v.emplace_back (std::move (t2));
+ v.emplace_back (std::move (t3));
+
+ return v;
+}
+
/* Pointer-ify something */
template <typename T>
static std::unique_ptr<T>
@@ -117,6 +131,9 @@ public:
/* Create an empty block */
std::unique_ptr<BlockExpr> block () const;
+ /* Create a block with just a tail expression */
+ std::unique_ptr<BlockExpr> block (std::unique_ptr<Expr> &&tail_expr) const;
+
/* Create an early return expression with an optional expression */
std::unique_ptr<Expr> return_expr (std::unique_ptr<Expr> &&to_return
= nullptr);
@@ -254,6 +271,10 @@ public:
std::unique_ptr<Expr> field_access (std::unique_ptr<Expr> &&instance,
std::string field) const;
+ std::unique_ptr<StructPatternField>
+ struct_pattern_ident_pattern (std::string field_name,
+ std::unique_ptr<Pattern> &&pattern);
+
/* Create a wildcard pattern (`_`) */
std::unique_ptr<Pattern> wildcard () const;
/* Create a reference pattern (`&pattern`) */
@@ -268,6 +289,7 @@ public:
MatchArm match_arm (std::unique_ptr<Pattern> &&pattern);
MatchCase match_case (std::unique_ptr<Pattern> &&pattern,
std::unique_ptr<Expr> &&expr);
+ MatchCase match_case (MatchArm &&arm, std::unique_ptr<Expr> &&expr);
/* Create a loop expression */
std::unique_ptr<Expr> loop (std::vector<std::unique_ptr<Stmt>> &&stmts);
@@ -285,11 +307,20 @@ public:
std::vector<std::unique_ptr<TypeParamBound>> &&bounds,
std::unique_ptr<Type> &&type = nullptr);
- static std::unique_ptr<Type> new_type (Type &type);
+ /**
+ * Create a let statement with the discriminant value of a given enum
+ * instance. This helper exists since it is a common operation in a lot of the
+ * derive implementations, and it sucks to repeat all the steps every time.
+ */
+ std::unique_ptr<Stmt> discriminant_value (std::string binding_name,
+ std::string instance = "self");
static std::unique_ptr<GenericParam>
new_lifetime_param (LifetimeParam &param);
+ std::unique_ptr<GenericParam>
+ new_const_param (ConstGenericParam &param) const;
+
static std::unique_ptr<GenericParam> new_type_param (
TypeParam &param,
std::vector<std::unique_ptr<TypeParamBound>> extra_trait_bounds = {});
@@ -298,11 +329,13 @@ public:
static GenericArgs new_generic_args (GenericArgs &args);
-private:
- /**
- * Location of the generated AST nodes
- */
+ /* Location of the generated AST nodes */
location_t loc;
+
+private:
+ /* Some constexpr helpers for some of the builders */
+ static constexpr std::initializer_list<const char *> discriminant_value_path
+ = {"core", "intrinsics", "discriminant_value"};
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index c850e96..3d9ea78 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -18,6 +18,7 @@
#include "rust-ast-collector.h"
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
#include "rust-diagnostics.h"
#include "rust-expr.h"
#include "rust-item.h"
@@ -154,20 +155,24 @@ TokenCollector::visit (Attribute &attrib)
{
switch (attrib.get_attr_input ().get_attr_input_type ())
{
- case AST::AttrInput::AttrInputType::LITERAL: {
+ case AST::AttrInput::AttrInputType::LITERAL:
+ {
visit (static_cast<AttrInputLiteral &> (attrib.get_attr_input ()));
break;
}
- case AST::AttrInput::AttrInputType::MACRO: {
+ case AST::AttrInput::AttrInputType::MACRO:
+ {
visit (static_cast<AttrInputMacro &> (attrib.get_attr_input ()));
break;
}
- case AST::AttrInput::AttrInputType::META_ITEM: {
+ case AST::AttrInput::AttrInputType::META_ITEM:
+ {
visit (static_cast<AttrInputMetaItemContainer &> (
attrib.get_attr_input ()));
break;
}
- case AST::AttrInput::AttrInputType::TOKEN_TREE: {
+ case AST::AttrInput::AttrInputType::TOKEN_TREE:
+ {
visit (static_cast<DelimTokenTree &> (attrib.get_attr_input ()));
break;
}
@@ -634,7 +639,8 @@ TokenCollector::visit (GenericArg &arg)
case GenericArg::Kind::Type:
visit (arg.get_type ());
break;
- case GenericArg::Kind::Either: {
+ case GenericArg::Kind::Either:
+ {
auto path = arg.get_path ();
push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path)));
}
@@ -789,7 +795,8 @@ TokenCollector::visit (Literal &lit, location_t locus)
push (Rust::Token::make_float (locus, std::move (value),
lit.get_type_hint ()));
break;
- case Literal::LitType::BOOL: {
+ case Literal::LitType::BOOL:
+ {
if (value == Values::Keywords::FALSE_LITERAL)
push (Rust::Token::make (FALSE_LITERAL, locus));
else if (value == Values::Keywords::TRUE_LITERAL)
@@ -833,13 +840,13 @@ TokenCollector::visit (MetaItemLitExpr &item)
}
void
-TokenCollector::visit (MetaItemPathLit &item)
+TokenCollector::visit (MetaItemPathExpr &item)
{
- auto path = item.get_path ();
- auto lit = item.get_literal ();
+ auto &path = item.get_path ();
+ auto &expr = item.get_expr ();
visit (path);
- push (Rust::Token::make (COLON, item.get_locus ()));
- visit (lit);
+ push (Rust::Token::make (EQUAL, item.get_locus ()));
+ visit (expr);
}
void
@@ -864,7 +871,8 @@ TokenCollector::visit (BorrowExpr &expr)
push (Rust::Token::make (MUT, UNDEF_LOCATION));
}
- visit (expr.get_borrowed_expr ());
+ if (expr.has_borrow_expr ())
+ visit (expr.get_borrowed_expr ());
}
void
@@ -1264,12 +1272,34 @@ TokenCollector::visit (BlockExpr &expr)
}
void
+TokenCollector::visit (AnonConst &expr)
+{
+ if (!expr.is_deferred ())
+ {
+ visit (expr.get_inner_expr ());
+ return;
+ }
+
+ push (Rust::Token::make_string (expr.get_locus (), "_"));
+}
+
+void
+TokenCollector::visit (ConstBlock &expr)
+{
+ push (Rust::Token::make (CONST, expr.get_locus ()));
+
+ // The inner expression is already a block expr, so we don't need to add
+ // curlies
+ visit (expr.get_const_expr ());
+}
+
+void
TokenCollector::visit (ClosureExprInnerTyped &expr)
{
visit_closure_common (expr);
push (Rust::Token::make (RETURN_TYPE, expr.get_locus ()));
visit (expr.get_return_type ());
- visit (expr.get_definition_block ());
+ visit (expr.get_definition_expr ());
}
void
@@ -1349,6 +1379,13 @@ TokenCollector::visit (ReturnExpr &expr)
}
void
+TokenCollector::visit (TryExpr &expr)
+{
+ push (Rust::Token::make (TRY, expr.get_locus ()));
+ visit (expr.get_block_expr ());
+}
+
+void
TokenCollector::visit (UnsafeBlockExpr &expr)
{
push (Rust::Token::make (UNSAFE, expr.get_locus ()));
@@ -1518,7 +1555,95 @@ TokenCollector::visit (AsyncBlockExpr &expr)
void
TokenCollector::visit (InlineAsm &expr)
-{}
+{
+ push (Rust::Token::make_identifier (expr.get_locus (), "asm"));
+ push (Rust::Token::make (EXCLAM, expr.get_locus ()));
+ push (Rust::Token::make (LEFT_PAREN, expr.get_locus ()));
+
+ for (auto &template_str : expr.get_template_strs ())
+ push (Rust::Token::make_string (template_str.get_locus (),
+ std::move (template_str.symbol)));
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+
+ for (auto &operand : expr.get_operands ())
+ {
+ using RegisterType = AST::InlineAsmOperand::RegisterType;
+ switch (operand.get_register_type ())
+ {
+ case RegisterType::In:
+ {
+ visit (operand.get_in ().expr);
+ break;
+ }
+ case RegisterType::Out:
+ {
+ visit (operand.get_out ().expr);
+ break;
+ }
+ case RegisterType::InOut:
+ {
+ visit (operand.get_in_out ().expr);
+ break;
+ }
+ case RegisterType::SplitInOut:
+ {
+ auto split = operand.get_split_in_out ();
+ visit (split.in_expr);
+ visit (split.out_expr);
+ break;
+ }
+ case RegisterType::Const:
+ {
+ visit (operand.get_const ().anon_const.get_inner_expr ());
+ break;
+ }
+ case RegisterType::Sym:
+ {
+ visit (operand.get_sym ().expr);
+ break;
+ }
+ case RegisterType::Label:
+ {
+ visit (operand.get_label ().expr);
+ break;
+ }
+ }
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+
+ for (auto &clobber : expr.get_clobber_abi ())
+ {
+ push (Rust::Token::make_string (expr.get_locus (),
+ std::move (clobber.symbol)));
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+
+ for (auto it = expr.named_args.begin (); it != expr.named_args.end (); ++it)
+ {
+ auto &arg = *it;
+ push (
+ Rust::Token::make_identifier (expr.get_locus (), arg.first.c_str ()));
+ push (Rust::Token::make (EQUAL, expr.get_locus ()));
+ push (Rust::Token::make_identifier (expr.get_locus (),
+ std::to_string (arg.second)));
+
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+
+ for (auto &option : expr.get_options ())
+ {
+ push (Rust::Token::make_identifier (
+ expr.get_locus (), InlineAsm::option_to_string (option).c_str ()));
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+
+ push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ()));
+}
void
TokenCollector::visit (LlvmInlineAsm &expr)
@@ -1695,7 +1820,8 @@ TokenCollector::visit (UseTreeGlob &use_tree)
{
switch (use_tree.get_glob_type ())
{
- case UseTreeGlob::PathType::PATH_PREFIXED: {
+ case UseTreeGlob::PathType::PATH_PREFIXED:
+ {
auto path = use_tree.get_path ();
visit (path);
push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
@@ -1715,7 +1841,8 @@ TokenCollector::visit (UseTreeList &use_tree)
{
switch (use_tree.get_path_type ())
{
- case UseTreeList::PathType::PATH_PREFIXED: {
+ case UseTreeList::PathType::PATH_PREFIXED:
+ {
auto path = use_tree.get_path ();
visit (path);
push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
@@ -1743,7 +1870,8 @@ TokenCollector::visit (UseTreeRebind &use_tree)
visit (path);
switch (use_tree.get_new_bind_type ())
{
- case UseTreeRebind::NewBindType::IDENTIFIER: {
+ case UseTreeRebind::NewBindType::IDENTIFIER:
+ {
push (Rust::Token::make (AS, UNDEF_LOCATION));
auto id = use_tree.get_identifier ().as_string ();
push (
@@ -1964,8 +2092,7 @@ TokenCollector::visit (ConstantItem &item)
}
else
{
- auto id = item.get_identifier ();
- push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
+ push (Rust::Token::make_identifier (item.get_identifier ()));
}
push (Rust::Token::make (COLON, UNDEF_LOCATION));
visit (item.get_type ());
@@ -2370,10 +2497,10 @@ TokenCollector::visit (IdentifierPattern &pattern)
auto id = pattern.get_ident ().as_string ();
push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
- if (pattern.has_pattern_to_bind ())
+ if (pattern.has_subpattern ())
{
push (Rust::Token::make (PATTERN_BIND, UNDEF_LOCATION));
- visit (pattern.get_pattern_to_bind ());
+ visit (pattern.get_subpattern ());
}
}
@@ -2591,10 +2718,34 @@ TokenCollector::visit (GroupedPattern &pattern)
}
void
+TokenCollector::visit (SlicePatternItemsNoRest &items)
+{
+ visit_items_joined_by_separator (items.get_patterns (), COMMA);
+}
+
+void
+TokenCollector::visit (SlicePatternItemsHasRest &items)
+{
+ if (!items.get_lower_patterns ().empty ())
+ {
+ visit_items_joined_by_separator (items.get_lower_patterns (), COMMA);
+ push (Rust::Token::make (COMMA, UNDEF_LOCATION));
+ }
+
+ push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION));
+
+ if (!items.get_upper_patterns ().empty ())
+ {
+ push (Rust::Token::make (COMMA, UNDEF_LOCATION));
+ visit_items_joined_by_separator (items.get_upper_patterns (), COMMA);
+ }
+}
+
+void
TokenCollector::visit (SlicePattern &pattern)
{
push (Rust::Token::make (LEFT_SQUARE, pattern.get_locus ()));
- visit_items_joined_by_separator (pattern.get_items (), COMMA);
+ visit (pattern.get_items ());
push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION));
}
@@ -2862,5 +3013,23 @@ TokenCollector::visit (AST::FormatArgs &fmt)
__FILE__, __LINE__);
}
+void
+TokenCollector::visit (AST::OffsetOf &offset_of)
+{
+ auto loc = offset_of.get_locus ();
+
+ push (Rust::Token::make_identifier (loc, "offset_of"));
+ push (Rust::Token::make (EXCLAM, loc));
+ push (Rust::Token::make (LEFT_PAREN, loc));
+
+ visit (offset_of.get_type ());
+
+ push (Rust::Token::make (COMMA, loc));
+
+ push (Rust::Token::make_identifier (offset_of.get_field ()));
+
+ push (Rust::Token::make (RIGHT_PAREN, loc));
+}
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h
index f45e3cc..d3ab18a 100644
--- a/gcc/rust/ast/rust-ast-collector.h
+++ b/gcc/rust/ast/rust-ast-collector.h
@@ -246,7 +246,7 @@ public:
void visit (AttrInputLiteral &attr_input);
void visit (AttrInputMacro &attr_input);
void visit (MetaItemLitExpr &meta_item);
- void visit (MetaItemPathLit &meta_item);
+ void visit (MetaItemPathExpr &meta_item);
void visit (BorrowExpr &expr);
void visit (DereferenceExpr &expr);
void visit (ErrorPropagationExpr &expr);
@@ -277,6 +277,8 @@ public:
void visit (ClosureParam &param);
void visit (ClosureExprInner &expr);
void visit (BlockExpr &expr);
+ void visit (AnonConst &expr);
+ void visit (ConstBlock &expr);
void visit (ClosureExprInnerTyped &expr);
void visit (ContinueExpr &expr);
void visit (BreakExpr &expr);
@@ -287,6 +289,7 @@ public:
void visit (RangeFromToInclExpr &expr);
void visit (RangeToInclExpr &expr);
void visit (ReturnExpr &expr);
+ void visit (TryExpr &expr);
void visit (BoxExpr &expr);
void visit (UnsafeBlockExpr &expr);
void visit (LoopExpr &expr);
@@ -375,6 +378,8 @@ public:
void visit (TuplePatternItemsRanged &tuple_items);
void visit (TuplePattern &pattern);
void visit (GroupedPattern &pattern);
+ void visit (SlicePatternItemsNoRest &items);
+ void visit (SlicePatternItemsHasRest &items);
void visit (SlicePattern &pattern);
void visit (AltPattern &pattern);
@@ -400,6 +405,7 @@ public:
void visit (BareFunctionType &type);
void visit (FormatArgs &fmt);
+ void visit (OffsetOf &offset_of);
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-ast-dump.h b/gcc/rust/ast/rust-ast-dump.h
index 02c99b7..0c3875e 100644
--- a/gcc/rust/ast/rust-ast-dump.h
+++ b/gcc/rust/ast/rust-ast-dump.h
@@ -49,7 +49,8 @@ public:
{
switch (item.get_kind ())
{
- case AST::CollectItem::Kind::Token: {
+ case AST::CollectItem::Kind::Token:
+ {
TokenPtr current = item.get_token ();
if (require_spacing (previous, current))
stream << " ";
@@ -90,7 +91,6 @@ private:
} // namespace Rust
// In the global namespace to make it easier to call from debugger
-void
-debug (Rust::AST::Visitable &v);
+void debug (Rust::AST::Visitable &v);
#endif // !RUST_AST_DUMP_H
diff --git a/gcc/rust/ast/rust-ast-formatting.h b/gcc/rust/ast/rust-ast-formatting.h
index 3dfabbc..aace93f 100644
--- a/gcc/rust/ast/rust-ast-formatting.h
+++ b/gcc/rust/ast/rust-ast-formatting.h
@@ -35,23 +35,18 @@ enum AttrMode
INNER
};
-std::string
-indent_spaces (enum indent_mode mode);
+std::string indent_spaces (enum indent_mode mode);
// Gets a string in a certain delim type.
-std::string
-get_string_in_delims (std::string str_input, DelimType delim_type);
+std::string get_string_in_delims (std::string str_input, DelimType delim_type);
-std::string
-get_mode_dump_desc (AttrMode mode);
+std::string get_mode_dump_desc (AttrMode mode);
// Adds lines below adding attributes
-std::string
-append_attributes (std::vector<Attribute> attrs, AttrMode mode);
+std::string append_attributes (std::vector<Attribute> attrs, AttrMode mode);
// Removes the beginning and end quotes of a quoted string.
-std::string
-unquote_string (std::string input);
+std::string unquote_string (std::string input);
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
index 9359248..09706ce 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -78,7 +78,7 @@ class LiteralExpr;
class AttrInputLiteral;
class AttrInputMacro;
class MetaItemLitExpr;
-class MetaItemPathLit;
+class MetaItemPathExpr;
class OperatorExpr;
class BorrowExpr;
class DereferenceExpr;
@@ -115,6 +115,8 @@ struct ClosureParam;
class ClosureExpr;
class ClosureExprInner;
class BlockExpr;
+class AnonConst;
+class ConstBlock;
class ClosureExprInnerTyped;
class ContinueExpr;
class BreakExpr;
@@ -126,6 +128,7 @@ class RangeFullExpr;
class RangeFromToInclExpr;
class RangeToInclExpr;
class ReturnExpr;
+class TryExpr;
class UnsafeBlockExpr;
class LoopLabel;
class BaseLoopExpr;
@@ -146,7 +149,6 @@ class MatchExpr;
class AwaitExpr;
class AsyncBlockExpr;
enum class InlineAsmOption;
-struct AnonConst;
struct InlineAsmRegOrRegClass;
class InlineAsmOperand;
struct InlineAsmPlaceHolder;
@@ -246,6 +248,8 @@ class TuplePatternItemsMultiple;
class TuplePatternItemsRanged;
class TuplePattern;
class GroupedPattern;
+class SlicePatternItemsNoRest;
+class SlicePatternItemsHasRest;
class SlicePattern;
class AltPattern;
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index b6833f6..ab8cdbe 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -19,6 +19,7 @@
#include "rust-ast-visitor.h"
#include "rust-ast-full-decls.h"
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
#include "rust-path.h"
#include "rust-token.h"
#include "rust-expr.h"
@@ -223,10 +224,10 @@ DefaultASTVisitor::visit (AST::SimplePath &path)
}
void
-DefaultASTVisitor::visit (AST::MetaItemPathLit &meta_item)
+DefaultASTVisitor::visit (AST::MetaItemPathExpr &meta_item)
{
visit (meta_item.get_path ());
- visit (meta_item.get_literal ());
+ visit (meta_item.get_expr ());
}
void
@@ -449,20 +450,38 @@ DefaultASTVisitor::visit (AST::BlockExpr &expr)
{
visit_outer_attrs (expr);
visit_inner_attrs (expr);
+
+ if (expr.has_label ())
+ visit (expr.get_label ());
+
for (auto &stmt : expr.get_statements ())
visit (stmt);
+
if (expr.has_tail_expr ())
visit (expr.get_tail_expr ());
}
void
+DefaultASTVisitor::visit (AST::ConstBlock &expr)
+{
+ visit (expr.get_const_expr ());
+}
+
+void
+DefaultASTVisitor::visit (AST::AnonConst &expr)
+{
+ if (!expr.is_deferred ())
+ visit (expr.get_inner_expr ());
+}
+
+void
DefaultASTVisitor::visit (AST::ClosureExprInnerTyped &expr)
{
visit_outer_attrs (expr);
for (auto &param : expr.get_params ())
visit (param);
visit (expr.get_return_type ());
- visit (expr.get_definition_block ());
+ visit (expr.get_definition_expr ());
}
void
@@ -538,6 +557,13 @@ DefaultASTVisitor::visit (AST::ReturnExpr &expr)
}
void
+DefaultASTVisitor::visit (AST::TryExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit (expr.get_block_expr ());
+}
+
+void
DefaultASTVisitor::visit (AST::BoxExpr &expr)
{
visit_outer_attrs (expr);
@@ -582,7 +608,10 @@ DefaultASTVisitor::visit (AST::WhileLetLoopExpr &expr)
visit_outer_attrs (expr);
for (auto &pattern : expr.get_patterns ())
visit (pattern);
- visit (expr.get_loop_label ());
+
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
+
visit (expr.get_scrutinee_expr ());
visit (expr.get_loop_block ());
}
@@ -680,33 +709,40 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr)
{
switch (operand.get_register_type ())
{
- case RegisterType::In: {
+ case RegisterType::In:
+ {
visit (operand.get_in ().expr);
break;
}
- case RegisterType::Out: {
+ case RegisterType::Out:
+ {
visit (operand.get_out ().expr);
break;
}
- case RegisterType::InOut: {
+ case RegisterType::InOut:
+ {
visit (operand.get_in_out ().expr);
break;
}
- case RegisterType::SplitInOut: {
+ case RegisterType::SplitInOut:
+ {
auto split = operand.get_split_in_out ();
visit (split.in_expr);
visit (split.out_expr);
break;
}
- case RegisterType::Const: {
- visit (operand.get_const ().anon_const.expr);
+ case RegisterType::Const:
+ {
+ visit (operand.get_const ().anon_const.get_inner_expr ());
break;
}
- case RegisterType::Sym: {
+ case RegisterType::Sym:
+ {
visit (operand.get_sym ().expr);
break;
}
- case RegisterType::Label: {
+ case RegisterType::Label:
+ {
visit (operand.get_label ().expr);
break;
}
@@ -755,7 +791,8 @@ DefaultASTVisitor::visit (AST::TypeBoundWhereClauseItem &item)
void
DefaultASTVisitor::visit (AST::Visibility &vis)
{
- visit (vis.get_path ());
+ if (vis.has_path ())
+ visit (vis.get_path ());
}
void
@@ -922,7 +959,7 @@ DefaultASTVisitor::visit (AST::EnumItem &item)
void
DefaultASTVisitor::visit (AST::EnumItemTuple &item)
{
- visit (reinterpret_cast<EnumItem &> (item));
+ DefaultASTVisitor::visit (static_cast<EnumItem &> (item));
for (auto &field : item.get_tuple_fields ())
visit (field);
}
@@ -930,7 +967,7 @@ DefaultASTVisitor::visit (AST::EnumItemTuple &item)
void
DefaultASTVisitor::visit (AST::EnumItemStruct &item)
{
- visit (reinterpret_cast<EnumItem &> (item));
+ DefaultASTVisitor::visit (static_cast<EnumItem &> (item));
for (auto &field : item.get_struct_fields ())
visit (field);
}
@@ -938,7 +975,7 @@ DefaultASTVisitor::visit (AST::EnumItemStruct &item)
void
DefaultASTVisitor::visit (AST::EnumItemDiscriminant &item)
{
- visit (reinterpret_cast<EnumItem &> (item));
+ DefaultASTVisitor::visit (static_cast<EnumItem &> (item));
visit (item.get_expr ());
}
@@ -1179,8 +1216,8 @@ DefaultASTVisitor::visit (AST::LiteralPattern &pattern)
void
DefaultASTVisitor::visit (AST::IdentifierPattern &pattern)
{
- if (pattern.has_pattern_to_bind ())
- visit (pattern.get_pattern_to_bind ());
+ if (pattern.has_subpattern ())
+ visit (pattern.get_subpattern ());
}
void
@@ -1310,13 +1347,28 @@ DefaultASTVisitor::visit (AST::GroupedPattern &pattern)
}
void
-DefaultASTVisitor::visit (AST::SlicePattern &pattern)
+DefaultASTVisitor::visit (AST::SlicePatternItemsNoRest &items)
+{
+ for (auto &item : items.get_patterns ())
+ visit (item);
+}
+
+void
+DefaultASTVisitor::visit (AST::SlicePatternItemsHasRest &items)
{
- for (auto &item : pattern.get_items ())
+ for (auto &item : items.get_lower_patterns ())
+ visit (item);
+ for (auto &item : items.get_upper_patterns ())
visit (item);
}
void
+DefaultASTVisitor::visit (AST::SlicePattern &pattern)
+{
+ visit (pattern.get_items ());
+}
+
+void
DefaultASTVisitor::visit (AST::AltPattern &pattern)
{
for (auto &alt : pattern.get_alts ())
@@ -1454,6 +1506,12 @@ DefaultASTVisitor::visit (AST::FormatArgs &)
}
void
+DefaultASTVisitor::visit (AST::OffsetOf &offset_of)
+{
+ visit (offset_of.get_type ());
+}
+
+void
DefaultASTVisitor::visit (AST::VariadicParam &param)
{
if (param.has_pattern ())
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index b1fc504..2d81aa1 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -73,7 +73,7 @@ public:
virtual void visit (AttrInputLiteral &attr_input) = 0;
virtual void visit (AttrInputMacro &attr_input) = 0;
virtual void visit (MetaItemLitExpr &meta_item) = 0;
- virtual void visit (MetaItemPathLit &meta_item) = 0;
+ virtual void visit (MetaItemPathExpr &meta_item) = 0;
virtual void visit (BorrowExpr &expr) = 0;
virtual void visit (DereferenceExpr &expr) = 0;
virtual void visit (ErrorPropagationExpr &expr) = 0;
@@ -104,6 +104,8 @@ public:
virtual void visit (FieldAccessExpr &expr) = 0;
virtual void visit (ClosureExprInner &expr) = 0;
virtual void visit (BlockExpr &expr) = 0;
+ virtual void visit (AnonConst &expr) = 0;
+ virtual void visit (ConstBlock &expr) = 0;
virtual void visit (ClosureExprInnerTyped &expr) = 0;
virtual void visit (ContinueExpr &expr) = 0;
virtual void visit (BreakExpr &expr) = 0;
@@ -114,6 +116,7 @@ public:
virtual void visit (RangeFromToInclExpr &expr) = 0;
virtual void visit (RangeToInclExpr &expr) = 0;
virtual void visit (ReturnExpr &expr) = 0;
+ virtual void visit (TryExpr &expr) = 0;
virtual void visit (BoxExpr &expr) = 0;
virtual void visit (UnsafeBlockExpr &expr) = 0;
virtual void visit (LoopExpr &expr) = 0;
@@ -209,6 +212,8 @@ public:
virtual void visit (TuplePatternItemsRanged &tuple_items) = 0;
virtual void visit (TuplePattern &pattern) = 0;
virtual void visit (GroupedPattern &pattern) = 0;
+ virtual void visit (SlicePatternItemsNoRest &items) = 0;
+ virtual void visit (SlicePatternItemsHasRest &items) = 0;
virtual void visit (SlicePattern &pattern) = 0;
virtual void visit (AltPattern &pattern) = 0;
@@ -235,6 +240,7 @@ public:
// special AST nodes for certain builtin macros such as `asm!()`
virtual void visit (FormatArgs &fmt) = 0;
+ virtual void visit (OffsetOf &fmt) = 0;
// TODO: rust-cond-compilation.h visiting? not currently used
};
@@ -264,7 +270,7 @@ public:
virtual void visit (AST::AttrInputLiteral &attr_input) override;
virtual void visit (AST::AttrInputMacro &attr_input) override;
virtual void visit (AST::MetaItemLitExpr &meta_item) override;
- virtual void visit (AST::MetaItemPathLit &meta_item) override;
+ virtual void visit (AST::MetaItemPathExpr &meta_item) override;
virtual void visit (AST::BorrowExpr &expr) override;
virtual void visit (AST::DereferenceExpr &expr) override;
virtual void visit (AST::ErrorPropagationExpr &expr) override;
@@ -293,6 +299,8 @@ public:
virtual void visit (AST::FieldAccessExpr &expr) override;
virtual void visit (AST::ClosureExprInner &expr) override;
virtual void visit (AST::BlockExpr &expr) override;
+ virtual void visit (AST::AnonConst &expr) override;
+ virtual void visit (AST::ConstBlock &expr) override;
virtual void visit (AST::ClosureExprInnerTyped &expr) override;
virtual void visit (AST::ContinueExpr &expr) override;
virtual void visit (AST::BreakExpr &expr) override;
@@ -303,6 +311,7 @@ public:
virtual void visit (AST::RangeFromToInclExpr &expr) override;
virtual void visit (AST::RangeToInclExpr &expr) override;
virtual void visit (AST::ReturnExpr &expr) override;
+ virtual void visit (AST::TryExpr &expr) override;
virtual void visit (AST::BoxExpr &expr) override;
virtual void visit (AST::UnsafeBlockExpr &expr) override;
virtual void visit (AST::LoopExpr &expr) override;
@@ -379,6 +388,8 @@ public:
virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override;
virtual void visit (AST::TuplePattern &pattern) override;
virtual void visit (AST::GroupedPattern &pattern) override;
+ virtual void visit (AST::SlicePatternItemsNoRest &items) override;
+ virtual void visit (AST::SlicePatternItemsHasRest &items) override;
virtual void visit (AST::SlicePattern &pattern) override;
virtual void visit (AST::AltPattern &pattern) override;
virtual void visit (AST::EmptyStmt &stmt) override;
@@ -402,6 +413,7 @@ public:
virtual void visit (AST::FunctionParam &param) override;
virtual void visit (AST::VariadicParam &param) override;
virtual void visit (AST::FormatArgs &fmt) override;
+ virtual void visit (AST::OffsetOf &fmt) override;
template <typename T> void visit (T &node) { node.accept_vis (*this); }
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 4e82be4..8e856fb 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "rust-operators.h"
#include "rust-dir-owner.h"
#include "rust-attribute-values.h"
+#include "rust-macro-invoc-lexer.h"
/* Compilation unit used for various AST-related functions that would make
* the headers too long if they were defined inline and don't receive any
@@ -249,27 +250,31 @@ Attribute::get_traits_to_derive ()
auto &input = get_attr_input ();
switch (input.get_attr_input_type ())
{
- case AST::AttrInput::META_ITEM: {
+ case AST::AttrInput::META_ITEM:
+ {
auto &meta = static_cast<AST::AttrInputMetaItemContainer &> (input);
for (auto &current : meta.get_items ())
{
// HACK: Find a better way to achieve the downcast.
switch (current->get_kind ())
{
- case AST::MetaItemInner::Kind::MetaItem: {
+ case AST::MetaItemInner::Kind::MetaItem:
+ {
// Let raw pointer go out of scope without freeing, it doesn't
// own the data anyway
auto meta_item
= static_cast<AST::MetaItem *> (current.get ());
switch (meta_item->get_item_kind ())
{
- case AST::MetaItem::ItemKind::Path: {
+ case AST::MetaItem::ItemKind::Path:
+ {
auto path
= static_cast<AST::MetaItemPath *> (meta_item);
result.push_back (path->get_path ());
}
break;
- case AST::MetaItem::ItemKind::Word: {
+ case AST::MetaItem::ItemKind::Word:
+ {
auto word = static_cast<AST::MetaWord *> (meta_item);
// Convert current word to path
current = std::make_unique<AST::MetaItemPath> (
@@ -283,7 +288,7 @@ Attribute::get_traits_to_derive ()
break;
case AST::MetaItem::ItemKind::ListPaths:
case AST::MetaItem::ItemKind::NameValueStr:
- case AST::MetaItem::ItemKind::PathLit:
+ case AST::MetaItem::ItemKind::PathExpr:
case AST::MetaItem::ItemKind::Seq:
case AST::MetaItem::ItemKind::ListNameValueStr:
default:
@@ -620,7 +625,7 @@ ConstantItem::as_string () const
{
std::string str = VisItem::as_string ();
- str += "const " + identifier;
+ str += "const " + identifier.as_string ();
// DEBUG: null pointer check
if (type == nullptr)
@@ -782,7 +787,8 @@ UseTreeGlob::as_string () const
return "*";
case GLOBAL:
return "::*";
- case PATH_PREFIXED: {
+ case PATH_PREFIXED:
+ {
std::string path_str = path.as_string ();
return path_str + "::*";
}
@@ -805,7 +811,8 @@ UseTreeList::as_string () const
case GLOBAL:
path_str = "::{";
break;
- case PATH_PREFIXED: {
+ case PATH_PREFIXED:
+ {
path_str = path.as_string () + "::{";
break;
}
@@ -1272,6 +1279,25 @@ BlockExpr::as_string () const
}
std::string
+AnonConst::as_string () const
+{
+ std::string str = "AnonConst: ";
+
+ if (kind == AnonConst::Kind::DeferredInference)
+ str += "_";
+ else
+ str += expr.value ()->as_string ();
+
+ return str;
+}
+
+std::string
+ConstBlock::as_string () const
+{
+ return "ConstBlock: " + expr.as_string ();
+}
+
+std::string
TraitImpl::as_string () const
{
std::string str = VisItem::as_string ();
@@ -1619,6 +1645,19 @@ ReturnExpr::as_string () const
}
std::string
+TryExpr::as_string () const
+{
+ /* TODO: find way to incorporate outer attrs - may have to represent in
+ * different style (i.e. something more like BorrowExpr: \n outer attrs) */
+
+ std::string str ("try ");
+
+ str += block_expr->as_string ();
+
+ return str;
+}
+
+std::string
RangeToExpr::as_string () const
{
return ".." + to->as_string ();
@@ -2714,7 +2753,7 @@ ImplTraitTypeOneBound::as_string () const
{
std::string str ("ImplTraitTypeOneBound: \n TraitBound: ");
- return str + trait_bound.as_string ();
+ return str + trait_bound->as_string ();
}
std::string
@@ -2736,7 +2775,7 @@ std::string
ArrayType::as_string () const
{
// TODO: rewrite to work with non-linearisable types and exprs
- return "[" + elem_type->as_string () + "; " + size->as_string () + "]";
+ return "[" + elem_type->as_string () + "; " + size.as_string () + "]";
}
std::string
@@ -3477,13 +3516,24 @@ DelimTokenTree::parse_to_meta_item () const
return new AttrInputMetaItemContainer (std::move (meta_items));
}
+AttributeParser::AttributeParser (
+ std::vector<std::unique_ptr<Token>> token_stream, int stream_start_pos)
+ : lexer (new MacroInvocLexer (std::move (token_stream))),
+ parser (new Parser<MacroInvocLexer> (*lexer))
+{
+ if (stream_start_pos)
+ lexer->skip_token (stream_start_pos - 1);
+}
+
+AttributeParser::~AttributeParser () {}
+
std::unique_ptr<MetaItemInner>
AttributeParser::parse_meta_item_inner ()
{
// if first tok not identifier, not a "special" case one
- if (peek_token ()->get_id () != IDENTIFIER)
+ if (lexer->peek_token ()->get_id () != IDENTIFIER)
{
- switch (peek_token ()->get_id ())
+ switch (lexer->peek_token ()->get_id ())
{
case CHAR_LITERAL:
case STRING_LITERAL:
@@ -3504,48 +3554,46 @@ AttributeParser::parse_meta_item_inner ()
return parse_path_meta_item ();
default:
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"unrecognised token '%s' in meta item",
- get_token_description (peek_token ()->get_id ()));
+ get_token_description (
+ lexer->peek_token ()->get_id ()));
return nullptr;
}
}
// else, check for path
- if (peek_token (1)->get_id () == SCOPE_RESOLUTION)
+ if (lexer->peek_token (1)->get_id () == SCOPE_RESOLUTION)
{
// path
return parse_path_meta_item ();
}
- auto ident = peek_token ()->as_string ();
- auto ident_locus = peek_token ()->get_locus ();
+ auto ident = lexer->peek_token ()->get_str ();
+ auto ident_locus = lexer->peek_token ()->get_locus ();
- if (is_end_meta_item_tok (peek_token (1)->get_id ()))
+ if (is_end_meta_item_tok (lexer->peek_token (1)->get_id ()))
{
// meta word syntax
- skip_token ();
+ lexer->skip_token ();
return std::unique_ptr<MetaWord> (new MetaWord (ident, ident_locus));
}
- if (peek_token (1)->get_id () == EQUAL)
+ if (lexer->peek_token (1)->get_id () == EQUAL)
{
// maybe meta name value str syntax - check next 2 tokens
- if (peek_token (2)->get_id () == STRING_LITERAL
- && is_end_meta_item_tok (peek_token (3)->get_id ()))
+ if (lexer->peek_token (2)->get_id () == STRING_LITERAL
+ && is_end_meta_item_tok (lexer->peek_token (3)->get_id ()))
{
// meta name value str syntax
- auto &value_tok = peek_token (2);
- auto value = value_tok->as_string ();
+ const_TokenPtr value_tok = lexer->peek_token (2);
+ auto value = value_tok->get_str ();
auto locus = value_tok->get_locus ();
- skip_token (2);
-
- // remove the quotes from the string value
- std::string raw_value = unquote_string (std::move (value));
+ lexer->skip_token (2);
return std::unique_ptr<MetaNameValueStr> (
- new MetaNameValueStr (ident, ident_locus, std::move (raw_value),
+ new MetaNameValueStr (ident, ident_locus, std::move (value),
locus));
}
else
@@ -3555,16 +3603,16 @@ AttributeParser::parse_meta_item_inner ()
}
}
- if (peek_token (1)->get_id () != LEFT_PAREN)
+ if (lexer->peek_token (1)->get_id () != LEFT_PAREN)
{
- rust_error_at (peek_token (1)->get_locus (),
+ rust_error_at (lexer->peek_token (1)->get_locus (),
"unexpected token '%s' after identifier in attribute",
- get_token_description (peek_token (1)->get_id ()));
+ get_token_description (lexer->peek_token (1)->get_id ()));
return nullptr;
}
// is it one of those special cases like not?
- if (peek_token ()->get_id () == IDENTIFIER)
+ if (lexer->peek_token ()->get_id () == IDENTIFIER)
{
return parse_path_meta_item ();
}
@@ -3643,49 +3691,46 @@ AttributeParser::is_end_meta_item_tok (TokenId id) const
std::unique_ptr<MetaItem>
AttributeParser::parse_path_meta_item ()
{
- SimplePath path = parse_simple_path ();
+ SimplePath path = parser->parse_simple_path ();
if (path.is_empty ())
{
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"failed to parse simple path in attribute");
return nullptr;
}
- switch (peek_token ()->get_id ())
+ switch (lexer->peek_token ()->get_id ())
{
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
std::vector<std::unique_ptr<MetaItemInner>> meta_items
= parse_meta_item_seq ();
return std::unique_ptr<MetaItemSeq> (
new MetaItemSeq (std::move (path), std::move (meta_items)));
}
- case EQUAL: {
- skip_token ();
+ case EQUAL:
+ {
+ lexer->skip_token ();
- location_t locus = peek_token ()->get_locus ();
- Literal lit = parse_literal ();
- if (lit.is_error ())
- {
- rust_error_at (peek_token ()->get_locus (),
- "failed to parse literal in attribute");
- return nullptr;
- }
- LiteralExpr expr (std::move (lit), {}, locus);
- // stream_pos++;
- /* shouldn't be required anymore due to parsing literal actually
- * skipping the token */
- return std::unique_ptr<MetaItemPathLit> (
- new MetaItemPathLit (std::move (path), std::move (expr)));
+ std::unique_ptr<Expr> expr = parser->parse_expr ();
+
+ // handle error
+ // parse_expr should already emit an error and return nullptr
+ if (!expr)
+ return nullptr;
+
+ return std::unique_ptr<MetaItemPathExpr> (
+ new MetaItemPathExpr (std::move (path), std::move (expr)));
}
case COMMA:
// just simple path
return std::unique_ptr<MetaItemPath> (
new MetaItemPath (std::move (path)));
default:
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"unrecognised token '%s' in meta item",
- get_token_description (peek_token ()->get_id ()));
+ get_token_description (lexer->peek_token ()->get_id ()));
return nullptr;
}
}
@@ -3695,41 +3740,41 @@ AttributeParser::parse_path_meta_item ()
std::vector<std::unique_ptr<MetaItemInner>>
AttributeParser::parse_meta_item_seq ()
{
- int vec_length = token_stream.size ();
std::vector<std::unique_ptr<MetaItemInner>> meta_items;
- if (peek_token ()->get_id () != LEFT_PAREN)
+ if (lexer->peek_token ()->get_id () != LEFT_PAREN)
{
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"missing left paren in delim token tree");
return {};
}
- skip_token ();
+ lexer->skip_token ();
- while (stream_pos < vec_length && peek_token ()->get_id () != RIGHT_PAREN)
+ while (lexer->peek_token ()->get_id () != END_OF_FILE
+ && lexer->peek_token ()->get_id () != RIGHT_PAREN)
{
std::unique_ptr<MetaItemInner> inner = parse_meta_item_inner ();
if (inner == nullptr)
{
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"failed to parse inner meta item in attribute");
return {};
}
meta_items.push_back (std::move (inner));
- if (peek_token ()->get_id () != COMMA)
+ if (lexer->peek_token ()->get_id () != COMMA)
break;
- skip_token ();
+ lexer->skip_token ();
}
- if (peek_token ()->get_id () != RIGHT_PAREN)
+ if (lexer->peek_token ()->get_id () != RIGHT_PAREN)
{
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"missing right paren in delim token tree");
return {};
}
- skip_token ();
+ lexer->skip_token ();
return meta_items;
}
@@ -3752,130 +3797,19 @@ DelimTokenTree::to_token_stream () const
return tokens;
}
-Literal
-AttributeParser::parse_literal ()
-{
- const std::unique_ptr<Token> &tok = peek_token ();
- switch (tok->get_id ())
- {
- case CHAR_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::CHAR, tok->get_type_hint ());
- case STRING_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::STRING,
- tok->get_type_hint ());
- case BYTE_CHAR_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::BYTE, tok->get_type_hint ());
- case BYTE_STRING_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::BYTE_STRING,
- tok->get_type_hint ());
- case RAW_STRING_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::RAW_STRING,
- tok->get_type_hint ());
- case INT_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::INT, tok->get_type_hint ());
- case FLOAT_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::FLOAT, tok->get_type_hint ());
- case TRUE_LITERAL:
- skip_token ();
- return Literal ("true", Literal::BOOL, tok->get_type_hint ());
- case FALSE_LITERAL:
- skip_token ();
- return Literal ("false", Literal::BOOL, tok->get_type_hint ());
- default:
- rust_error_at (tok->get_locus (), "expected literal - found '%s'",
- get_token_description (tok->get_id ()));
- return Literal::create_error ();
- }
-}
-
-SimplePath
-AttributeParser::parse_simple_path ()
-{
- bool has_opening_scope_res = false;
- if (peek_token ()->get_id () == SCOPE_RESOLUTION)
- {
- has_opening_scope_res = true;
- skip_token ();
- }
-
- std::vector<SimplePathSegment> segments;
-
- SimplePathSegment segment = parse_simple_path_segment ();
- if (segment.is_error ())
- {
- rust_error_at (
- peek_token ()->get_locus (),
- "failed to parse simple path segment in attribute simple path");
- return SimplePath::create_empty ();
- }
- segments.push_back (std::move (segment));
-
- while (peek_token ()->get_id () == SCOPE_RESOLUTION)
- {
- skip_token ();
-
- SimplePathSegment segment = parse_simple_path_segment ();
- if (segment.is_error ())
- {
- rust_error_at (
- peek_token ()->get_locus (),
- "failed to parse simple path segment in attribute simple path");
- return SimplePath::create_empty ();
- }
- segments.push_back (std::move (segment));
- }
- segments.shrink_to_fit ();
-
- return SimplePath (std::move (segments), has_opening_scope_res);
-}
-
-SimplePathSegment
-AttributeParser::parse_simple_path_segment ()
-{
- const std::unique_ptr<Token> &tok = peek_token ();
- switch (tok->get_id ())
- {
- case IDENTIFIER:
- skip_token ();
- return SimplePathSegment (tok->as_string (), tok->get_locus ());
- case SUPER:
- skip_token ();
- return SimplePathSegment ("super", tok->get_locus ());
- case SELF:
- skip_token ();
- return SimplePathSegment ("self", tok->get_locus ());
- case CRATE:
- skip_token ();
- return SimplePathSegment ("crate", tok->get_locus ());
- case DOLLAR_SIGN:
- if (peek_token (1)->get_id () == CRATE)
- {
- skip_token (1);
- return SimplePathSegment ("$crate", tok->get_locus ());
- }
- gcc_fallthrough ();
- default:
- rust_error_at (tok->get_locus (),
- "unexpected token '%s' in simple path segment",
- get_token_description (tok->get_id ()));
- return SimplePathSegment::create_error ();
- }
-}
-
std::unique_ptr<MetaItemLitExpr>
AttributeParser::parse_meta_item_lit ()
{
- location_t locus = peek_token ()->get_locus ();
- LiteralExpr lit_expr (parse_literal (), {}, locus);
+ std::unique_ptr<LiteralExpr> lit_expr = parser->parse_literal_expr ({});
+
+ // TODO: return nullptr instead?
+ if (!lit_expr)
+ lit_expr = std::unique_ptr<LiteralExpr> (
+ new LiteralExpr (Literal::create_error (), {},
+ lexer->peek_token ()->get_locus ()));
+
return std::unique_ptr<MetaItemLitExpr> (
- new MetaItemLitExpr (std::move (lit_expr)));
+ new MetaItemLitExpr (std::move (*lit_expr)));
}
bool
@@ -4084,10 +4018,12 @@ MetaNameValueStr::check_cfg_predicate (const Session &session) const
}
bool
-MetaItemPathLit::check_cfg_predicate (const Session &session) const
+MetaItemPathExpr::check_cfg_predicate (const Session &session) const
{
+ // FIXME: Accept path expressions
+ rust_assert (expr->is_literal ());
return session.options.target_data.has_key_value_pair (path.as_string (),
- lit.as_string ());
+ expr->as_string ());
}
std::vector<std::unique_ptr<Token>>
@@ -4175,8 +4111,10 @@ MetaListNameValueStr::to_attribute () const
}
Attribute
-MetaItemPathLit::to_attribute () const
+MetaItemPathExpr::to_attribute () const
{
+ rust_assert (expr->is_literal ());
+ auto &lit = static_cast<LiteralExpr &> (*expr);
return Attribute (path, std::unique_ptr<AttrInputLiteral> (
new AttrInputLiteral (lit)));
}
@@ -4279,11 +4217,12 @@ AttrInputMacro::AttrInputMacro (const AttrInputMacro &oth)
: macro (oth.macro->clone_macro_invocation_impl ())
{}
-void
+AttrInputMacro &
AttrInputMacro::operator= (const AttrInputMacro &oth)
{
macro = std::unique_ptr<MacroInvocation> (
oth.macro->clone_macro_invocation_impl ());
+ return *this;
}
/* Visitor implementations - these are short but inlining can't happen anyway
@@ -4345,7 +4284,7 @@ MetaItemLitExpr::accept_vis (ASTVisitor &vis)
}
void
-MetaItemPathLit::accept_vis (ASTVisitor &vis)
+MetaItemPathExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
@@ -4513,6 +4452,18 @@ BlockExpr::accept_vis (ASTVisitor &vis)
}
void
+AnonConst::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstBlock::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
ClosureExprInnerTyped::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
@@ -4573,6 +4524,12 @@ ReturnExpr::accept_vis (ASTVisitor &vis)
}
void
+TryExpr::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
UnsafeBlockExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
@@ -5010,6 +4967,12 @@ FormatArgs::accept_vis (ASTVisitor &vis)
vis.visit (*this);
}
+void
+OffsetOf::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
std::string
FormatArgs::as_string () const
{
@@ -5017,6 +4980,12 @@ FormatArgs::as_string () const
return "FormatArgs";
}
+std::string
+OffsetOf::as_string () const
+{
+ return "OffsetOf(" + type->as_string () + ", " + field.as_string () + ")";
+}
+
location_t
FormatArgs::get_locus () const
{
@@ -5047,7 +5016,8 @@ FormatArgs::get_outer_attrs ()
rust_unreachable ();
}
-void FormatArgs::set_outer_attrs (std::vector<Attribute>)
+void
+FormatArgs::set_outer_attrs (std::vector<Attribute>)
{
rust_unreachable ();
}
@@ -5060,6 +5030,24 @@ FormatArgs::clone_expr_impl () const
return new FormatArgs (*this);
}
+std::vector<Attribute> &
+OffsetOf::get_outer_attrs ()
+{
+ rust_unreachable ();
+}
+
+void
+OffsetOf::set_outer_attrs (std::vector<Attribute>)
+{
+ rust_unreachable ();
+}
+
+Expr *
+OffsetOf::clone_expr_impl () const
+{
+ return new OffsetOf (*this);
+}
+
} // namespace AST
std::ostream &
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index aa6ad50..2d2c5d0 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -62,13 +62,14 @@ public:
return ident == other.ident;
}
+ operator const std::string & () const { return ident; }
+
private:
std::string ident;
location_t loc;
};
-std::ostream &
-operator<< (std::ostream &os, Identifier const &i);
+std::ostream &operator<< (std::ostream &os, Identifier const &i);
namespace AST {
// foward decl: ast visitor
@@ -82,6 +83,38 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
};
+/**
+ * Base function for reconstructing and asserting that the new NodeId is
+ * different from the old NodeId. It then wraps the given pointer into a unique
+ * pointer and returns it.
+ */
+template <typename T>
+std::unique_ptr<T>
+reconstruct_base (const T *instance)
+{
+ auto *reconstructed = instance->reconstruct_impl ();
+
+ rust_assert (reconstructed->get_node_id () != instance->get_node_id ());
+
+ return std::unique_ptr<T> (reconstructed);
+}
+
+/**
+ * Reconstruct multiple items in a vector
+ */
+template <typename T>
+std::vector<std::unique_ptr<T>>
+reconstruct_vec (const std::vector<std::unique_ptr<T>> &to_reconstruct)
+{
+ std::vector<std::unique_ptr<T>> reconstructed;
+ reconstructed.reserve (to_reconstruct.size ());
+
+ for (const auto &elt : to_reconstruct)
+ reconstructed.emplace_back (std::unique_ptr<T> (elt->reconstruct_impl ()));
+
+ return reconstructed;
+}
+
// Delimiter types - used in macros and whatever.
enum DelimType
{
@@ -250,6 +283,7 @@ public:
std::vector<std::unique_ptr<Token>> to_token_stream () const override;
TokenId get_id () const { return tok_ref->get_id (); }
+ bool has_str () const { return tok_ref->has_str (); }
const std::string &get_str () const { return tok_ref->get_str (); }
location_t get_locus () const { return tok_ref->get_locus (); }
@@ -403,15 +437,15 @@ class SimplePath
public:
// Constructor
- SimplePath (std::vector<SimplePathSegment> path_segments,
- bool has_opening_scope_resolution = false,
- location_t locus = UNDEF_LOCATION)
+ explicit SimplePath (std::vector<SimplePathSegment> path_segments,
+ bool has_opening_scope_resolution = false,
+ location_t locus = UNDEF_LOCATION)
: opening_scope_resolution (has_opening_scope_resolution),
segments (std::move (path_segments)), locus (locus),
node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
- SimplePath (Identifier ident)
+ explicit SimplePath (Identifier ident)
: opening_scope_resolution (false),
segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}),
locus (ident.get_locus ()),
@@ -1039,7 +1073,7 @@ public:
Path,
Word,
NameValueStr,
- PathLit,
+ PathExpr,
Seq,
ListPaths,
ListNameValueStr,
@@ -1057,7 +1091,7 @@ public:
class MetaItemLitExpr;
// Forward decl - defined in rust-expr.h
-class MetaItemPathLit;
+class MetaItemPathExpr;
// Forward decl - defined in rust-macro.h
class MetaItemPath;
@@ -1256,6 +1290,8 @@ public:
FieldAccess,
Closure,
Block,
+ ConstExpr,
+ ConstBlock,
Continue,
Break,
Range,
@@ -1272,6 +1308,7 @@ public:
LlvmInlineAsm,
Identifier,
FormatArgs,
+ OffsetOf,
MacroInvocation,
Borrow,
Dereference,
@@ -1283,6 +1320,7 @@ public:
TypeCast,
Assignment,
CompoundAssignment,
+ Try,
};
virtual Kind get_expr_kind () const = 0;
@@ -1477,6 +1515,10 @@ public:
return std::unique_ptr<Type> (clone_type_impl ());
}
+ // Similar to `clone_type`, but generates a new instance of the node with a
+ // different NodeId
+ std::unique_ptr<Type> reconstruct () const { return reconstruct_base (this); }
+
// virtual destructor
virtual ~Type () {}
@@ -1495,11 +1537,13 @@ public:
virtual location_t get_locus () const = 0;
NodeId get_node_id () const { return node_id; }
+ virtual Type *reconstruct_impl () const = 0;
protected:
Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
+ Type (NodeId node_id) : node_id (node_id) {}
- // Clone function implementation as pure virtual method
+ // Clone and reconstruct function implementations as pure virtual methods
virtual Type *clone_type_impl () const = 0;
NodeId node_id;
@@ -1515,6 +1559,13 @@ public:
return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ());
}
+ std::unique_ptr<TypeNoBounds> reconstruct () const
+ {
+ return reconstruct_base (this);
+ }
+
+ virtual TypeNoBounds *reconstruct_impl () const override = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0;
@@ -1549,6 +1600,11 @@ public:
return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ());
}
+ std::unique_ptr<TypeParamBound> reconstruct () const
+ {
+ return reconstruct_base (this);
+ }
+
virtual std::string as_string () const = 0;
NodeId get_node_id () const { return node_id; }
@@ -1557,10 +1613,14 @@ public:
virtual TypeParamBoundType get_bound_type () const = 0;
+ virtual TypeParamBound *reconstruct_impl () const = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
+ TypeParamBound () : node_id (Analysis::Mappings::get ().get_next_node_id ())
+ {}
TypeParamBound (NodeId node_id) : node_id (node_id) {}
NodeId node_id;
@@ -1622,6 +1682,10 @@ protected:
{
return new Lifetime (node_id, lifetime_type, lifetime_name, locus);
}
+ Lifetime *reconstruct_impl () const override
+ {
+ return new Lifetime (lifetime_type, lifetime_name, locus);
+ }
};
/* Base generic parameter in AST. Abstract - can be represented by a Lifetime
diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h
index 3684092..2893e7b 100644
--- a/gcc/rust/ast/rust-builtin-ast-nodes.h
+++ b/gcc/rust/ast/rust-builtin-ast-nodes.h
@@ -225,6 +225,59 @@ protected:
virtual Expr *clone_expr_impl () const override;
};
+/**
+ * The node associated with the builtin offset_of!() macro
+ */
+class OffsetOf : public Expr
+{
+public:
+ OffsetOf (std::unique_ptr<Type> &&type, Identifier field, location_t loc)
+ : type (std::move (type)), field (field), loc (loc)
+ {}
+
+ OffsetOf (const OffsetOf &other)
+ : type (other.type->clone_type ()), field (other.field), loc (other.loc),
+ marked_for_strip (other.marked_for_strip)
+ {}
+
+ OffsetOf &operator= (const OffsetOf &other)
+ {
+ type = other.type->clone_type ();
+ field = other.field;
+ loc = other.loc;
+ marked_for_strip = other.marked_for_strip;
+
+ return *this;
+ }
+
+ void accept_vis (AST::ASTVisitor &vis) override;
+
+ virtual location_t get_locus () const override { return loc; }
+ const Type &get_type () const { return *type; }
+ Type &get_type () { return *type; }
+ const Identifier &get_field () const { return field; }
+
+ bool is_expr_without_block () const override { return false; }
+
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+
+ std::string as_string () const override;
+
+ std::vector<Attribute> &get_outer_attrs () override;
+ void set_outer_attrs (std::vector<Attribute>) override;
+ Expr *clone_expr_impl () const override;
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::OffsetOf; }
+
+private:
+ std::unique_ptr<Type> type;
+ Identifier field;
+
+ location_t loc;
+ bool marked_for_strip = false;
+};
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc
index cd6be7f..306c6f7 100644
--- a/gcc/rust/ast/rust-collect-lang-items.cc
+++ b/gcc/rust/ast/rust-collect-lang-items.cc
@@ -109,5 +109,29 @@ CollectLangItems::visit (AST::EnumItem &item)
DefaultASTVisitor::visit (item);
}
+void
+CollectLangItems::visit (AST::EnumItemTuple &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
+void
+CollectLangItems::visit (AST::EnumItemStruct &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
+void
+CollectLangItems::visit (AST::EnumItemDiscriminant &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-collect-lang-items.h b/gcc/rust/ast/rust-collect-lang-items.h
index ddb34a9..ddc7b51 100644
--- a/gcc/rust/ast/rust-collect-lang-items.h
+++ b/gcc/rust/ast/rust-collect-lang-items.h
@@ -50,6 +50,9 @@ public:
void visit (AST::Function &item) override;
void visit (AST::StructStruct &item) override;
void visit (AST::EnumItem &item) override;
+ void visit (AST::EnumItemTuple &item) override;
+ void visit (AST::EnumItemStruct &item) override;
+ void visit (AST::EnumItemDiscriminant &item) override;
private:
template <typename T> void maybe_add_lang_item (const T &item);
diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h
index 610b904..56a5646 100644
--- a/gcc/rust/ast/rust-cond-compilation.h
+++ b/gcc/rust/ast/rust-cond-compilation.h
@@ -42,8 +42,8 @@ public:
protected:
// Clone function impl to be overriden in base classes
- virtual ConfigurationPredicate *
- clone_configuration_predicate_impl () const = 0;
+ virtual ConfigurationPredicate *clone_configuration_predicate_impl () const
+ = 0;
};
// A configuration option - true if option is set, false if option is not set.
diff --git a/gcc/rust/ast/rust-desugar-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc
new file mode 100644
index 0000000..bca14ee
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-apit.cc
@@ -0,0 +1,522 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-desugar-apit.h"
+#include "rust-ast.h"
+#include "rust-type.h"
+
+namespace Rust {
+namespace AST {
+
+class DesugarApitType : public DefaultASTVisitor
+{
+ using DefaultASTVisitor::visit;
+
+public:
+ static std::pair<AST::Type *, std::vector<std::unique_ptr<GenericParam>>>
+ Desugar (AST::Type &type)
+ {
+ DesugarApitType visitor (&type);
+ type.accept_vis (visitor);
+ rust_assert (visitor.translated != nullptr);
+ return std::make_pair (visitor.translated,
+ std::move (visitor.implicit_generic_params));
+ }
+
+ // Generate a unique impl trait parameter name
+ static Identifier get_impl_name ()
+ {
+ static size_t counter = 0;
+ return Identifier ("Impl_" + std::to_string (counter++));
+ }
+
+ // these can hold other types
+ void visit (AST::TupleType &tuple) override
+ {
+ for (auto &elem : tuple.get_elems ())
+ {
+ auto &type = *elem.get ();
+ auto desugar = Desugar (type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ continue;
+
+ if (tt != elem.get ())
+ elem = std::unique_ptr<Type> (tt);
+
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+ }
+
+ void visit (AST::ArrayType &type) override
+ {
+ auto &element_type = type.get_element_type ();
+ auto desugar = Desugar (*element_type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ if (tt != element_type.get ())
+ element_type = std::unique_ptr<AST::Type> (tt);
+
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ void visit (AST::ReferenceType &type) override
+ {
+ // Get a reference to the current type for in-place modification
+ auto &referenced_type = type.get_type_referenced ();
+ auto desugar = Desugar (referenced_type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ // Update the reference type's contents rather than creating a new one
+ if (&referenced_type != tt)
+ {
+ std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds (
+ static_cast<AST::TypeNoBounds *> (tt));
+ type.get_type_ptr () = std::move (new_type_no_bounds);
+ }
+
+ // Collect all the implicit generic parameters we found
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ void visit (AST::RawPointerType &type) override
+ {
+ auto &pointed_type = type.get_type_pointed_to ();
+ auto desugar = Desugar (pointed_type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ // Update the pointer's inner type directly using the new accessor
+ if (&pointed_type != tt)
+ {
+ std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds (
+ static_cast<AST::TypeNoBounds *> (tt));
+ type.get_type_ptr () = std::move (new_type_no_bounds);
+ }
+
+ // Collect all the implicit generic parameters we found
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ void visit (AST::SliceType &type) override
+ {
+ auto &element_type = type.get_elem_type ();
+ auto desugar = Desugar (element_type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ if (&element_type != tt)
+ {
+ std::unique_ptr<AST::Type> new_elem_type (tt);
+ type.get_elem_type_ptr () = std::move (new_elem_type);
+ }
+
+ // Collect all the implicit generic parameters we found
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ void visit (AST::ParenthesisedType &type) override
+ {
+ auto &inner_type_ptr = type.get_type_in_parens ();
+ auto desugar = Desugar (*inner_type_ptr);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ if (inner_type_ptr.get () != tt)
+ {
+ std::unique_ptr<AST::Type> new_inner_type (tt);
+ inner_type_ptr = std::move (new_inner_type);
+ }
+
+ // Collect all the implicit generic parameters we found
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ // this is where the desugar happens
+ void visit (AST::ImplTraitType &type) override
+ {
+ // Generate a unique name using the static method
+ auto ident = get_impl_name ();
+
+ // Create a type path for the new generic parameter
+ // Create a SimplePathSegment with the identifier string
+ auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ());
+ // Create a vector of SimplePathSegments for SimplePath constructor
+ std::vector<SimplePathSegment> simple_segs = {simple_seg};
+ // Create a SimplePath
+ auto simple_path = SimplePath (simple_segs, false, type.get_locus ());
+
+ // Convert to TypePath by creating path segments
+ std::vector<std::unique_ptr<TypePathSegment>> segments;
+ segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment (
+ PathIdentSegment (ident.as_string (), type.get_locus ()), false,
+ type.get_locus ())));
+
+ // Create TypePath from segments
+ auto type_path
+ = new TypePath (std::move (segments), type.get_locus (), false);
+
+ // Convert bounds from impl trait to generic parameter bounds
+ std::vector<std::unique_ptr<TypeParamBound>> bounds;
+ for (auto &bound : type.get_type_param_bounds ())
+ bounds.push_back (bound->clone_type_param_bound ());
+
+ // Create the new generic parameter
+ auto generic_param = std::unique_ptr<TypeParam> (
+ new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {},
+ true /*from impl trait*/));
+
+ // Store the generic parameter to be added to the function signature
+ implicit_generic_params.push_back (std::move (generic_param));
+
+ // Replace impl trait with the new type parameter
+ translated = type_path;
+ }
+
+ void visit (AST::ImplTraitTypeOneBound &type) override
+ {
+ // Generate a unique name using the static method
+ auto ident = get_impl_name ();
+
+ // Create a type path for the new generic parameter
+ // Create a SimplePathSegment with the identifier string
+ auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ());
+ // Create a vector of SimplePathSegments for SimplePath constructor
+ std::vector<SimplePathSegment> simple_segs = {simple_seg};
+ // Create a SimplePath
+ auto simple_path = SimplePath (simple_segs, false, type.get_locus ());
+
+ // Convert to TypePath by creating path segments
+ std::vector<std::unique_ptr<TypePathSegment>> segments;
+ segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment (
+ PathIdentSegment (ident.as_string (), type.get_locus ()), false,
+ type.get_locus ())));
+
+ // Create TypePath from segments
+ auto type_path
+ = new TypePath (std::move (segments), type.get_locus (), false);
+
+ // Convert the bound to a generic parameter bound
+ std::vector<std::unique_ptr<TypeParamBound>> bounds;
+ bounds.push_back (std::move (type.get_trait_bound ()));
+
+ // Create the new generic parameter
+ auto generic_param = std::unique_ptr<TypeParam> (
+ new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {},
+ true /*from impl trait*/));
+
+ // Store the generic parameter to be added to the function signature
+ implicit_generic_params.push_back (std::move (generic_param));
+
+ // Replace impl trait with the new type parameter
+ translated = type_path;
+ }
+
+private:
+ DesugarApitType (AST::Type *base)
+ : translated (base), implicit_generic_params ()
+ {}
+
+ AST::Type *translated;
+ std::vector<std::unique_ptr<GenericParam>> implicit_generic_params;
+};
+
+// ---------
+
+class ApitBoundProcessor
+{
+public:
+ ApitBoundProcessor (
+ WhereClause &where_clause,
+ std::vector<std::unique_ptr<GenericParam>> &generic_params)
+ : where_clause (where_clause), generic_params (generic_params)
+ {}
+
+ void go (std::vector<std::unique_ptr<GenericParam>> &implicit_generics)
+ {
+ // some desugars are more complex so imagine this case
+ //
+ // pub fn foo(_value: impl Bar<Baz = impl Foo>) -> i32 {
+ // 15
+ // }
+ //
+ // this needs to become:
+ //
+ // pub fn foo<T, U>(_value: T) -> i32
+ // where
+ // T: Bar<Baz = U>,
+ // U: Foo,
+ // {
+ // 15
+ // }
+ //
+ // so we need to walk all the implicit generics and the trait bounds paths
+ // for more generics
+
+ for (auto &implicit_generic : implicit_generics)
+ {
+ switch (implicit_generic->get_kind ())
+ {
+ case GenericParam::Kind::Type:
+ {
+ TypeParam &p
+ = *static_cast<TypeParam *> (implicit_generic.get ());
+
+ process_type_param (p);
+ generic_params.push_back (std::move (implicit_generic));
+ for (auto &synth : synthetic_params)
+ generic_params.push_back (std::move (synth));
+ synthetic_params.clear ();
+ }
+ break;
+
+ default:
+ generic_params.push_back (std::move (implicit_generic));
+ break;
+ }
+ }
+ }
+
+private:
+ void process_type_param (TypeParam &p)
+ {
+ auto &bounds = p.get_type_param_bounds ();
+ std::vector<size_t> bounds_to_remove;
+ for (size_t i = 0; i < bounds.size (); i++)
+ {
+ auto &tb = bounds[i];
+ switch (tb->get_bound_type ())
+ {
+ case TypeParamBound::TypeParamBoundType::TRAIT:
+ {
+ TraitBound &ttb = *static_cast<TraitBound *> (tb.get ());
+ TypePath &path = ttb.get_type_path ();
+ bool deusgared = process_type_path (p, ttb, path);
+ if (deusgared)
+ bounds_to_remove.push_back (i);
+ }
+
+ default:
+ break;
+ }
+ }
+ for (auto it = bounds_to_remove.rbegin (); it != bounds_to_remove.rend ();
+ ++it)
+ bounds.erase (bounds.begin () + *it);
+ }
+
+ bool process_type_path (TypeParam &p, TraitBound &parent, TypePath &path)
+ {
+ bool desugared = false;
+ for (auto &segment : path.get_segments ())
+ {
+ switch (segment->get_type ())
+ {
+ case TypePathSegment::SegmentType::GENERIC:
+ {
+ TypePathSegmentGeneric &seg
+ = *static_cast<TypePathSegmentGeneric *> (segment.get ());
+ desugared |= process_generic_segment (p, parent, path, seg);
+ }
+
+ default:
+ break;
+ }
+ }
+ return desugared;
+ }
+
+ bool process_generic_segment (TypeParam &p, TraitBound &parent,
+ TypePath &path, TypePathSegmentGeneric &seg)
+ {
+ // we need to look for any impl types as default arguments in any generics
+ // and remove this index from the generic arguments by using a where
+ // constraint instead
+
+ std::vector<std::unique_ptr<WhereClauseItem>> new_clauses;
+ GenericArgs &generic_args = seg.get_generic_args ();
+ std::vector<std::reference_wrapper<const GenericArgsBinding>>
+ bindings_desugared;
+ std::vector<GenericArgsBinding> &bindings
+ = generic_args.get_binding_args ();
+
+ for (auto &generic : bindings)
+ {
+ auto &t = generic.get_type ();
+ auto translated = DesugarApitType::Desugar (t);
+ auto tt = translated.first;
+
+ auto &implicit_generics = translated.second;
+ if (implicit_generics.empty ())
+ continue;
+
+ if (tt != &t)
+ {
+ bindings_desugared.push_back (generic);
+ generic.get_type_ptr () = std::unique_ptr<Type> (tt);
+ }
+
+ for (auto &implicit_generic : implicit_generics)
+ {
+ switch (implicit_generic->get_kind ())
+ {
+ case GenericParam::Kind::Type:
+ {
+ TypeParam &tp
+ = *static_cast<TypeParam *> (implicit_generic.get ());
+
+ std::vector<std::unique_ptr<TypeParamBound>>
+ type_param_bounds;
+ for (auto &b : tp.get_type_param_bounds ())
+ type_param_bounds.push_back (std::move (b));
+ tp.get_type_param_bounds ().clear ();
+
+ // add synthetic parameter for this
+ synthetic_params.push_back (std::move (implicit_generic));
+
+ auto bound_type_path
+ = get_type_for_identifier (tp.get_type_representation ());
+
+ auto clause = new TypeBoundWhereClauseItem (
+ {}, std::move (bound_type_path),
+ std::move (type_param_bounds), tp.get_locus ());
+ std::unique_ptr<WhereClauseItem> clause_item
+ = std::unique_ptr<WhereClauseItem> (clause);
+ new_clauses.push_back (std::move (clause_item));
+ }
+ break;
+
+ default:
+ synthetic_params.push_back (std::move (implicit_generic));
+ break;
+ }
+ }
+ }
+
+ std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
+ auto bound = std::unique_ptr<TypeParamBound> (new TraitBound (parent));
+ type_param_bounds.push_back (std::move (bound));
+ auto parent_type_path
+ = get_type_for_identifier (p.get_type_representation ());
+ auto clause
+ = new TypeBoundWhereClauseItem ({}, std::move (parent_type_path),
+ std::move (type_param_bounds),
+ parent.get_locus ());
+ std::unique_ptr<WhereClauseItem> clause_item
+ = std::unique_ptr<WhereClauseItem> (clause);
+ where_clause.get_items ().push_back (std::move (clause_item));
+
+ for (auto &where_item : new_clauses)
+ where_clause.get_items ().push_back (std::move (where_item));
+
+ return !bindings_desugared.empty ();
+ }
+
+ static std::unique_ptr<Type> get_type_for_identifier (const Identifier &ident)
+ {
+ auto simple_seg
+ = SimplePathSegment (ident.as_string (), ident.get_locus ());
+ std::vector<SimplePathSegment> simple_segs = {simple_seg};
+ auto simple_path = SimplePath (simple_segs, false, ident.get_locus ());
+ std::vector<std::unique_ptr<TypePathSegment>> segments;
+ segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment (
+ PathIdentSegment (ident.as_string (), ident.get_locus ()), false,
+ ident.get_locus ())));
+ auto type_path = new TypePath (std::move (segments), ident.get_locus ());
+ return std::unique_ptr<Type> (type_path);
+ }
+
+private:
+ WhereClause &where_clause;
+ std::vector<std::unique_ptr<GenericParam>> &generic_params;
+
+ // mutates
+ std::vector<std::unique_ptr<GenericParam>> synthetic_params;
+};
+
+// ---------
+
+DesugarApit::DesugarApit () {}
+
+void
+DesugarApit::go (AST::Crate &crate)
+{
+ DefaultASTVisitor::visit (crate);
+}
+
+void
+DesugarApit::visit (AST::Function &function)
+{
+ if (!function.has_function_params ())
+ return;
+
+ auto &fn_params = function.get_function_params ();
+ for (auto &param : fn_params)
+ {
+ if (param->is_variadic () || param->is_self ())
+ continue;
+
+ auto *p = param.get ();
+ auto &fp = *static_cast<AST::FunctionParam *> (p);
+ auto &type = fp.get_type ();
+
+ auto translated = DesugarApitType::Desugar (type);
+ auto tt = translated.first;
+
+ auto &implicit_generics = translated.second;
+ if (implicit_generics.empty ())
+ continue;
+
+ if (fp.get_type_ptr ().get () != tt)
+ {
+ fp.get_type_ptr () = std::unique_ptr<AST::Type> (tt);
+ }
+
+ ApitBoundProcessor processor (function.get_where_clause (),
+ function.get_generic_params ());
+ processor.go (implicit_generics);
+ }
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-apit.h b/gcc/rust/ast/rust-desugar-apit.h
new file mode 100644
index 0000000..07c25e2
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-apit.h
@@ -0,0 +1,42 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_DESUGAR_APIT_H
+#define RUST_DESUGAR_APIT_H
+
+#include "rust-ast-visitor.h"
+
+namespace Rust {
+namespace AST {
+
+class DesugarApit : public DefaultASTVisitor
+{
+ using DefaultASTVisitor::visit;
+
+public:
+ DesugarApit ();
+ void go (AST::Crate &);
+
+private:
+ void visit (AST::Function &) override;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DESUGAR_APIT_H
diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc
index ffc3470..5cc1c19 100644
--- a/gcc/rust/ast/rust-desugar-for-loops.cc
+++ b/gcc/rust/ast/rust-desugar-for-loops.cc
@@ -17,7 +17,6 @@
// <http://www.gnu.org/licenses/>.
#include "rust-desugar-for-loops.h"
-#include "rust-ast-visitor.h"
#include "rust-ast.h"
#include "rust-hir-map.h"
#include "rust-path.h"
@@ -31,32 +30,10 @@ namespace AST {
DesugarForLoops::DesugarForLoops () {}
-void
-DesugarForLoops::go (AST::Crate &crate)
-{
- DefaultASTVisitor::visit (crate);
-}
-
-static void
-replace_for_loop (std::unique_ptr<Expr> &for_loop,
- std::unique_ptr<Expr> &&expanded)
-{
- for_loop = std::move (expanded);
-}
-
-MatchArm
-DesugarForLoops::DesugarCtx::make_match_arm (std::unique_ptr<Pattern> &&path)
-{
- auto patterns = std::vector<std::unique_ptr<Pattern>> ();
- patterns.emplace_back (std::move (path));
-
- return MatchArm (std::move (patterns), loc);
-}
-
MatchCase
DesugarForLoops::DesugarCtx::make_break_arm ()
{
- auto arm = make_match_arm (std::unique_ptr<Pattern> (new PathInExpression (
+ auto arm = builder.match_arm (std::unique_ptr<Pattern> (new PathInExpression (
builder.path_in_expression (LangItem::Kind::OPTION_NONE))));
auto break_expr
@@ -79,7 +56,7 @@ DesugarForLoops::DesugarCtx::make_continue_arm ()
builder.path_in_expression (LangItem::Kind::OPTION_SOME),
std::move (pattern_item)));
- auto val_arm = make_match_arm (std::move (pattern));
+ auto val_arm = builder.match_arm (std::move (pattern));
auto next = builder.identifier (DesugarCtx::next_value_id);
@@ -91,14 +68,8 @@ DesugarForLoops::DesugarCtx::make_continue_arm ()
return MatchCase (std::move (val_arm), std::move (assignment));
}
-std::unique_ptr<Stmt>
-DesugarForLoops::DesugarCtx::statementify (std::unique_ptr<Expr> &&expr)
-{
- return std::unique_ptr<Stmt> (new ExprStmt (std::move (expr), loc, true));
-}
-
std::unique_ptr<Expr>
-DesugarForLoops::desugar (AST::ForLoopExpr &expr)
+DesugarForLoops::desugar (ForLoopExpr &expr)
{
auto ctx = DesugarCtx (expr.get_locus ());
@@ -140,10 +111,10 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr)
auto loop_stmts = std::vector<std::unique_ptr<Stmt>> ();
loop_stmts.emplace_back (std::move (let_next));
- loop_stmts.emplace_back (ctx.statementify (std::move (match_next)));
+ loop_stmts.emplace_back (ctx.builder.statementify (std::move (match_next)));
loop_stmts.emplace_back (std::move (let_pat));
loop_stmts.emplace_back (
- ctx.statementify (expr.get_loop_block ().clone_expr ()));
+ ctx.builder.statementify (expr.get_loop_block ().clone_expr ()));
// loop {
// <let_next>;
@@ -170,34 +141,18 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr)
}
void
-DesugarForLoops::maybe_desugar_expr (std::unique_ptr<Expr> &expr)
+DesugarForLoops::go (std::unique_ptr<Expr> &ptr)
{
- if (expr->get_expr_kind () == AST::Expr::Kind::Loop)
- {
- auto &loop = static_cast<AST::BaseLoopExpr &> (*expr);
+ rust_assert (ptr->get_expr_kind () == Expr::Kind::Loop);
- if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For)
- {
- auto &for_loop = static_cast<AST::ForLoopExpr &> (loop);
+ auto &loop = static_cast<BaseLoopExpr &> (*ptr);
- auto desugared = desugar (for_loop);
-
- replace_for_loop (expr, std::move (desugared));
- }
- }
-}
-
-void
-DesugarForLoops::visit (AST::BlockExpr &block)
-{
- for (auto &stmt : block.get_statements ())
- if (stmt->get_stmt_kind () == AST::Stmt::Kind::Expr)
- maybe_desugar_expr (static_cast<AST::ExprStmt &> (*stmt).get_expr_ptr ());
+ rust_assert (loop.get_loop_kind () == BaseLoopExpr::Kind::For);
- if (block.has_tail_expr ())
- maybe_desugar_expr (block.get_tail_expr_ptr ());
+ auto &for_loop = static_cast<ForLoopExpr &> (loop);
+ auto desugared = DesugarForLoops ().desugar (for_loop);
- DefaultASTVisitor::visit (block);
+ ptr = std::move (desugared);
}
} // namespace AST
diff --git a/gcc/rust/ast/rust-desugar-for-loops.h b/gcc/rust/ast/rust-desugar-for-loops.h
index 7beb692..96b63ff 100644
--- a/gcc/rust/ast/rust-desugar-for-loops.h
+++ b/gcc/rust/ast/rust-desugar-for-loops.h
@@ -20,7 +20,6 @@
#define RUST_DESUGAR_FOR_LOOPS_H
#include "rust-ast-builder.h"
-#include "rust-ast-visitor.h"
#include "rust-expr.h"
namespace Rust {
@@ -69,15 +68,14 @@ namespace AST {
// of the way the typechecker is currently structured, where it will fetch name
// resolution information in order to typecheck paths - which technically isn't
// necessary.
-class DesugarForLoops : public DefaultASTVisitor
+class DesugarForLoops
{
- using DefaultASTVisitor::visit;
-
public:
- DesugarForLoops ();
- void go (AST::Crate &);
+ static void go (std::unique_ptr<Expr> &ptr);
private:
+ DesugarForLoops ();
+
struct DesugarCtx
{
DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {}
@@ -85,10 +83,8 @@ private:
Builder builder;
location_t loc;
- MatchArm make_match_arm (std::unique_ptr<Pattern> &&pattern);
MatchCase make_break_arm ();
MatchCase make_continue_arm ();
- std::unique_ptr<Stmt> statementify (std::unique_ptr<Expr> &&expr);
constexpr static const char *continue_pattern_id = "#val";
constexpr static const char *next_value_id = "#__next";
@@ -96,10 +92,7 @@ private:
constexpr static const char *result_id = "#result";
};
- std::unique_ptr<Expr> desugar (AST::ForLoopExpr &expr);
- void maybe_desugar_expr (std::unique_ptr<Expr> &expr);
-
- void visit (AST::BlockExpr &) override;
+ std::unique_ptr<Expr> desugar (ForLoopExpr &expr);
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-desugar-question-mark.cc b/gcc/rust/ast/rust-desugar-question-mark.cc
index 4d2933b..01400d8 100644
--- a/gcc/rust/ast/rust-desugar-question-mark.cc
+++ b/gcc/rust/ast/rust-desugar-question-mark.cc
@@ -18,7 +18,6 @@
#include "rust-desugar-question-mark.h"
#include "rust-ast-builder.h"
-#include "rust-ast-visitor.h"
namespace Rust {
namespace AST {
@@ -26,42 +25,14 @@ namespace AST {
DesugarQuestionMark::DesugarQuestionMark () {}
void
-DesugarQuestionMark::go (AST::Crate &crate)
+DesugarQuestionMark::go (std::unique_ptr<Expr> &ptr)
{
- DesugarQuestionMark::visit (crate);
-}
-
-void
-DesugarQuestionMark::visit (ExprStmt &stmt)
-{
- if (stmt.get_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation)
- desugar_and_replace (stmt.get_expr_ptr ());
-
- DefaultASTVisitor::visit (stmt);
-}
-
-void
-DesugarQuestionMark::visit (CallExpr &call)
-{
- if (call.get_function_expr ().get_expr_kind ()
- == Expr::Kind::ErrorPropagation)
- desugar_and_replace (call.get_function_expr_ptr ());
-
- for (auto &arg : call.get_params ())
- if (arg->get_expr_kind () == Expr::Kind::ErrorPropagation)
- desugar_and_replace (arg);
-
- DefaultASTVisitor::visit (call);
-}
+ rust_assert (ptr->get_expr_kind () == Expr::Kind::ErrorPropagation);
-void
-DesugarQuestionMark::visit (LetStmt &stmt)
-{
- if (stmt.has_init_expr ()
- && stmt.get_init_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation)
- desugar_and_replace (stmt.get_init_expr_ptr ());
+ auto original = static_cast<ErrorPropagationExpr &> (*ptr);
+ auto desugared = DesugarQuestionMark ().desugar (original);
- DefaultASTVisitor::visit (stmt);
+ ptr = std::move (desugared);
}
MatchArm
@@ -99,6 +70,12 @@ ok_case (Builder &builder)
MatchCase
err_case (Builder &builder)
{
+ // TODO: We need to handle the case where there is an enclosing `try {}`
+ // block, as that will create an additional block label that we can break to.
+ // This allows try blocks to use the question mark operator without having the
+ // offending statement early return from the enclosing function
+ // FIXME: How to mark that there is an enclosing block label?
+
auto val = builder.identifier_pattern ("err");
auto patterns = std::vector<std::unique_ptr<Pattern>> ();
@@ -154,14 +131,5 @@ DesugarQuestionMark::desugar (ErrorPropagationExpr &expr)
expr.get_locus ()));
}
-void
-DesugarQuestionMark::desugar_and_replace (std::unique_ptr<Expr> &ptr)
-{
- auto original = static_cast<ErrorPropagationExpr &> (*ptr);
- auto desugared = desugar (original);
-
- ptr = std::move (desugared);
-}
-
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-question-mark.h b/gcc/rust/ast/rust-desugar-question-mark.h
index e4c513f..542c52b 100644
--- a/gcc/rust/ast/rust-desugar-question-mark.h
+++ b/gcc/rust/ast/rust-desugar-question-mark.h
@@ -19,9 +19,7 @@
#ifndef RUST_DESUGAR_QUESTION_MARK
#define RUST_DESUGAR_QUESTION_MARK
-#include "rust-ast-visitor.h"
#include "rust-expr.h"
-#include "rust-stmt.h"
namespace Rust {
namespace AST {
@@ -56,21 +54,15 @@ namespace AST {
// }
// }
// ```
-class DesugarQuestionMark : public DefaultASTVisitor
+class DesugarQuestionMark
{
- using DefaultASTVisitor::visit;
-
public:
- DesugarQuestionMark ();
- void go (AST::Crate &);
+ static void go (std::unique_ptr<Expr> &ptr);
private:
- void desugar_and_replace (std::unique_ptr<Expr> &ptr);
- std::unique_ptr<Expr> desugar (ErrorPropagationExpr &);
+ DesugarQuestionMark ();
- void visit (AST::ExprStmt &) override;
- void visit (AST::CallExpr &) override;
- void visit (AST::LetStmt &) override;
+ std::unique_ptr<Expr> desugar (ErrorPropagationExpr &);
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-desugar-try-block.cc b/gcc/rust/ast/rust-desugar-try-block.cc
new file mode 100644
index 0000000..07f06aa
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-try-block.cc
@@ -0,0 +1,62 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-desugar-try-block.h"
+#include "rust-ast-builder.h"
+#include "rust-expr.h"
+
+namespace Rust {
+namespace AST {
+
+DesugarTryBlock::DesugarTryBlock () {}
+
+void
+DesugarTryBlock::go (std::unique_ptr<Expr> &ptr)
+{
+ rust_assert (ptr->get_expr_kind () == Expr::Kind::Try);
+
+ auto original = static_cast<TryExpr &> (*ptr);
+ auto desugared = DesugarTryBlock ().desugar (original);
+
+ ptr = std::move (desugared);
+}
+
+std::unique_ptr<Expr>
+DesugarTryBlock::desugar (TryExpr &expr)
+{
+ auto builder = Builder (expr.get_locus ());
+ auto &block = expr.get_block_expr ();
+
+ if (block.has_statements ())
+ rust_sorry_at (expr.get_locus (),
+ "cannot desugar try-blocks with statements");
+
+ auto tail_expr = builder.tuple ();
+
+ if (block.has_tail_expr ())
+ tail_expr = block.get_tail_expr ().clone_expr ();
+
+ // Wrap in Try::from_ok call
+ auto from_ok = builder.path_in_expression (LangItem::Kind::TRY_FROM_OK);
+ auto call = builder.call (ptrify (from_ok), std::move (tail_expr));
+
+ return builder.block (std::move (call));
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-try-block.h b/gcc/rust/ast/rust-desugar-try-block.h
new file mode 100644
index 0000000..bfd0463
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-try-block.h
@@ -0,0 +1,42 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_DESUGAR_TRY_BLOCK
+#define RUST_DESUGAR_TRY_BLOCK
+
+#include "rust-expr.h"
+
+namespace Rust {
+namespace AST {
+
+// FIXME: Add documentation
+class DesugarTryBlock
+{
+public:
+ static void go (std::unique_ptr<Expr> &ptr);
+
+private:
+ DesugarTryBlock ();
+
+ std::unique_ptr<Expr> desugar (TryExpr &);
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DESUGAR_TRY_BLOCK
diff --git a/gcc/rust/ast/rust-desugar-while-let.cc b/gcc/rust/ast/rust-desugar-while-let.cc
new file mode 100644
index 0000000..5eadc59
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-while-let.cc
@@ -0,0 +1,104 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-desugar-while-let.h"
+#include "rust-ast.h"
+#include "rust-hir-map.h"
+#include "rust-path.h"
+#include "rust-pattern.h"
+#include "rust-stmt.h"
+#include "rust-expr.h"
+#include "rust-ast-builder.h"
+
+namespace Rust {
+namespace AST {
+
+DesugarWhileLet::DesugarWhileLet () {}
+
+MatchCase
+DesugarWhileLet::DesugarCtx::make_break_arm ()
+{
+ auto arm = builder.match_arm (builder.wildcard ());
+
+ auto break_expr
+ = std::unique_ptr<Expr> (new BreakExpr (tl::nullopt, nullptr, {}, loc));
+
+ return MatchCase (std::move (arm), std::move (break_expr));
+}
+
+MatchCase
+DesugarWhileLet::DesugarCtx::make_continue_arm (
+ std::unique_ptr<Pattern> &&pattern, std::unique_ptr<BlockExpr> &&body)
+{
+ auto arm = builder.match_arm (std::move (pattern));
+
+ return MatchCase (std::move (arm), std::move (body));
+}
+
+std::unique_ptr<Expr>
+DesugarWhileLet::desugar (WhileLetLoopExpr &expr)
+{
+ rust_assert (expr.get_patterns ().size () == 1);
+
+ auto pattern = expr.get_patterns ()[0]->clone_pattern ();
+ auto body = expr.get_loop_block ().clone_block_expr ();
+ auto scrutinee = expr.get_scrutinee_expr ().clone_expr ();
+
+ auto ctx = DesugarCtx (expr.get_locus ());
+
+ // _ => break,
+ auto break_arm = ctx.make_break_arm ();
+
+ // <pattern> => <body>,
+ auto continue_arm
+ = ctx.make_continue_arm (std::move (pattern), std::move (body));
+
+ // match <scrutinee> {
+ // <continue_arm>
+ // <break_arm>
+ // }
+ auto match_expr
+ = ctx.builder.match (std::move (scrutinee),
+ {std::move (continue_arm), std::move (break_arm)});
+
+ auto loop_stmts = std::vector<std::unique_ptr<Stmt>> ();
+ loop_stmts.emplace_back (ctx.builder.statementify (std::move (match_expr)));
+
+ // loop {
+ // <match_expr>
+ // }
+ return ctx.builder.loop (std::move (loop_stmts));
+}
+
+void
+DesugarWhileLet::go (std::unique_ptr<Expr> &ptr)
+{
+ rust_assert (ptr->get_expr_kind () == Expr::Kind::Loop);
+
+ auto &loop = static_cast<BaseLoopExpr &> (*ptr);
+
+ rust_assert (loop.get_loop_kind () == BaseLoopExpr::Kind::WhileLet);
+
+ auto &while_let = static_cast<WhileLetLoopExpr &> (loop);
+ auto desugared = DesugarWhileLet ().desugar (while_let);
+
+ ptr = std::move (desugared);
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-while-let.h b/gcc/rust/ast/rust-desugar-while-let.h
new file mode 100644
index 0000000..60e0693
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-while-let.h
@@ -0,0 +1,71 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_DESUGAR_WHILE_LET_H
+#define RUST_DESUGAR_WHILE_LET_H
+
+#include "rust-ast-builder.h"
+#include "rust-expr.h"
+
+namespace Rust {
+namespace AST {
+
+// Desugar while-let into a set of other AST nodes. The desugar is of the
+// following form:
+//
+// ```
+// whilet let <pat> = <expr> <body>
+// ```
+//
+// becomes:
+//
+// ```
+// loop {
+// match <expr> {
+// <pat> => <body>,
+// _ => break
+// }
+// }
+// ```
+class DesugarWhileLet
+{
+public:
+ static void go (std::unique_ptr<Expr> &ptr);
+
+private:
+ DesugarWhileLet ();
+
+ struct DesugarCtx
+ {
+ DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {}
+
+ Builder builder;
+ location_t loc;
+
+ MatchCase make_break_arm ();
+ MatchCase make_continue_arm (std::unique_ptr<Pattern> &&pattern,
+ std::unique_ptr<BlockExpr> &&body);
+ };
+
+ std::unique_ptr<Expr> desugar (WhileLetLoopExpr &expr);
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DESUGAR_WHILE_LET_H
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index fdb6360..7b0df25 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -1,6 +1,7 @@
#ifndef RUST_AST_EXPR_H
#define RUST_AST_EXPR_H
+#include "optional.h"
#include "rust-ast.h"
#include "rust-common.h"
#include "rust-path.h"
@@ -182,9 +183,13 @@ public:
AttrInputMacro (AttrInputMacro &&oth) : macro (std::move (oth.macro)) {}
- void operator= (const AttrInputMacro &oth);
+ AttrInputMacro &operator= (const AttrInputMacro &oth);
- void operator= (AttrInputMacro &&oth) { macro = std::move (oth.macro); }
+ AttrInputMacro &operator= (AttrInputMacro &&oth)
+ {
+ macro = std::move (oth.macro);
+ return *this;
+ }
std::string as_string () const override;
@@ -244,36 +249,50 @@ protected:
}
};
-// more generic meta item "path = lit" form
-class MetaItemPathLit : public MetaItem
+// more generic meta item "path = expr" form
+class MetaItemPathExpr : public MetaItem
{
SimplePath path;
- LiteralExpr lit;
+ std::unique_ptr<Expr> expr;
public:
- MetaItemPathLit (SimplePath path, LiteralExpr lit_expr)
- : path (std::move (path)), lit (std::move (lit_expr))
+ MetaItemPathExpr (SimplePath path, std::unique_ptr<Expr> expr)
+ : path (std::move (path)), expr (std::move (expr))
{}
+ MetaItemPathExpr (const MetaItemPathExpr &other)
+ : MetaItem (other), path (other.path), expr (other.expr->clone_expr ())
+ {}
+
+ MetaItemPathExpr (MetaItemPathExpr &&) = default;
+
+ MetaItemPathExpr &operator= (MetaItemPathExpr &&) = default;
+
+ MetaItemPathExpr operator= (const MetaItemPathExpr &other)
+ {
+ MetaItem::operator= (other);
+ path = other.path;
+ expr = other.expr->clone_expr ();
+ return *this;
+ }
+
SimplePath get_path () const { return path; }
SimplePath &get_path () { return path; }
- LiteralExpr get_literal () const { return lit; }
-
- LiteralExpr &get_literal () { return lit; }
+ Expr &get_expr () { return *expr; }
std::string as_string () const override
{
- return path.as_string () + " = " + lit.as_string ();
+ return path.as_string () + " = " + expr->as_string ();
}
MetaItem::ItemKind get_item_kind () const override
{
- return MetaItem::ItemKind::PathLit;
+ return MetaItem::ItemKind::PathExpr;
}
- // There are two Locations in MetaItemPathLit (path and lit_expr),
+ // There are two Locations in MetaItemPathExpr (path and 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.
@@ -289,9 +308,9 @@ public:
protected:
// Use covariance to implement clone function as returning this type
- MetaItemPathLit *clone_meta_item_inner_impl () const override
+ MetaItemPathExpr *clone_meta_item_inner_impl () const override
{
- return new MetaItemPathLit (*this);
+ return new MetaItemPathExpr (*this);
}
};
@@ -395,6 +414,8 @@ public:
return *main_or_left_expr;
}
+ bool has_borrow_expr () const { return main_or_left_expr != nullptr; }
+
bool get_is_mut () const { return mutability == Mutability::Mut; }
Mutability get_mutability () const { return mutability; }
@@ -1160,11 +1181,11 @@ protected:
// Value array elements
class ArrayElemsValues : public ArrayElems
{
- std::vector<std::unique_ptr<Expr> > values;
+ std::vector<std::unique_ptr<Expr>> values;
location_t locus;
public:
- ArrayElemsValues (std::vector<std::unique_ptr<Expr> > elems, location_t locus)
+ ArrayElemsValues (std::vector<std::unique_ptr<Expr>> elems, location_t locus)
: ArrayElems (), values (std::move (elems)), locus (locus)
{}
@@ -1192,14 +1213,16 @@ public:
std::string as_string () const override;
+ location_t get_locus () const { return locus; }
+
void accept_vis (ASTVisitor &vis) override;
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Expr> > &get_values () const
+ const std::vector<std::unique_ptr<Expr>> &get_values () const
{
return values;
}
- std::vector<std::unique_ptr<Expr> > &get_values () { return values; }
+ std::vector<std::unique_ptr<Expr>> &get_values () { return values; }
size_t get_num_values () const { return values.size (); }
@@ -1214,6 +1237,8 @@ protected:
class ArrayElemsCopied : public ArrayElems
{
std::unique_ptr<Expr> elem_to_copy;
+
+ // TODO: This should be replaced by a ConstExpr
std::unique_ptr<Expr> num_copies;
location_t locus;
@@ -1246,6 +1271,8 @@ public:
std::string as_string () const override;
+ location_t get_locus () const { return locus; }
+
void accept_vis (ASTVisitor &vis) override;
// TODO: is this better? Or is a "vis_block" better?
@@ -1472,7 +1499,7 @@ class TupleExpr : public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
std::vector<Attribute> inner_attrs;
- std::vector<std::unique_ptr<Expr> > tuple_elems;
+ std::vector<std::unique_ptr<Expr>> tuple_elems;
location_t locus;
// TODO: find another way to store this to save memory?
@@ -1492,7 +1519,7 @@ public:
outer_attrs = std::move (new_attrs);
}
- TupleExpr (std::vector<std::unique_ptr<Expr> > tuple_elements,
+ TupleExpr (std::vector<std::unique_ptr<Expr>> tuple_elements,
std::vector<Attribute> inner_attribs,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
@@ -1543,14 +1570,11 @@ public:
bool is_marked_for_strip () const override { return marked_for_strip; }
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Expr> > &get_tuple_elems () const
- {
- return tuple_elems;
- }
- std::vector<std::unique_ptr<Expr> > &get_tuple_elems ()
+ const std::vector<std::unique_ptr<Expr>> &get_tuple_elems () const
{
return tuple_elems;
}
+ std::vector<std::unique_ptr<Expr>> &get_tuple_elems () { return tuple_elems; }
bool is_unit () const { return tuple_elems.size () == 0; }
@@ -1775,6 +1799,8 @@ public:
std::string as_string () const;
+ location_t get_locus () const { return locus; }
+
// TODO: is this better? Or is a "vis_block" better?
Expr &get_base_struct ()
{
@@ -1972,7 +1998,7 @@ protected:
class StructExprStructFields : public StructExprStruct
{
// std::vector<StructExprField> fields;
- std::vector<std::unique_ptr<StructExprField> > fields;
+ std::vector<std::unique_ptr<StructExprField>> fields;
// bool has_struct_base;
StructBase struct_base;
@@ -1985,8 +2011,8 @@ public:
// Constructor for StructExprStructFields when no struct base is used
StructExprStructFields (
PathInExpression struct_path,
- std::vector<std::unique_ptr<StructExprField> > expr_fields,
- location_t locus, StructBase base_struct = StructBase::error (),
+ std::vector<std::unique_ptr<StructExprField>> expr_fields, location_t locus,
+ StructBase base_struct = StructBase::error (),
std::vector<Attribute> inner_attribs = std::vector<Attribute> (),
std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
: StructExprStruct (std::move (struct_path), std::move (inner_attribs),
@@ -2023,11 +2049,11 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: this mutable getter seems really dodgy. Think up better way.
- std::vector<std::unique_ptr<StructExprField> > &get_fields ()
+ std::vector<std::unique_ptr<StructExprField>> &get_fields ()
{
return fields;
}
- const std::vector<std::unique_ptr<StructExprField> > &get_fields () const
+ const std::vector<std::unique_ptr<StructExprField>> &get_fields () const
{
return fields;
}
@@ -2084,7 +2110,7 @@ class CallExpr : public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
std::unique_ptr<Expr> function;
- std::vector<std::unique_ptr<Expr> > params;
+ std::vector<std::unique_ptr<Expr>> params;
location_t locus;
public:
@@ -2093,7 +2119,7 @@ public:
std::string as_string () const override;
CallExpr (std::unique_ptr<Expr> function_expr,
- std::vector<std::unique_ptr<Expr> > function_params,
+ std::vector<std::unique_ptr<Expr>> function_params,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
function (std::move (function_expr)),
@@ -2150,11 +2176,11 @@ public:
bool is_marked_for_strip () const override { return function == nullptr; }
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Expr> > &get_params () const
+ const std::vector<std::unique_ptr<Expr>> &get_params () const
{
return params;
}
- std::vector<std::unique_ptr<Expr> > &get_params () { return params; }
+ std::vector<std::unique_ptr<Expr>> &get_params () { return params; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_function_expr ()
@@ -2190,7 +2216,7 @@ class MethodCallExpr : public ExprWithoutBlock
std::vector<Attribute> outer_attrs;
std::unique_ptr<Expr> receiver;
PathExprSegment method_name;
- std::vector<std::unique_ptr<Expr> > params;
+ std::vector<std::unique_ptr<Expr>> params;
location_t locus;
public:
@@ -2198,7 +2224,7 @@ public:
MethodCallExpr (std::unique_ptr<Expr> call_receiver,
PathExprSegment method_path,
- std::vector<std::unique_ptr<Expr> > method_params,
+ std::vector<std::unique_ptr<Expr>> method_params,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
receiver (std::move (call_receiver)),
@@ -2254,11 +2280,11 @@ public:
bool is_marked_for_strip () const override { return receiver == nullptr; }
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Expr> > &get_params () const
+ const std::vector<std::unique_ptr<Expr>> &get_params () const
{
return params;
}
- std::vector<std::unique_ptr<Expr> > &get_params () { return params; }
+ std::vector<std::unique_ptr<Expr>> &get_params () { return params; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_receiver_expr ()
@@ -2504,6 +2530,8 @@ public:
bool get_has_move () const { return has_move; }
Expr::Kind get_expr_kind () const override { return Expr::Kind::Closure; }
+
+ virtual Expr &get_definition_expr () = 0;
};
// Represents a non-type-specified closure expression AST node
@@ -2563,7 +2591,7 @@ public:
return closure_inner == nullptr;
}
- Expr &get_definition_expr ()
+ Expr &get_definition_expr () override
{
rust_assert (closure_inner != nullptr);
return *closure_inner;
@@ -2583,7 +2611,7 @@ class BlockExpr : public ExprWithBlock
{
std::vector<Attribute> outer_attrs;
std::vector<Attribute> inner_attrs;
- std::vector<std::unique_ptr<Stmt> > statements;
+ std::vector<std::unique_ptr<Stmt>> statements;
std::unique_ptr<Expr> expr;
tl::optional<LoopLabel> label;
location_t start_locus;
@@ -2599,7 +2627,7 @@ public:
// Returns whether the block contains a final expression.
bool has_tail_expr () const { return expr != nullptr; }
- BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements,
+ BlockExpr (std::vector<std::unique_ptr<Stmt>> block_statements,
std::unique_ptr<Expr> block_expr,
std::vector<Attribute> inner_attribs,
std::vector<Attribute> outer_attribs,
@@ -2678,11 +2706,11 @@ public:
const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
- const std::vector<std::unique_ptr<Stmt> > &get_statements () const
+ const std::vector<std::unique_ptr<Stmt>> &get_statements () const
{
return statements;
}
- std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; }
+ std::vector<std::unique_ptr<Stmt>> &get_statements () { return statements; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_tail_expr ()
@@ -2744,6 +2772,151 @@ protected:
}
};
+class AnonConst : public ExprWithBlock
+{
+public:
+ enum class Kind
+ {
+ Explicit,
+ DeferredInference,
+ };
+
+ AnonConst (std::unique_ptr<Expr> &&expr, location_t locus = UNKNOWN_LOCATION)
+ : ExprWithBlock (), locus (locus), kind (Kind::Explicit),
+ expr (std::move (expr))
+ {
+ rust_assert (this->expr.value ());
+ }
+
+ AnonConst (location_t locus = UNKNOWN_LOCATION)
+ : ExprWithBlock (), locus (locus), kind (Kind::DeferredInference),
+ expr (tl::nullopt)
+ {}
+
+ AnonConst (const AnonConst &other)
+ {
+ node_id = other.node_id;
+ locus = other.locus;
+ kind = other.kind;
+
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
+ }
+
+ AnonConst operator= (const AnonConst &other)
+ {
+ node_id = other.node_id;
+ locus = other.locus;
+ kind = other.kind;
+
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
+
+ return *this;
+ }
+
+ std::string as_string () const override;
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstExpr; }
+
+ location_t get_locus () const override { return locus; }
+
+ Expr &get_inner_expr ()
+ {
+ rust_assert (expr.has_value ());
+ return *expr.value ();
+ }
+
+ NodeId get_node_id () const override { return node_id; }
+
+ /* FIXME: AnonConst are always "internal" and should not have outer attributes
+ * - is that true? Or should we instead call
+ * expr->get_outer_attrs()/expr->set_outer_attrs() */
+
+ std::vector<Attribute> &get_outer_attrs () override
+ {
+ static auto attrs = std::vector<Attribute> ();
+ return attrs;
+ }
+
+ void set_outer_attrs (std::vector<Attribute>) override {}
+
+ /* FIXME: Likewise for mark_for_strip() ? */
+ void mark_for_strip () override {}
+ bool is_marked_for_strip () const override { return false; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ bool is_deferred () const { return kind == Kind::DeferredInference; }
+
+private:
+ location_t locus;
+ Kind kind;
+ tl::optional<std::unique_ptr<Expr>> expr;
+
+ AnonConst *clone_expr_with_block_impl () const override
+ {
+ return new AnonConst (*this);
+ }
+};
+
+class ConstBlock : public ExprWithBlock
+{
+public:
+ ConstBlock (AnonConst &&expr, location_t locus = UNKNOWN_LOCATION,
+ std::vector<Attribute> &&outer_attrs = {})
+ : ExprWithBlock (), expr (std::move (expr)),
+ outer_attrs (std::move (outer_attrs)), locus (locus)
+ {}
+
+ ConstBlock (const ConstBlock &other)
+ : ExprWithBlock (other), expr (other.expr), outer_attrs (other.outer_attrs),
+ locus (other.locus)
+ {}
+
+ ConstBlock operator= (const ConstBlock &other)
+ {
+ expr = other.expr;
+ node_id = other.node_id;
+ outer_attrs = other.outer_attrs;
+ locus = other.locus;
+
+ return *this;
+ }
+
+ std::string as_string () const override;
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstBlock; }
+
+ AnonConst &get_const_expr () { return expr; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
+
+ void set_outer_attrs (std::vector<Attribute> new_attrs) override
+ {
+ outer_attrs = std::move (new_attrs);
+ }
+
+ location_t get_locus () const override { return locus; }
+
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+ void mark_for_strip () override { marked_for_strip = true; }
+
+private:
+ AnonConst expr;
+
+ std::vector<Attribute> outer_attrs;
+ location_t locus;
+ bool marked_for_strip = false;
+
+ ConstBlock *clone_expr_with_block_impl () const override
+ {
+ return new ConstBlock (*this);
+ }
+};
+
// Represents a type-specified closure expression AST node
class ClosureExprInnerTyped : public ClosureExpr
{
@@ -2812,7 +2985,7 @@ public:
bool is_marked_for_strip () const override { return expr == nullptr; }
// TODO: is this better? Or is a "vis_block" better?
- BlockExpr &get_definition_block ()
+ BlockExpr &get_definition_expr () override
{
rust_assert (expr != nullptr);
return *expr;
@@ -3572,6 +3745,82 @@ protected:
}
};
+// Try expression AST node representation
+class TryExpr : public ExprWithBlock
+{
+ std::vector<Attribute> outer_attrs;
+ std::unique_ptr<BlockExpr> block_expr;
+ location_t locus;
+
+ // TODO: find another way to store this to save memory?
+ bool marked_for_strip = false;
+
+public:
+ std::string as_string () const override;
+
+ // Constructor for ReturnExpr.
+ TryExpr (std::unique_ptr<BlockExpr> block_expr,
+ std::vector<Attribute> outer_attribs, location_t locus)
+ : outer_attrs (std::move (outer_attribs)),
+ block_expr (std::move (block_expr)), locus (locus)
+ {
+ rust_assert (this->block_expr);
+ }
+
+ // Copy constructor with clone
+ TryExpr (TryExpr const &other)
+ : ExprWithBlock (other), outer_attrs (other.outer_attrs),
+ block_expr (other.block_expr->clone_block_expr ()), locus (other.locus),
+ marked_for_strip (other.marked_for_strip)
+ {}
+
+ // Overloaded assignment operator to clone return_expr pointer
+ TryExpr &operator= (TryExpr const &other)
+ {
+ ExprWithBlock::operator= (other);
+ locus = other.locus;
+ marked_for_strip = other.marked_for_strip;
+ outer_attrs = other.outer_attrs;
+
+ block_expr = other.block_expr->clone_block_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ TryExpr (TryExpr &&other) = default;
+ TryExpr &operator= (TryExpr &&other) = default;
+
+ location_t get_locus () const override final { return locus; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ // Can't think of any invalid invariants, so store boolean.
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ BlockExpr &get_block_expr () { return *block_expr; }
+
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+ std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
+
+ void set_outer_attrs (std::vector<Attribute> new_attrs) override
+ {
+ outer_attrs = std::move (new_attrs);
+ }
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Try; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ TryExpr *clone_expr_with_block_impl () const override
+ {
+ return new TryExpr (*this);
+ }
+};
+
// Forward decl - defined in rust-macro.h
class MacroInvocation;
@@ -3847,14 +4096,14 @@ protected:
class WhileLetLoopExpr : public BaseLoopExpr
{
// MatchArmPatterns patterns;
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
+ std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined
std::unique_ptr<Expr> scrutinee;
public:
std::string as_string () const override;
// Constructor with a loop label
- WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
+ WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
std::unique_ptr<Expr> scrutinee,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
tl::optional<LoopLabel> loop_label = tl::nullopt,
@@ -3908,11 +4157,11 @@ public:
}
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
{
return match_arm_patterns;
}
- std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_patterns ()
{
return match_arm_patterns;
}
@@ -4195,7 +4444,7 @@ protected:
class IfLetExpr : public ExprWithBlock
{
std::vector<Attribute> outer_attrs;
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
+ std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined
std::unique_ptr<Expr> value;
std::unique_ptr<BlockExpr> if_block;
location_t locus;
@@ -4203,7 +4452,7 @@ class IfLetExpr : public ExprWithBlock
public:
std::string as_string () const override;
- IfLetExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
+ IfLetExpr (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block,
std::vector<Attribute> outer_attrs, location_t locus)
: outer_attrs (std::move (outer_attrs)),
@@ -4297,11 +4546,11 @@ public:
}
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
{
return match_arm_patterns;
}
- std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_patterns ()
{
return match_arm_patterns;
}
@@ -4341,11 +4590,11 @@ class IfLetExprConseqElse : public IfLetExpr
public:
std::string as_string () const override;
- IfLetExprConseqElse (
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
- std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block,
- std::unique_ptr<ExprWithBlock> else_block,
- std::vector<Attribute> outer_attrs, location_t locus)
+ IfLetExprConseqElse (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
+ std::unique_ptr<Expr> value,
+ std::unique_ptr<BlockExpr> if_block,
+ std::unique_ptr<ExprWithBlock> else_block,
+ std::vector<Attribute> outer_attrs, location_t locus)
: IfLetExpr (std::move (match_arm_patterns), std::move (value),
std::move (if_block), std::move (outer_attrs), locus),
else_block (std::move (else_block))
@@ -4398,7 +4647,7 @@ struct MatchArm
private:
std::vector<Attribute> outer_attrs;
// MatchArmPatterns patterns;
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
+ std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined
// bool has_match_arm_guard;
// inlined from MatchArmGuard
@@ -4411,7 +4660,7 @@ public:
bool has_match_arm_guard () const { return guard_expr != nullptr; }
// Constructor for match arm with a guard expression
- MatchArm (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
+ MatchArm (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
location_t locus, std::unique_ptr<Expr> guard_expr = nullptr,
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
: outer_attrs (std::move (outer_attrs)),
@@ -4463,7 +4712,7 @@ public:
static MatchArm create_error ()
{
location_t locus = UNDEF_LOCATION;
- return MatchArm (std::vector<std::unique_ptr<Pattern> > (), locus);
+ return MatchArm (std::vector<std::unique_ptr<Pattern>> (), locus);
}
std::string as_string () const;
@@ -4485,11 +4734,11 @@ public:
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
- const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
{
return match_arm_patterns;
}
- std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_patterns ()
{
return match_arm_patterns;
}
@@ -4836,29 +5085,6 @@ enum class InlineAsmOption
MAY_UNWIND = 1 << 8,
};
-struct AnonConst
-{
- NodeId id;
- std::unique_ptr<Expr> expr;
- AnonConst (NodeId id, std::unique_ptr<Expr> expr)
- : id (id), expr (std::move (expr))
- {
- rust_assert (this->expr != nullptr);
- }
- AnonConst (const AnonConst &other)
- {
- id = other.id;
- expr = other.expr->clone_expr ();
- }
-
- AnonConst operator= (const AnonConst &other)
- {
- id = other.id;
- expr = other.expr->clone_expr ();
- return *this;
- }
-};
-
struct InlineAsmRegOrRegClass
{
enum Type
@@ -5288,6 +5514,20 @@ struct TupleTemplateStr
// Inline Assembly Node
class InlineAsm : public ExprWithoutBlock
{
+public:
+ enum class Option
+ {
+ PURE = 1 << 0,
+ NOMEM = 1 << 1,
+ READONLY = 1 << 2,
+ PRESERVES_FLAGS = 1 << 3,
+ NORETURN = 1 << 4,
+ NOSTACK = 1 << 5,
+ ATT_SYNTAX = 1 << 6,
+ RAW = 1 << 7,
+ MAY_UNWIND = 1 << 8,
+ };
+
private:
location_t locus;
// TODO: Not sure how outer_attrs plays with InlineAsm, I put it here in order
@@ -5311,7 +5551,7 @@ public:
std::map<std::string, int> named_args;
std::set<int> reg_args;
std::vector<TupleClobber> clobber_abi;
- std::set<InlineAsmOption> options;
+ std::set<InlineAsm::Option> options;
std::vector<location_t> line_spans;
@@ -5342,7 +5582,7 @@ public:
std::vector<TupleClobber> get_clobber_abi () { return clobber_abi; }
- std::set<InlineAsmOption> get_options () { return options; }
+ std::set<InlineAsm::Option> get_options () { return options; }
InlineAsm *clone_expr_without_block_impl () const override
{
@@ -5350,6 +5590,33 @@ public:
}
Expr::Kind get_expr_kind () const override { return Expr::Kind::InlineAsm; }
+
+ static std::string option_to_string (Option option)
+ {
+ switch (option)
+ {
+ case Option::PURE:
+ return "pure";
+ case Option::NOMEM:
+ return "nomem";
+ case Option::READONLY:
+ return "readonly";
+ case Option::PRESERVES_FLAGS:
+ return "preserves_flags";
+ case Option::NORETURN:
+ return "noreturn";
+ case Option::NOSTACK:
+ return "nostack";
+ case Option::ATT_SYNTAX:
+ return "att_syntax";
+ case Option::RAW:
+ return "raw";
+ case Option::MAY_UNWIND:
+ return "may_unwind";
+ default:
+ rust_unreachable ();
+ }
+ }
};
class LlvmInlineAsm : public ExprWithoutBlock
diff --git a/gcc/rust/ast/rust-expression-yeast.cc b/gcc/rust/ast/rust-expression-yeast.cc
new file mode 100644
index 0000000..9f6a62f
--- /dev/null
+++ b/gcc/rust/ast/rust-expression-yeast.cc
@@ -0,0 +1,118 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-expression-yeast.h"
+#include "rust-ast-visitor.h"
+#include "rust-desugar-question-mark.h"
+#include "rust-desugar-try-block.h"
+#include "rust-desugar-for-loops.h"
+#include "rust-ast-full.h"
+#include "rust-desugar-while-let.h"
+#include "rust-expr.h"
+#include "rust-stmt.h"
+
+namespace Rust {
+namespace AST {
+
+void
+ExpressionYeast::go (AST::Crate &crate)
+{
+ DefaultASTVisitor::visit (crate);
+}
+
+void
+ExpressionYeast::dispatch_loops (std::unique_ptr<Expr> &loop_expr)
+{
+ auto &loop = static_cast<BaseLoopExpr &> (*loop_expr.get ());
+
+ switch (loop.get_loop_kind ())
+ {
+ case BaseLoopExpr::Kind::For:
+ DesugarForLoops::go (loop_expr);
+ break;
+ case BaseLoopExpr::Kind::WhileLet:
+ DesugarWhileLet::go (loop_expr);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+ExpressionYeast::dispatch (std::unique_ptr<Expr> &expr)
+{
+ switch (expr->get_expr_kind ())
+ {
+ case Expr::Kind::ErrorPropagation:
+ DesugarQuestionMark::go (expr);
+ break;
+ case Expr::Kind::Try:
+ DesugarTryBlock::go (expr);
+ break;
+ case Expr::Kind::Loop:
+ dispatch_loops (expr);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+ExpressionYeast::visit (ExprStmt &stmt)
+{
+ dispatch (stmt.get_expr_ptr ());
+
+ DefaultASTVisitor::visit (stmt);
+}
+
+void
+ExpressionYeast::visit (CallExpr &call)
+{
+ dispatch (call.get_function_expr_ptr ());
+
+ for (auto &arg : call.get_params ())
+ dispatch (arg);
+
+ DefaultASTVisitor::visit (call);
+}
+
+void
+ExpressionYeast::visit (BlockExpr &block)
+{
+ for (auto &stmt : block.get_statements ())
+ if (stmt->get_stmt_kind () == Stmt::Kind::Expr)
+ dispatch (static_cast<ExprStmt &> (*stmt).get_expr_ptr ());
+
+ if (block.has_tail_expr ())
+ dispatch (block.get_tail_expr_ptr ());
+
+ DefaultASTVisitor::visit (block);
+}
+
+void
+ExpressionYeast::visit (LetStmt &stmt)
+{
+ if (stmt.has_init_expr ())
+ dispatch (stmt.get_init_expr_ptr ());
+
+ DefaultASTVisitor::visit (stmt);
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-expression-yeast.h b/gcc/rust/ast/rust-expression-yeast.h
new file mode 100644
index 0000000..855918f
--- /dev/null
+++ b/gcc/rust/ast/rust-expression-yeast.h
@@ -0,0 +1,52 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_EXPRESSION_YEAST
+#define RUST_EXPRESSION_YEAST
+
+#include "rust-ast-visitor.h"
+#include "rust-ast.h"
+#include "rust-desugar-question-mark.h"
+
+namespace Rust {
+namespace AST {
+
+// This visitor takes care of all the expression desugars: try-blocks,
+// error-propagation, etc.
+class ExpressionYeast : public AST::DefaultASTVisitor
+{
+ using AST::DefaultASTVisitor::visit;
+
+public:
+ void go (AST::Crate &);
+
+private:
+ // Dispatch to the proper desugar
+ void dispatch (std::unique_ptr<Expr> &expr);
+ void dispatch_loops (std::unique_ptr<Expr> &loop_expr);
+
+ void visit (AST::ExprStmt &) override;
+ void visit (AST::CallExpr &) override;
+ void visit (AST::LetStmt &) override;
+ void visit (AST::BlockExpr &) override;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_EXPRESSION_YEAST
diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h
index a54faec..3722db2 100644
--- a/gcc/rust/ast/rust-fmt.h
+++ b/gcc/rust/ast/rust-fmt.h
@@ -266,11 +266,10 @@ enum ParseMode
extern "C" {
-FormatArgsHandle
-collect_pieces (const char *input, bool append_newline, ParseMode parse_mode);
+FormatArgsHandle collect_pieces (const char *input, bool append_newline,
+ ParseMode parse_mode);
-FormatArgsHandle
-clone_pieces (const FormatArgsHandle &);
+FormatArgsHandle clone_pieces (const FormatArgsHandle &);
void destroy_pieces (FormatArgsHandle);
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 062f85d..d11eed7 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -51,21 +51,12 @@ class TypePath;
// A type generic parameter (as opposed to a lifetime generic parameter)
class TypeParam : public GenericParam
{
- // bool has_outer_attribute;
- // std::unique_ptr<Attribute> outer_attr;
AST::AttrVec outer_attrs;
-
Identifier type_representation;
-
- // bool has_type_param_bounds;
- // TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
- type_param_bounds; // inlined form
-
- // bool has_type;
+ std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
std::unique_ptr<Type> type;
-
location_t locus;
+ bool was_impl_trait;
public:
Identifier get_type_representation () const { return type_representation; }
@@ -85,18 +76,19 @@ public:
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds
= std::vector<std::unique_ptr<TypeParamBound>> (),
std::unique_ptr<Type> type = nullptr,
- AST::AttrVec outer_attrs = {})
+ AST::AttrVec outer_attrs = {}, bool was_impl_trait = false)
: GenericParam (Analysis::Mappings::get ().get_next_node_id ()),
outer_attrs (std::move (outer_attrs)),
type_representation (std::move (type_representation)),
type_param_bounds (std::move (type_param_bounds)),
- type (std::move (type)), locus (locus)
+ type (std::move (type)), locus (locus), was_impl_trait (was_impl_trait)
{}
// Copy constructor uses clone
TypeParam (TypeParam const &other)
: GenericParam (other.node_id), outer_attrs (other.outer_attrs),
- type_representation (other.type_representation), locus (other.locus)
+ type_representation (other.type_representation), locus (other.locus),
+ was_impl_trait (other.was_impl_trait)
{
// guard to prevent null pointer dereference
if (other.type != nullptr)
@@ -114,6 +106,7 @@ public:
outer_attrs = other.outer_attrs;
locus = other.locus;
node_id = other.node_id;
+ was_impl_trait = other.was_impl_trait;
// guard to prevent null pointer dereference
if (other.type != nullptr)
@@ -153,17 +146,19 @@ public:
return type;
}
- // TODO: mutable getter seems kinda dodgy
std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
{
return type_param_bounds;
}
+
const std::vector<std::unique_ptr<TypeParamBound>> &
get_type_param_bounds () const
{
return type_param_bounds;
}
+ bool from_impl_trait () const { return was_impl_trait; }
+
protected:
// Clone function implementation as virtual method
TypeParam *clone_generic_param_impl () const override
@@ -2455,7 +2450,7 @@ class ConstantItem : public VisItem, public AssociatedItem
// either has an identifier or "_" - maybe handle in identifier?
// bool identifier_is_underscore;
// if no identifier declared, identifier will be "_"
- std::string identifier;
+ Identifier identifier;
std::unique_ptr<Type> type;
std::unique_ptr<Expr> const_expr;
@@ -2465,7 +2460,7 @@ class ConstantItem : public VisItem, public AssociatedItem
public:
std::string as_string () const override;
- ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type,
+ ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type,
std::unique_ptr<Expr> const_expr,
std::vector<Attribute> outer_attrs, location_t locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
@@ -2473,7 +2468,7 @@ public:
const_expr (std::move (const_expr)), locus (locus)
{}
- ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type,
+ ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type,
std::vector<Attribute> outer_attrs, location_t locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
identifier (std::move (ident)), type (std::move (type)),
@@ -2516,7 +2511,7 @@ public:
/* Returns whether constant item is an "unnamed" (wildcard underscore used
* as identifier) constant. */
- bool is_unnamed () const { return identifier == "_"; }
+ bool is_unnamed () const { return identifier.as_string () == "_"; }
location_t get_locus () const override final { return locus; }
@@ -2561,7 +2556,7 @@ public:
return type;
}
- std::string get_identifier () const { return identifier; }
+ const Identifier &get_identifier () const { return identifier; }
Item::Kind get_item_kind () const override
{
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index fc01e57..4165075 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -27,6 +27,11 @@
#include "rust-macro-builtins.h"
namespace Rust {
+
+// forward declarations for AttributeParser
+class MacroInvocLexer;
+template <typename ManagedTokenSource> class Parser;
+
namespace AST {
class MacroFragSpec
@@ -756,22 +761,16 @@ private:
std::vector<std::unique_ptr<MacroInvocation>> pending_eager_invocs;
protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
MacroInvocation *clone_pattern_impl () const final override
{
return clone_macro_invocation_impl ();
}
- /* Use covariance to implement clone function as returning this object rather
- * than base */
MacroInvocation *clone_expr_without_block_impl () const final override
{
return clone_macro_invocation_impl ();
}
- /* Use covariance to implement clone function as returning this object rather
- * than base */
MacroInvocation *clone_type_no_bounds_impl () const final override
{
return clone_macro_invocation_impl ();
@@ -788,6 +787,20 @@ public:
return new MacroInvocation (*this);
}
+ std::unique_ptr<MacroInvocation> reconstruct_macro_invocation () const
+ {
+ return nullptr;
+ // return reconstruct (this,
+ // &MacroInvocation::reconstruct_macro_invocation_impl);
+ }
+
+ MacroInvocation *reconstruct_impl () const override
+ {
+ return new MacroInvocation (kind, builtin_kind, invoc_data, outer_attrs,
+ locus, is_semi_coloned,
+ reconstruct_vec (pending_eager_invocs));
+ }
+
void add_semicolon () override { is_semi_coloned = true; }
Pattern::Kind get_pattern_kind () override
@@ -1108,16 +1121,14 @@ struct AttributeParser
{
private:
// TODO: might as well rewrite to use lexer tokens
- std::vector<std::unique_ptr<Token>> token_stream;
- int stream_pos;
+ std::unique_ptr<MacroInvocLexer> lexer;
+ std::unique_ptr<Parser<MacroInvocLexer>> parser;
public:
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)
- {}
+ int stream_start_pos = 0);
- ~AttributeParser () = default;
+ ~AttributeParser ();
std::vector<std::unique_ptr<MetaItemInner>> parse_meta_item_seq ();
@@ -1126,24 +1137,10 @@ private:
std::unique_ptr<MetaItemInner> parse_meta_item_inner ();
// Returns whether token can end a meta item.
bool is_end_meta_item_tok (TokenId id) const;
- // Parses a simple path.
- SimplePath parse_simple_path ();
- // Parses a segment of a simple path (but not scope resolution operator).
- SimplePathSegment parse_simple_path_segment ();
// Parses a MetaItemLitExpr.
std::unique_ptr<MetaItemLitExpr> parse_meta_item_lit ();
- // Parses a literal.
- Literal parse_literal ();
// Parses a meta item that begins with a simple path.
std::unique_ptr<MetaItem> parse_path_meta_item ();
-
- // TODO: should this be const?
- std::unique_ptr<Token> &peek_token (int i = 0)
- {
- return token_stream[stream_pos + i];
- }
-
- void skip_token (int i = 0) { stream_pos += 1 + i; }
};
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc
index 8e43ddf..793423a 100644
--- a/gcc/rust/ast/rust-path.cc
+++ b/gcc/rust/ast/rust-path.cc
@@ -266,6 +266,27 @@ TypePath::as_simple_path () const
locus);
}
+std::string
+TypePath::make_debug_string () const
+{
+ rust_assert (!segments.empty ());
+
+ std::string output;
+
+ for (const auto &segment : segments)
+ {
+ if (segment != nullptr && !segment->is_lang_item ()
+ && !segment->is_error ())
+ {
+ if (!output.empty () || has_opening_scope_resolution_op ())
+ output.append ("::");
+ output.append (segment->get_ident_segment ().as_string ());
+ }
+ }
+
+ return output;
+}
+
// hopefully definition here will prevent circular dependency issue
TraitBound *
TypePath::to_trait_bound (bool in_parens) const
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index a4ba93b..a1b19d5 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -391,6 +391,13 @@ public:
return default_value.value ();
}
+ tl::optional<GenericArg> &get_default_value () { return default_value; }
+
+ const tl::optional<GenericArg> &get_default_value () const
+ {
+ return default_value;
+ }
+
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
@@ -779,6 +786,11 @@ public:
{
return new TypePathSegment (*this);
}
+ virtual TypePathSegment *reconstruct_impl () const
+ {
+ return new TypePathSegment (lang_item, ident_segment,
+ has_separating_scope_resolution, locus);
+ }
public:
virtual ~TypePathSegment () {}
@@ -790,6 +802,11 @@ public:
{
return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ());
}
+ // Unique pointer custom reconstruct function
+ std::unique_ptr<TypePathSegment> reconstruct () const
+ {
+ return reconstruct_base (this);
+ }
TypePathSegment (PathIdentSegment ident_segment,
bool has_separating_scope_resolution, location_t locus)
@@ -814,6 +831,15 @@ public:
node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
+ // General constructor
+ TypePathSegment (tl::optional<LangItem::Kind> lang_item,
+ tl::optional<PathIdentSegment> ident_segment,
+ bool has_separating_scope_resolution, location_t locus)
+ : lang_item (lang_item), ident_segment (ident_segment), locus (locus),
+ has_separating_scope_resolution (has_separating_scope_resolution),
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
+ {}
+
TypePathSegment (TypePathSegment const &other)
: lang_item (other.lang_item), ident_segment (other.ident_segment),
locus (other.locus),
@@ -968,11 +994,7 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: is this better? Or is a "vis_pattern" better?
- GenericArgs &get_generic_args ()
- {
- rust_assert (has_generic_args ());
- return generic_args;
- }
+ GenericArgs &get_generic_args () { return generic_args; }
// Use covariance to override base class method
TypePathSegmentGeneric *clone_type_path_segment_impl () const override
@@ -1149,6 +1171,11 @@ protected:
{
return new TypePath (*this);
}
+ TypePath *reconstruct_impl () const override
+ {
+ return new TypePath (reconstruct_vec (segments), locus,
+ has_opening_scope_resolution);
+ }
public:
/* Returns whether the TypePath has an opening scope resolution operator
@@ -1215,6 +1242,8 @@ public:
std::string as_string () const override;
+ std::string make_debug_string () const;
+
/* Converts TypePath to SimplePath if possible (i.e. no generic or function
* arguments). Otherwise returns an empty SimplePath. */
SimplePath as_simple_path () const;
@@ -1438,6 +1467,12 @@ protected:
{
return new QualifiedPathInType (*this);
}
+ QualifiedPathInType *reconstruct_impl () const override
+ {
+ return new QualifiedPathInType (path_type,
+ associated_segment->reconstruct (),
+ reconstruct_vec (segments), locus);
+ }
public:
QualifiedPathInType (
diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc
index fc7b610..15ab0b7 100644
--- a/gcc/rust/ast/rust-pattern.cc
+++ b/gcc/rust/ast/rust-pattern.cc
@@ -65,8 +65,8 @@ IdentifierPattern::as_string () const
str += variable_ident.as_string ();
- if (has_pattern_to_bind ())
- str += " @ " + to_bind->as_string ();
+ if (has_subpattern ())
+ str += " @ " + subpattern->as_string ();
return str;
}
@@ -327,17 +327,53 @@ GroupedExpr::as_string () const
}
std::string
-SlicePattern::as_string () const
+SlicePatternItemsNoRest::as_string () const
{
- std::string str ("SlicePattern: ");
+ std::string str;
- for (const auto &pattern : items)
+ for (const auto &pattern : patterns)
str += "\n " + pattern->as_string ();
return str;
}
std::string
+SlicePatternItemsHasRest::as_string () const
+{
+ std::string str;
+
+ str += "\n Lower patterns: ";
+ if (lower_patterns.empty ())
+ {
+ str += "none";
+ }
+ else
+ {
+ for (const auto &lower : lower_patterns)
+ str += "\n " + lower->as_string ();
+ }
+
+ str += "\n Upper patterns: ";
+ if (upper_patterns.empty ())
+ {
+ str += "none";
+ }
+ else
+ {
+ for (const auto &upper : upper_patterns)
+ str += "\n " + upper->as_string ();
+ }
+
+ return str;
+}
+
+std::string
+SlicePattern::as_string () const
+{
+ return "SlicePattern: " + items->as_string ();
+}
+
+std::string
AltPattern::as_string () const
{
std::string str ("AltPattern: ");
@@ -367,6 +403,18 @@ GroupedExpr::accept_vis (ASTVisitor &vis)
}
void
+SlicePatternItemsNoRest::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+SlicePatternItemsHasRest::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
SlicePattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index 69dbd98..4945ec4 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -74,7 +74,7 @@ class IdentifierPattern : public Pattern
bool is_mut;
// bool has_pattern;
- std::unique_ptr<Pattern> to_bind;
+ std::unique_ptr<Pattern> subpattern;
location_t locus;
NodeId node_id;
@@ -82,22 +82,22 @@ public:
std::string as_string () const override;
// Returns whether the IdentifierPattern has a pattern to bind.
- bool has_pattern_to_bind () const { return to_bind != nullptr; }
+ bool has_subpattern () const { return subpattern != nullptr; }
// Constructor
IdentifierPattern (Identifier ident, location_t locus, bool is_ref = false,
bool is_mut = false,
- std::unique_ptr<Pattern> to_bind = nullptr)
+ std::unique_ptr<Pattern> subpattern = nullptr)
: Pattern (), variable_ident (std::move (ident)), is_ref (is_ref),
- is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus),
+ is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus),
node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
IdentifierPattern (NodeId node_id, Identifier ident, location_t locus,
bool is_ref = false, bool is_mut = false,
- std::unique_ptr<Pattern> to_bind = nullptr)
+ std::unique_ptr<Pattern> subpattern = nullptr)
: Pattern (), variable_ident (std::move (ident)), is_ref (is_ref),
- is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus),
+ is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus),
node_id (node_id)
{}
@@ -107,8 +107,8 @@ public:
is_mut (other.is_mut), locus (other.locus), node_id (other.node_id)
{
// fix to get prevent null pointer dereference
- if (other.to_bind != nullptr)
- to_bind = other.to_bind->clone_pattern ();
+ if (other.subpattern != nullptr)
+ subpattern = other.subpattern->clone_pattern ();
}
// Overload assignment operator to use clone
@@ -121,10 +121,10 @@ public:
node_id = other.node_id;
// fix to prevent null pointer dereference
- if (other.to_bind != nullptr)
- to_bind = other.to_bind->clone_pattern ();
+ if (other.subpattern != nullptr)
+ subpattern = other.subpattern->clone_pattern ();
else
- to_bind = nullptr;
+ subpattern = nullptr;
return *this;
}
@@ -137,11 +137,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
- // TODO: is this better? Or is a "vis_pattern" better?
- Pattern &get_pattern_to_bind ()
+ Pattern &get_subpattern ()
{
- rust_assert (has_pattern_to_bind ());
- return *to_bind;
+ rust_assert (has_subpattern ());
+ return *subpattern;
}
Identifier get_ident () const { return variable_ident; }
@@ -375,8 +374,7 @@ enum class RangeKind
EXCLUDED,
};
-RangeKind
-tokenid_to_rangekind (TokenId id);
+RangeKind tokenid_to_rangekind (TokenId id);
// AST node for matching within a certain range (range pattern)
class RangePattern : public Pattern
{
@@ -950,7 +948,7 @@ public:
* is empty). */
bool has_struct_pattern_elems () const { return !elems.is_empty (); }
- location_t get_locus () const override { return path.get_locus (); }
+ location_t get_locus () const override { return locus; }
void accept_vis (ASTVisitor &vis) override;
@@ -1523,41 +1521,217 @@ protected:
}
};
+// Base abstract class representing patterns in a SlicePattern
+class SlicePatternItems
+{
+public:
+ enum SlicePatternItemType
+ {
+ NO_REST,
+ HAS_REST,
+ };
+
+ virtual ~SlicePatternItems () {}
+
+ // TODO: should this store location data?
+
+ // Unique pointer custom clone function
+ std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const
+ {
+ return std::unique_ptr<SlicePatternItems> (
+ clone_slice_pattern_items_impl ());
+ }
+
+ virtual std::string as_string () const = 0;
+
+ virtual void accept_vis (ASTVisitor &vis) = 0;
+
+ virtual SlicePatternItemType get_pattern_type () const = 0;
+
+protected:
+ // pure virtual clone implementation
+ virtual SlicePatternItems *clone_slice_pattern_items_impl () const = 0;
+};
+
+// Class representing the patterns in a SlicePattern without `..`
+class SlicePatternItemsNoRest : public SlicePatternItems
+{
+ std::vector<std::unique_ptr<Pattern>> patterns;
+
+public:
+ SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
+ : patterns (std::move (patterns))
+ {}
+
+ // Copy constructor with vector clone
+ SlicePatternItemsNoRest (SlicePatternItemsNoRest const &other)
+ {
+ patterns.reserve (other.patterns.size ());
+ for (const auto &e : other.patterns)
+ patterns.push_back (e->clone_pattern ());
+ }
+
+ // Overloaded assignment operator to vector clone
+ SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest const &other)
+ {
+ patterns.clear ();
+ patterns.reserve (other.patterns.size ());
+ for (const auto &e : other.patterns)
+ patterns.push_back (e->clone_pattern ());
+
+ return *this;
+ }
+
+ // move constructors
+ SlicePatternItemsNoRest (SlicePatternItemsNoRest &&other) = default;
+ SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest &&other)
+ = default;
+
+ std::string as_string () const override;
+
+ 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
+ {
+ return patterns;
+ }
+
+ SlicePatternItemType get_pattern_type () const override
+ {
+ return SlicePatternItemType::NO_REST;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ SlicePatternItemsNoRest *clone_slice_pattern_items_impl () const override
+ {
+ return new SlicePatternItemsNoRest (*this);
+ }
+};
+
+// Class representing the patterns in a SlicePattern that contains a `..`
+class SlicePatternItemsHasRest : public SlicePatternItems
+{
+ std::vector<std::unique_ptr<Pattern>> lower_patterns;
+ std::vector<std::unique_ptr<Pattern>> upper_patterns;
+
+public:
+ SlicePatternItemsHasRest (
+ 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))
+ {}
+
+ // Copy constructor with vector clone
+ SlicePatternItemsHasRest (SlicePatternItemsHasRest const &other)
+ {
+ lower_patterns.reserve (other.lower_patterns.size ());
+ for (const auto &e : other.lower_patterns)
+ lower_patterns.push_back (e->clone_pattern ());
+
+ upper_patterns.reserve (other.upper_patterns.size ());
+ for (const auto &e : other.upper_patterns)
+ upper_patterns.push_back (e->clone_pattern ());
+ }
+
+ // Overloaded assignment operator to clone
+ SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest const &other)
+ {
+ lower_patterns.clear ();
+ lower_patterns.reserve (other.lower_patterns.size ());
+ for (const auto &e : other.lower_patterns)
+ lower_patterns.push_back (e->clone_pattern ());
+
+ upper_patterns.clear ();
+ upper_patterns.reserve (other.upper_patterns.size ());
+ for (const auto &e : other.upper_patterns)
+ upper_patterns.push_back (e->clone_pattern ());
+
+ return *this;
+ }
+
+ // move constructors
+ SlicePatternItemsHasRest (SlicePatternItemsHasRest &&other) = default;
+ SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest &&other)
+ = default;
+
+ std::string as_string () const override;
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: seems kinda dodgy. Think of better way.
+ 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;
+ }
+
+ // TODO: seems kinda dodgy. Think of better way.
+ 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;
+ }
+
+ SlicePatternItemType get_pattern_type () const override
+ {
+ return SlicePatternItemType::HAS_REST;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ SlicePatternItemsHasRest *clone_slice_pattern_items_impl () const override
+ {
+ return new SlicePatternItemsHasRest (*this);
+ }
+};
+
// AST node representing patterns that can match slices and arrays
class SlicePattern : public Pattern
{
- std::vector<std::unique_ptr<Pattern>> items;
+ std::unique_ptr<SlicePatternItems> items;
location_t locus;
NodeId node_id;
public:
std::string as_string () const override;
- SlicePattern (std::vector<std::unique_ptr<Pattern>> items, location_t locus)
+ SlicePattern (std::unique_ptr<SlicePatternItems> items, location_t locus)
: items (std::move (items)), locus (locus),
node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
- // Copy constructor with vector clone
+ // Copy constructor requires clone
SlicePattern (SlicePattern const &other) : locus (other.locus)
{
+ // guard to prevent null dereference
+ rust_assert (other.items != nullptr);
+
node_id = other.node_id;
- items.reserve (other.items.size ());
- for (const auto &e : other.items)
- items.push_back (e->clone_pattern ());
+ items = other.items->clone_slice_pattern_items ();
}
- // Overloaded assignment operator to vector clone
+ // Overloaded assignment operator to clone
SlicePattern &operator= (SlicePattern const &other)
{
locus = other.locus;
node_id = other.node_id;
- items.clear ();
- items.reserve (other.items.size ());
- for (const auto &e : other.items)
- items.push_back (e->clone_pattern ());
+ // guard to prevent null dereference
+ rust_assert (other.items != nullptr);
+ items = other.items->clone_slice_pattern_items ();
return *this;
}
@@ -1570,10 +1744,10 @@ 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
+ SlicePatternItems &get_items ()
{
- return items;
+ rust_assert (items != nullptr);
+ return *items;
}
NodeId get_node_id () const override { return node_id; }
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 1bb521d..2a3496b 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -19,7 +19,9 @@
#ifndef RUST_AST_TYPE_H
#define RUST_AST_TYPE_H
+#include "optional.h"
#include "rust-ast.h"
+#include "rust-expr.h"
#include "rust-path.h"
namespace Rust {
@@ -73,6 +75,13 @@ public:
type_path (std::move (type_path)), locus (locus)
{}
+ TraitBound (TraitBound const &other)
+ : TypeParamBound (other.get_node_id ()), in_parens (other.in_parens),
+ opening_question_mark (other.opening_question_mark),
+ for_lifetimes (other.for_lifetimes), type_path (other.type_path),
+ locus (other.locus)
+ {}
+
std::string as_string () const override;
location_t get_locus () const override final { return locus; }
@@ -99,6 +108,11 @@ protected:
return new TraitBound (node_id, type_path, locus, in_parens,
opening_question_mark, for_lifetimes);
}
+ TraitBound *reconstruct_impl () const override
+ {
+ return new TraitBound (type_path, locus, in_parens, opening_question_mark,
+ for_lifetimes);
+ }
};
// definition moved to rust-ast.h
@@ -120,6 +134,10 @@ protected:
{
return new ImplTraitType (*this);
}
+ ImplTraitType *reconstruct_impl () const override
+ {
+ return new ImplTraitType (reconstruct_vec (type_param_bounds), locus);
+ }
public:
ImplTraitType (
@@ -129,7 +147,8 @@ public:
{}
// copy constructor with vector clone
- ImplTraitType (ImplTraitType const &other) : locus (other.locus)
+ ImplTraitType (ImplTraitType const &other)
+ : Type (other.node_id), locus (other.locus)
{
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
@@ -184,6 +203,11 @@ protected:
{
return new TraitObjectType (*this);
}
+ TraitObjectType *reconstruct_impl () const override
+ {
+ return new TraitObjectType (reconstruct_vec (type_param_bounds), locus,
+ has_dyn);
+ }
public:
TraitObjectType (
@@ -195,7 +219,7 @@ public:
// copy constructor with vector clone
TraitObjectType (TraitObjectType const &other)
- : has_dyn (other.has_dyn), locus (other.locus)
+ : Type (other.node_id), has_dyn (other.has_dyn), locus (other.locus)
{
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
@@ -251,6 +275,10 @@ protected:
{
return new ParenthesisedType (*this);
}
+ ParenthesisedType *reconstruct_impl () const override
+ {
+ return new ParenthesisedType (type_in_parens->reconstruct (), locus);
+ }
public:
// Constructor uses Type pointer for polymorphism
@@ -305,33 +333,35 @@ public:
// Impl trait with a single bound? Poor reference material here.
class ImplTraitTypeOneBound : public TypeNoBounds
{
- TraitBound trait_bound;
+ std::unique_ptr<TypeParamBound> trait_bound;
location_t locus;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override
- {
- return new ImplTraitTypeOneBound (*this);
- }
-
public:
- ImplTraitTypeOneBound (TraitBound trait_bound, location_t locus)
+ ImplTraitTypeOneBound (std::unique_ptr<TypeParamBound> trait_bound,
+ location_t locus)
: trait_bound (std::move (trait_bound)), locus (locus)
{}
+ ImplTraitTypeOneBound (ImplTraitTypeOneBound const &other)
+ : trait_bound (other.trait_bound->clone_type_param_bound ()),
+ locus (other.locus)
+ {}
+
std::string as_string () const override;
location_t get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
- // TODO: would a "vis_type" be better?
- TraitBound &get_trait_bound ()
+ std::unique_ptr<TypeParamBound> &get_trait_bound () { return trait_bound; }
+
+ TypeNoBounds *clone_type_no_bounds_impl () const override
{
- // TODO: check to ensure invariants are met?
- return trait_bound;
+ return new ImplTraitTypeOneBound (*this);
+ }
+ TypeNoBounds *reconstruct_impl () const override
+ {
+ return new ImplTraitTypeOneBound (trait_bound->reconstruct (), locus);
}
};
@@ -350,6 +380,10 @@ protected:
{
return new TraitObjectTypeOneBound (*this);
}
+ TraitObjectTypeOneBound *reconstruct_impl () const override
+ {
+ return new TraitObjectTypeOneBound (trait_bound, locus, has_dyn);
+ }
public:
TraitObjectTypeOneBound (TraitBound trait_bound, location_t locus,
@@ -443,6 +477,10 @@ protected:
{
return new TupleType (*this);
}
+ TupleType *reconstruct_impl () const override
+ {
+ return new TupleType (reconstruct_vec (elems), locus);
+ }
};
/* A type with no values, representing the result of computations that never
@@ -459,6 +497,10 @@ protected:
{
return new NeverType (*this);
}
+ NeverType *reconstruct_impl () const override
+ {
+ return new NeverType (locus);
+ }
public:
NeverType (location_t locus) : locus (locus) {}
@@ -529,6 +571,9 @@ public:
return *type;
}
+ // Getter for direct access to the type unique_ptr
+ std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -536,6 +581,10 @@ protected:
{
return new RawPointerType (*this);
}
+ RawPointerType *reconstruct_impl () const override
+ {
+ return new RawPointerType (pointer_type, type->reconstruct (), locus);
+ }
};
// A type pointing to memory owned by another value
@@ -604,6 +653,9 @@ public:
TypeNoBounds &get_base_type () { return *type; }
+ // Getter for direct access to the type unique_ptr
+ std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -611,33 +663,42 @@ protected:
{
return new ReferenceType (*this);
}
+ ReferenceType *reconstruct_impl () const override
+ {
+ return new ReferenceType (has_mut, type->reconstruct (), locus,
+ // TODO: Improve this - it's ugly!
+ has_lifetime () ? tl::make_optional<Lifetime> (
+ lifetime->get_lifetime_type (),
+ lifetime->get_lifetime_name (),
+ lifetime->get_locus ())
+ : tl::nullopt);
+ }
};
// A fixed-size sequence of elements of a specified type
class ArrayType : public TypeNoBounds
{
std::unique_ptr<Type> elem_type;
- std::unique_ptr<Expr> size;
+ AnonConst size;
location_t locus;
public:
// Constructor requires pointers for polymorphism
- ArrayType (std::unique_ptr<Type> type, std::unique_ptr<Expr> array_size,
- location_t locus)
+ ArrayType (std::unique_ptr<Type> type, AnonConst array_size, location_t locus)
: elem_type (std::move (type)), size (std::move (array_size)), locus (locus)
{}
// Copy constructor requires deep copies of both unique pointers
ArrayType (ArrayType const &other)
- : elem_type (other.elem_type->clone_type ()),
- size (other.size->clone_expr ()), locus (other.locus)
+ : elem_type (other.elem_type->clone_type ()), size (other.size),
+ locus (other.locus)
{}
// Overload assignment operator to deep copy pointers
ArrayType &operator= (ArrayType const &other)
{
elem_type = other.elem_type->clone_type ();
- size = other.size->clone_expr ();
+ size = other.size;
locus = other.locus;
return *this;
}
@@ -660,12 +721,15 @@ public:
}
// TODO: would a "vis_expr" be better?
- Expr &get_size_expr ()
+ AnonConst &get_size_expr ()
{
- rust_assert (size != nullptr);
- return *size;
+ // rust_assert (size != nullptr);
+
+ return size;
}
+ std::unique_ptr<Type> &get_element_type () { return elem_type; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -673,6 +737,12 @@ protected:
{
return new ArrayType (*this);
}
+ ArrayType *reconstruct_impl () const override
+ {
+ return new ArrayType (elem_type->reconstruct (),
+ size /* FIXME: This should be `reconstruct_expr()` */,
+ locus);
+ }
};
/* A dynamically-sized type representing a "view" into a sequence of elements of
@@ -719,13 +789,20 @@ public:
return *elem_type;
}
+ // Getter for direct access to the elem_type unique_ptr
+ std::unique_ptr<Type> &get_elem_type_ptr () { return elem_type; }
+
protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
+ /* Use covariance to implement clone function as returning this object
+ * rather than base */
SliceType *clone_type_no_bounds_impl () const override
{
return new SliceType (*this);
}
+ SliceType *reconstruct_impl () const override
+ {
+ return new SliceType (elem_type->reconstruct (), locus);
+ }
};
/* Type used in generic arguments to explicitly request type inference (wildcard
@@ -736,13 +813,21 @@ class InferredType : public TypeNoBounds
// e.g. Vec<_> = whatever
protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
+ /* Use covariance to implement clone function as returning this object
+ * rather than base */
InferredType *clone_type_no_bounds_impl () const override
{
+ // This goes through the copy constructor
return new InferredType (*this);
}
+ InferredType *reconstruct_impl () const override
+ {
+ // This goes through the base constructor which calls the base
+ // TypeNoBounds constructor, which allocates a new NodeId
+ return new InferredType (locus);
+ }
+
public:
InferredType (location_t locus) : locus (locus) {}
@@ -961,9 +1046,17 @@ public:
FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; }
+ BareFunctionType *reconstruct_impl () const override
+ {
+ return new BareFunctionType (
+ for_lifetimes, function_qualifiers, params,
+ /* FIXME: Should params be reconstruct() as well? */
+ _is_variadic, variadic_attrs, return_type->reconstruct (), locus);
+ }
+
protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
+ /* Use covariance to implement clone function as returning this object
+ * rather than base */
BareFunctionType *clone_type_no_bounds_impl () const override
{
return new BareFunctionType (*this);
@@ -980,13 +1073,13 @@ class MacroInvocation;
* function item type?
* closure expression types?
* primitive types (bool, int, float, char, str (the slice))
- * Although supposedly TypePaths are used to reference these types (including
- * primitives) */
+ * Although supposedly TypePaths are used to reference these types
+ * (including primitives) */
/* FIXME: Incomplete spec references:
- * anonymous type parameters, aka "impl Trait in argument position" - impl then
- * trait bounds abstract return types, aka "impl Trait in return position" -
- * impl then trait bounds */
+ * anonymous type parameters, aka "impl Trait in argument position" - impl
+ * then trait bounds abstract return types, aka "impl Trait in return
+ * position" - impl then trait bounds */
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-asm.cc b/gcc/rust/backend/rust-compile-asm.cc
index 7351cf0..b7143a8 100644
--- a/gcc/rust/backend/rust-compile-asm.cc
+++ b/gcc/rust/backend/rust-compile-asm.cc
@@ -74,57 +74,94 @@ CompileAsm::asm_construct_string_tree (HIR::InlineAsm &expr)
return Backend::string_constant_expression (result);
}
+tl::optional<std::reference_wrapper<HIR::Expr>>
+get_out_expr (HIR::InlineAsmOperand &operand)
+{
+ switch (operand.get_register_type ())
+ {
+ case HIR::InlineAsmOperand::RegisterType::Out:
+ return *operand.get_out ().expr;
+ case HIR::InlineAsmOperand::RegisterType::InOut:
+ return *operand.get_in_out ().expr;
+ case HIR::InlineAsmOperand::RegisterType::SplitInOut:
+ return *operand.get_split_in_out ().out_expr;
+ case HIR::InlineAsmOperand::RegisterType::Const:
+ case HIR::InlineAsmOperand::RegisterType::Sym:
+ case HIR::InlineAsmOperand::RegisterType::Label:
+ case HIR::InlineAsmOperand::RegisterType::In:
+ break;
+ }
+ return tl::nullopt;
+}
+
tree
CompileAsm::asm_construct_outputs (HIR::InlineAsm &expr)
{
// TODO: Do i need to do this?
tree head = NULL_TREE;
- for (auto &output : expr.get_operands ())
+ for (auto &operand : expr.get_operands ())
{
- if (output.get_register_type ()
- == AST::InlineAsmOperand::RegisterType::Out)
- {
- auto out = output.get_out ();
-
- tree out_tree = CompileExpr::Compile (*out.expr, this->ctx);
- // expects a tree list
- // TODO: This assumes that the output is a register
- std::string expr_name = "=r";
- auto name = build_string (expr_name.size () + 1, expr_name.c_str ());
- head
- = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name),
- out_tree));
-
- /*Backend::debug (head);*/
- /*head = chainon (head, out_tree);*/
- }
+ tl::optional<std::reference_wrapper<HIR::Expr>> out_expr
+ = get_out_expr (operand);
+ if (!out_expr.has_value ())
+ continue;
+
+ tree out_tree = CompileExpr::Compile (*out_expr, this->ctx);
+ // expects a tree list
+ // TODO: This assumes that the output is a register
+ std::string expr_name = "=r";
+ auto name = build_string (expr_name.size () + 1, expr_name.c_str ());
+ head = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name),
+ out_tree));
+
+ /*Backend::debug (head);*/
+ /*head = chainon (head, out_tree);*/
}
return head;
}
+tl::optional<std::reference_wrapper<HIR::Expr>>
+get_in_expr (HIR::InlineAsmOperand &operand)
+{
+ switch (operand.get_register_type ())
+ {
+ case HIR::InlineAsmOperand::RegisterType::In:
+ return *operand.get_in ().expr;
+ case HIR::InlineAsmOperand::RegisterType::InOut:
+ return *operand.get_in_out ().expr;
+ case HIR::InlineAsmOperand::RegisterType::SplitInOut:
+ return *operand.get_split_in_out ().in_expr;
+ case HIR::InlineAsmOperand::RegisterType::Const:
+ case HIR::InlineAsmOperand::RegisterType::Sym:
+ case HIR::InlineAsmOperand::RegisterType::Label:
+ case HIR::InlineAsmOperand::RegisterType::Out:
+ break;
+ }
+ return tl::nullopt;
+}
+
tree
CompileAsm::asm_construct_inputs (HIR::InlineAsm &expr)
{
// TODO: Do i need to do this?
tree head = NULL_TREE;
- for (auto &input : expr.get_operands ())
+ for (auto &operand : expr.get_operands ())
{
- if (input.get_register_type () == AST::InlineAsmOperand::RegisterType::In)
- {
- auto in = input.get_in ();
-
- tree in_tree = CompileExpr::Compile (*in.expr, this->ctx);
- // expects a tree list
- // TODO: This assumes that the input is a register
- std::string expr_name = "r";
- auto name = build_string (expr_name.size () + 1, expr_name.c_str ());
- head
- = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name),
- in_tree));
-
- /*head = chainon (head, out_tree);*/
- }
+ tl::optional<std::reference_wrapper<HIR::Expr>> in_expr
+ = get_in_expr (operand);
+ if (!in_expr.has_value ())
+ continue;
+
+ tree in_tree = CompileExpr::Compile (*in_expr, this->ctx);
+ // expects a tree list
+ // TODO: This assumes that the input is a register
+ std::string expr_name = "r";
+ auto name = build_string (expr_name.size () + 1, expr_name.c_str ());
+ head = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name),
+ in_tree));
+
+ /*head = chainon (head, out_tree);*/
}
return head;
}
diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc
index 12b9561..73c34b2 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -576,6 +576,25 @@ HIRCompileBase::compile_constant_expr (
}
tree
+HIRCompileBase::query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty,
+ HIR::Expr &const_value_expr)
+{
+ HIRCompileBase c (ctx);
+
+ ctx->push_const_context ();
+
+ HirId expr_id = const_value_expr.get_mappings ().get_hirid ();
+ location_t locus = const_value_expr.get_locus ();
+ tree capacity_expr = HIRCompileBase::compile_constant_expr (
+ ctx, expr_id, expr_ty, expr_ty, Resolver::CanonicalPath::create_empty (),
+ const_value_expr, locus, locus);
+
+ ctx->pop_const_context ();
+
+ return fold_expr (capacity_expr);
+}
+
+tree
HIRCompileBase::indirect_expression (tree expr, location_t locus)
{
if (expr == error_mark_node)
@@ -677,8 +696,12 @@ HIRCompileBase::compile_function (
std::string ir_symbol_name
= canonical_path.get () + fntype->subst_as_string ();
+ rust_debug_loc (locus, "--> Compiling [%s] - %s", ir_symbol_name.c_str (),
+ fntype->get_name ().c_str ());
+
// we don't mangle the main fn since we haven't implemented the main shim
- bool is_main_fn = fn_name.compare ("main") == 0 && is_root_item;
+ bool is_main_fn = fn_name.compare ("main") == 0 && is_root_item
+ && canonical_path.size () <= 2;
if (is_main_fn)
{
rust_assert (!main_identifier_node);
@@ -687,14 +710,9 @@ HIRCompileBase::compile_function (
}
std::string asm_name = fn_name;
- auto &mappings = Analysis::Mappings::get ();
-
- if (flag_name_resolution_2_0)
- ir_symbol_name = mappings.get_current_crate_name () + "::" + ir_symbol_name;
-
unsigned int flags = 0;
tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name,
- "" /* asm_name */, flags, locus);
+ tl::nullopt /* asm_name */, flags, locus);
setup_fndecl (fndecl, is_main_fn, fntype->has_substitutions_defined (),
visibility, qualifiers, outer_attrs);
@@ -812,11 +830,12 @@ HIRCompileBase::compile_constant_item (
// machineary that we already have. This means the best approach is to
// make a _fake_ function with a block so it can hold onto temps then
// use our constexpr code to fold it completely or error_mark_node
- Backend::typed_identifier receiver;
+ Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
tree compiled_fn_type = Backend::function_type (
receiver, {}, {Backend::typed_identifier ("_", const_type, locus)}, NULL,
locus);
- tree fndecl = Backend::function (compiled_fn_type, ident, "", 0, locus);
+ tree fndecl
+ = Backend::function (compiled_fn_type, ident, tl::nullopt, 0, locus);
TREE_READONLY (fndecl) = 1;
tree enclosing_scope = NULL_TREE;
diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h
index 6814abc..e9b8596 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -38,6 +38,9 @@ public:
const Resolver::CanonicalPath &canonical_path, HIR::Expr &const_value_expr,
location_t locus, location_t expr_locus);
+ static tree query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty,
+ HIR::Expr &const_value_expr);
+
protected:
HIRCompileBase (Context *ctx) : ctx (ctx) {}
diff --git a/gcc/rust/backend/rust-compile-block.cc b/gcc/rust/backend/rust-compile-block.cc
index f844a27..03c36d2 100644
--- a/gcc/rust/backend/rust-compile-block.cc
+++ b/gcc/rust/backend/rust-compile-block.cc
@@ -19,6 +19,7 @@
#include "rust-compile-block.h"
#include "rust-compile-stmt.h"
#include "rust-compile-expr.h"
+#include "rust-hir-expr.h"
namespace Rust {
namespace Compile {
diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h
index 3f38d08..f84bace 100644
--- a/gcc/rust/backend/rust-compile-block.h
+++ b/gcc/rust/backend/rust-compile-block.h
@@ -20,6 +20,7 @@
#define RUST_COMPILE_BLOCK
#include "rust-compile-base.h"
+#include "rust-hir-expr.h"
#include "rust-hir-visitor.h"
namespace Rust {
@@ -83,6 +84,8 @@ public:
void visit (HIR::MethodCallExpr &) override {}
void visit (HIR::FieldAccessExpr &) override {}
void visit (HIR::BlockExpr &) override {}
+ void visit (HIR::AnonConst &) override {}
+ void visit (HIR::ConstBlock &) override {}
void visit (HIR::ContinueExpr &) override {}
void visit (HIR::BreakExpr &) override {}
void visit (HIR::RangeFromToExpr &) override {}
@@ -101,6 +104,7 @@ public:
void visit (HIR::AsyncBlockExpr &) override {}
void visit (HIR::InlineAsm &) override {}
void visit (HIR::LlvmInlineAsm &) override {}
+ void visit (HIR::OffsetOf &) override {}
private:
CompileConditionalBlocks (Context *ctx, Bvariable *result)
@@ -138,6 +142,12 @@ public:
translated = CompileBlock::compile (expr, ctx, result);
}
+ void visit (HIR::ConstBlock &expr) override
+ {
+ rust_unreachable ();
+ // translated = CompileExpr::compile (expr, ctx, result);
+ }
+
// Empty visit for unused Expression HIR nodes.
void visit (HIR::PathInExpression &) override {}
void visit (HIR::QualifiedPathInExpression &) override {}
@@ -184,6 +194,8 @@ public:
void visit (HIR::AsyncBlockExpr &) override {}
void visit (HIR::InlineAsm &) override {}
void visit (HIR::LlvmInlineAsm &) override {}
+ void visit (HIR::OffsetOf &) override {}
+ void visit (HIR::AnonConst &) override {}
private:
CompileExprWithBlock (Context *ctx, Bvariable *result)
diff --git a/gcc/rust/backend/rust-compile-context.cc b/gcc/rust/backend/rust-compile-context.cc
index 86f0894..349d492 100644
--- a/gcc/rust/backend/rust-compile-context.cc
+++ b/gcc/rust/backend/rust-compile-context.cc
@@ -22,9 +22,18 @@
namespace Rust {
namespace Compile {
+Context *
+Context::get ()
+{
+ static Context *instance;
+ if (instance == nullptr)
+ instance = new Context ();
+
+ return instance;
+}
+
Context::Context ()
- : resolver (Resolver::Resolver::get ()),
- tyctx (Resolver::TypeCheckContext::get ()),
+ : tyctx (Resolver::TypeCheckContext::get ()),
mappings (Analysis::Mappings::get ()), mangler (Mangler ())
{
setup_builtins ();
@@ -70,7 +79,8 @@ Context::type_hasher (tree type)
hstate.add_object (TYPE_HASH (TYPE_OFFSET_BASETYPE (type)));
break;
- case ARRAY_TYPE: {
+ case ARRAY_TYPE:
+ {
if (TYPE_DOMAIN (type))
hstate.add_object (TYPE_HASH (TYPE_DOMAIN (type)));
if (!AGGREGATE_TYPE_P (TREE_TYPE (type)))
@@ -81,7 +91,8 @@ Context::type_hasher (tree type)
}
break;
- case INTEGER_TYPE: {
+ case INTEGER_TYPE:
+ {
tree t = TYPE_MAX_VALUE (type);
if (!t)
t = TYPE_MIN_VALUE (type);
@@ -91,7 +102,8 @@ Context::type_hasher (tree type)
}
case REAL_TYPE:
- case FIXED_POINT_TYPE: {
+ case FIXED_POINT_TYPE:
+ {
unsigned prec = TYPE_PRECISION (type);
hstate.add_object (prec);
break;
@@ -103,7 +115,8 @@ Context::type_hasher (tree type)
case RECORD_TYPE:
case UNION_TYPE:
- case QUAL_UNION_TYPE: {
+ case QUAL_UNION_TYPE:
+ {
for (tree t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
{
hashval_t name_hash = IDENTIFIER_HASH_VALUE (DECL_NAME (t));
@@ -118,7 +131,8 @@ Context::type_hasher (tree type)
break;
case REFERENCE_TYPE:
- case POINTER_TYPE: {
+ case POINTER_TYPE:
+ {
hashval_t type_hash = type_hasher (TREE_TYPE (type));
hstate.add_object (type_hash);
}
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index ce81a1d..d4a642b 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -49,7 +49,7 @@ struct CustomDeriveInfo
class Context
{
public:
- Context ();
+ static Context *get ();
void setup_builtins ();
@@ -90,7 +90,6 @@ public:
return type;
}
- Resolver::Resolver *get_resolver () { return resolver; }
Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
Analysis::Mappings &get_mappings () { return mappings; }
@@ -391,7 +390,8 @@ public:
}
private:
- Resolver::Resolver *resolver;
+ Context ();
+
Resolver::TypeCheckContext *tyctx;
Analysis::Mappings &mappings;
Mangler mangler;
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index dd3420f..6433923 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -17,6 +17,8 @@
// <http://www.gnu.org/licenses/>.
#include "rust-compile-expr.h"
+#include "rust-backend.h"
+#include "rust-compile-type.h"
#include "rust-compile-struct-field-expr.h"
#include "rust-compile-pattern.h"
#include "rust-compile-resolve-path.h"
@@ -30,8 +32,11 @@
#include "realmpfr.h"
#include "convert.h"
#include "print-tree.h"
+#include "rust-hir-expr.h"
#include "rust-system.h"
+#include "rust-tree.h"
#include "rust-tyty.h"
+#include "tree-core.h"
namespace Rust {
namespace Compile {
@@ -375,6 +380,31 @@ CompileExpr::visit (HIR::LlvmInlineAsm &expr)
}
void
+CompileExpr::visit (HIR::OffsetOf &expr)
+{
+ TyTy::BaseType *type = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ expr.get_type ().get_mappings ().get_hirid (), &type))
+ {
+ translated = error_mark_node;
+ return;
+ }
+
+ auto compiled_ty = TyTyResolveCompile::compile (ctx, type);
+
+ rust_assert (TREE_CODE (compiled_ty) == RECORD_TYPE);
+
+ // Create an identifier node for the field
+ auto field_id = Backend::get_identifier_node (expr.get_field ().as_string ());
+
+ // And now look it up and get its value for `byte_position`
+ auto field = Backend::lookup_field (compiled_ty, field_id);
+ auto field_value = TREE_VALUE (field);
+
+ translated = byte_position (field_value);
+}
+
+void
CompileExpr::visit (HIR::IfExprConseqElse &expr)
{
TyTy::BaseType *if_type = nullptr;
@@ -441,6 +471,18 @@ CompileExpr::visit (HIR::BlockExpr &expr)
}
void
+CompileExpr::visit (HIR::AnonConst &expr)
+{
+ expr.get_inner_expr ().accept_vis (*this);
+}
+
+void
+CompileExpr::visit (HIR::ConstBlock &expr)
+{
+ expr.get_const_expr ().accept_vis (*this);
+}
+
+void
CompileExpr::visit (HIR::UnsafeBlockExpr &expr)
{
expr.get_block_expr ().accept_vis (*this);
@@ -471,6 +513,8 @@ CompileExpr::visit (HIR::StructExprStructFields &struct_expr)
rust_error_at (struct_expr.get_locus (), "unknown type");
return;
}
+ if (!tyty->is<TyTy::ADTType> ())
+ return;
// it must be an ADT
rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT);
@@ -669,6 +713,15 @@ void
CompileExpr::visit (HIR::LoopExpr &expr)
{
TyTy::BaseType *block_tyty = nullptr;
+ fncontext fnctx = ctx->peek_fn ();
+ if (ctx->const_context_p () && !DECL_DECLARED_CONSTEXPR_P (fnctx.fndecl))
+ {
+ rich_location r (line_table, expr.get_locus ());
+ rust_error_at (r, ErrorCode::E0658,
+ "%<loop%> is not allowed in const context");
+ return;
+ }
+
if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
&block_tyty))
{
@@ -676,7 +729,6 @@ CompileExpr::visit (HIR::LoopExpr &expr)
return;
}
- fncontext fnctx = ctx->peek_fn ();
tree enclosing_scope = ctx->peek_enclosing_scope ();
tree block_type = TyTyResolveCompile::compile (ctx, block_tyty);
@@ -701,7 +753,8 @@ CompileExpr::visit (HIR::LoopExpr &expr)
loop_label.get_lifetime ().get_mappings ().get_hirid (), label);
}
- tree loop_begin_label = Backend::label (fnctx.fndecl, "", expr.get_locus ());
+ tree loop_begin_label
+ = Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ());
tree loop_begin_label_decl
= Backend::label_definition_statement (loop_begin_label);
ctx->add_statement (loop_begin_label_decl);
@@ -743,7 +796,8 @@ CompileExpr::visit (HIR::WhileLoopExpr &expr)
start_location, end_location);
ctx->push_block (loop_block);
- tree loop_begin_label = Backend::label (fnctx.fndecl, "", expr.get_locus ());
+ tree loop_begin_label
+ = Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ());
tree loop_begin_label_decl
= Backend::label_definition_statement (loop_begin_label);
ctx->add_statement (loop_begin_label_decl);
@@ -787,25 +841,16 @@ CompileExpr::visit (HIR::BreakExpr &expr)
if (expr.has_label ())
{
- NodeId resolved_node_id = UNKNOWN_NODEID;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (auto id
- = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ()))
- resolved_node_id = *id;
- }
- else
+ NodeId resolved_node_id;
+ if (auto id
+ = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ()))
{
- NodeId tmp = UNKNOWN_NODEID;
- if (ctx->get_resolver ()->lookup_resolved_label (
- expr.get_label ().get_mappings ().get_nodeid (), &tmp))
- resolved_node_id = tmp;
+ resolved_node_id = *id;
}
-
- if (resolved_node_id == UNKNOWN_NODEID)
+ else
{
rust_error_at (
expr.get_label ().get_locus (),
@@ -849,26 +894,16 @@ CompileExpr::visit (HIR::ContinueExpr &expr)
tree label = ctx->peek_loop_begin_label ();
if (expr.has_label ())
{
- NodeId resolved_node_id = UNKNOWN_NODEID;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (auto id
- = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ()))
- resolved_node_id = *id;
- }
- else
+ NodeId resolved_node_id;
+ if (auto id
+ = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ()))
{
- NodeId tmp = UNKNOWN_NODEID;
-
- if (ctx->get_resolver ()->lookup_resolved_label (
- expr.get_label ().get_mappings ().get_nodeid (), &tmp))
- resolved_node_id = tmp;
+ resolved_node_id = *id;
}
-
- if (resolved_node_id == UNKNOWN_NODEID)
+ else
{
rust_error_at (
expr.get_label ().get_locus (),
@@ -1130,9 +1165,8 @@ CompileExpr::visit (HIR::MatchExpr &expr)
// setup the end label so the cases can exit properly
tree fndecl = fnctx.fndecl;
location_t end_label_locus = expr.get_locus (); // FIXME
- tree end_label
- = Backend::label (fndecl, "" /* empty creates an artificial label */,
- end_label_locus);
+ // tl::nullopt creates an artificial label
+ tree end_label = Backend::label (fndecl, tl::nullopt, end_label_locus);
tree end_label_decl_statement
= Backend::label_definition_statement (end_label);
@@ -1325,6 +1359,28 @@ CompileExpr::visit (HIR::CallExpr &expr)
};
auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx);
+ if (ctx->const_context_p ())
+ {
+ if (!FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn_address)))
+ {
+ rust_error_at (expr.get_locus (),
+ "calls in constants are limited to constant "
+ "functions, tuple structs and tuple variants");
+ return;
+ }
+
+ if (TREE_CODE (fn_address) == ADDR_EXPR)
+ {
+ tree fndecl = TREE_OPERAND (fn_address, 0);
+ if (!DECL_DECLARED_CONSTEXPR_P (fndecl))
+ {
+ rust_error_at (expr.get_locus (),
+ "calls in constants are limited to constant "
+ "functions, tuple structs and tuple variants");
+ return;
+ }
+ }
+ }
// is this a closure call?
bool possible_trait_call
@@ -1883,7 +1939,8 @@ CompileExpr::visit (HIR::ArrayExpr &expr)
HIR::ArrayElems &elements = expr.get_internal_elements ();
switch (elements.get_array_expr_type ())
{
- case HIR::ArrayElems::ArrayExprType::VALUES: {
+ case HIR::ArrayElems::ArrayExprType::VALUES:
+ {
HIR::ArrayElemsValues &elems
= static_cast<HIR::ArrayElemsValues &> (elements);
translated
@@ -2032,7 +2089,8 @@ HIRCompileBase::resolve_adjustements (
return error_mark_node;
case Resolver::Adjustment::AdjustmentType::IMM_REF:
- case Resolver::Adjustment::AdjustmentType::MUT_REF: {
+ case Resolver::Adjustment::AdjustmentType::MUT_REF:
+ {
if (!RS_DST_FLAG (TREE_TYPE (e)))
{
e = address_expression (e, locus);
@@ -2474,23 +2532,12 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr,
if (is_block_expr)
{
auto body_mappings = function_body.get_mappings ();
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- auto candidate = nr_ctx.values.to_rib (body_mappings.get_nodeid ());
+ auto candidate = nr_ctx.values.to_rib (body_mappings.get_nodeid ());
- rust_assert (candidate.has_value ());
- }
- else
- {
- Resolver::Rib *rib = nullptr;
- bool ok
- = ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (),
- &rib);
- rust_assert (ok);
- }
+ rust_assert (candidate.has_value ());
}
tree enclosing_scope = NULL_TREE;
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 65ed4b3..b8b4e8d 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -48,6 +48,8 @@ public:
void visit (HIR::IfExpr &expr) override;
void visit (HIR::IfExprConseqElse &expr) override;
void visit (HIR::BlockExpr &expr) override;
+ void visit (HIR::AnonConst &expr) override;
+ void visit (HIR::ConstBlock &expr) override;
void visit (HIR::UnsafeBlockExpr &expr) override;
void visit (HIR::StructExprStruct &struct_expr) override;
void visit (HIR::StructExprStructFields &struct_expr) override;
@@ -70,6 +72,7 @@ public:
void visit (HIR::ClosureExpr &expr) override;
void visit (HIR::InlineAsm &expr) override;
void visit (HIR::LlvmInlineAsm &expr) override;
+ void visit (HIR::OffsetOf &expr) override;
// TODO
void visit (HIR::ErrorPropagationExpr &) override {}
diff --git a/gcc/rust/backend/rust-compile-implitem.cc b/gcc/rust/backend/rust-compile-implitem.cc
index 1230c85..63df2f5 100644
--- a/gcc/rust/backend/rust-compile-implitem.cc
+++ b/gcc/rust/backend/rust-compile-implitem.cc
@@ -27,22 +27,11 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant)
rust_assert (concrete != nullptr);
TyTy::BaseType *resolved_type = concrete;
- tl::optional<Resolver::CanonicalPath> canonical_path;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path = nr_ctx.values.to_canonical_path (
- constant.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = ctx->get_mappings ().lookup_canonical_path (
- constant.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path);
+ Resolver::CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (constant.get_mappings ().get_nodeid ());
HIR::Expr &const_value_expr = constant.get_expr ();
TyTy::BaseType *expr_type = nullptr;
@@ -52,7 +41,7 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant)
tree const_expr
= compile_constant_item (constant.get_mappings ().get_hirid (), expr_type,
- resolved_type, *canonical_path, const_value_expr,
+ resolved_type, canonical_path, const_value_expr,
constant.get_locus (),
const_value_expr.get_locus ());
ctx->push_const (const_expr);
@@ -96,22 +85,11 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func)
fntype->override_context ();
}
- tl::optional<Resolver::CanonicalPath> canonical_path;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.values.to_canonical_path (func.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = ctx->get_mappings ().lookup_canonical_path (
- func.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path);
+ Resolver::CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (func.get_mappings ().get_nodeid ());
// FIXME: How do we get the proper visibility here?
auto vis = HIR::Visibility (HIR::Visibility::VisType::PUBLIC);
@@ -121,7 +99,7 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func)
function.get_self (), function.get_function_params (),
function.get_qualifiers (), vis,
func.get_outer_attrs (), func.get_locus (),
- &func.get_block_expr (), *canonical_path, fntype);
+ &func.get_block_expr (), canonical_path, fntype);
reference = address_expression (fndecl, ref_locus);
}
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index 4888e23..450a869 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -32,8 +32,7 @@
// declaration taken from "stringpool.h"
// the get_identifier macro causes compilation issues
-extern tree
-get_identifier (const char *);
+extern tree get_identifier (const char *);
namespace Rust {
namespace Compile {
@@ -70,28 +69,19 @@ check_for_basic_integer_type (const std::string &intrinsic_str,
return is_basic_integer;
}
-static tree
-offset_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-sizeof_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-transmute_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-rotate_handler (Context *ctx, TyTy::FnType *fntype, tree_code op);
-static tree
-wrapping_op_handler_inner (Context *ctx, TyTy::FnType *fntype, tree_code op);
-static tree
-op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, tree_code op);
-static tree
-uninit_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-move_val_init_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-assume_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-discriminant_value_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-variant_count_handler (Context *ctx, TyTy::FnType *fntype);
+static tree offset_handler (Context *ctx, TyTy::FnType *fntype);
+static tree sizeof_handler (Context *ctx, TyTy::FnType *fntype);
+static tree transmute_handler (Context *ctx, TyTy::FnType *fntype);
+static tree rotate_handler (Context *ctx, TyTy::FnType *fntype, tree_code op);
+static tree wrapping_op_handler_inner (Context *ctx, TyTy::FnType *fntype,
+ tree_code op);
+static tree op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype,
+ tree_code op);
+static tree uninit_handler (Context *ctx, TyTy::FnType *fntype);
+static tree move_val_init_handler (Context *ctx, TyTy::FnType *fntype);
+static tree assume_handler (Context *ctx, TyTy::FnType *fntype);
+static tree discriminant_value_handler (Context *ctx, TyTy::FnType *fntype);
+static tree variant_count_handler (Context *ctx, TyTy::FnType *fntype);
enum class Prefetch
{
@@ -99,8 +89,8 @@ enum class Prefetch
Write
};
-static tree
-prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind);
+static tree prefetch_data_handler (Context *ctx, TyTy::FnType *fntype,
+ Prefetch kind);
static inline tree
rotate_left_handler (Context *ctx, TyTy::FnType *fntype)
@@ -140,10 +130,10 @@ prefetch_write_data (Context *ctx, TyTy::FnType *fntype)
return prefetch_data_handler (ctx, fntype, Prefetch::Write);
}
-static tree
-atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering);
-static tree
-atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering);
+static tree atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype,
+ int ordering);
+static tree atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype,
+ int ordering);
static inline std::function<tree (Context *, TyTy::FnType *)>
atomic_store_handler (int ordering)
@@ -161,8 +151,8 @@ atomic_load_handler (int ordering)
};
}
-static inline tree
-unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, tree_code op);
+static inline tree unchecked_op_inner (Context *ctx, TyTy::FnType *fntype,
+ tree_code op);
const static std::function<tree (Context *, TyTy::FnType *)>
unchecked_op_handler (tree_code op)
@@ -172,8 +162,8 @@ unchecked_op_handler (tree_code op)
};
}
-static inline tree
-copy_handler_inner (Context *ctx, TyTy::FnType *fntype, bool overlaps);
+static inline tree copy_handler_inner (Context *ctx, TyTy::FnType *fntype,
+ bool overlaps);
const static std::function<tree (Context *, TyTy::FnType *)>
copy_handler (bool overlaps)
@@ -183,8 +173,8 @@ copy_handler (bool overlaps)
};
}
-static inline tree
-expect_handler_inner (Context *ctx, TyTy::FnType *fntype, bool likely);
+static inline tree expect_handler_inner (Context *ctx, TyTy::FnType *fntype,
+ bool likely);
const static std::function<tree (Context *, TyTy::FnType *)>
expect_handler (bool likely)
@@ -194,8 +184,8 @@ expect_handler (bool likely)
};
}
-static tree
-try_handler_inner (Context *ctx, TyTy::FnType *fntype, bool is_new_api);
+static tree try_handler_inner (Context *ctx, TyTy::FnType *fntype,
+ bool is_new_api);
const static std::function<tree (Context *, TyTy::FnType *)>
try_handler (bool is_new_api)
@@ -447,8 +437,8 @@ sizeof_handler (Context *ctx, TyTy::FnType *fntype)
// get the template parameter type tree fn size_of<T>();
rust_assert (fntype->get_num_substitutions () == 1);
auto &param_mapping = fntype->get_substs ().at (0);
- const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
- TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
+ const auto param_tyty = param_mapping.get_param_ty ();
+ auto resolved_tyty = param_tyty->resolve ();
tree template_parameter_type
= TyTyResolveCompile::compile (ctx, resolved_tyty);
@@ -653,8 +643,8 @@ op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, tree_code op)
rust_assert (fntype->get_num_substitutions () == 1);
auto &param_mapping = fntype->get_substs ().at (0);
- const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
- TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
+ const auto param_tyty = param_mapping.get_param_ty ();
+ auto resolved_tyty = param_tyty->resolve ();
tree template_parameter_type
= TyTyResolveCompile::compile (ctx, resolved_tyty);
@@ -1089,8 +1079,8 @@ uninit_handler (Context *ctx, TyTy::FnType *fntype)
// get the template parameter type tree fn uninit<T>();
rust_assert (fntype->get_num_substitutions () == 1);
auto &param_mapping = fntype->get_substs ().at (0);
- const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
- TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
+ const auto param_tyty = param_mapping.get_param_ty ();
+ auto resolved_tyty = param_tyty->resolve ();
tree template_parameter_type
= TyTyResolveCompile::compile (ctx, resolved_tyty);
@@ -1154,8 +1144,8 @@ move_val_init_handler (Context *ctx, TyTy::FnType *fntype)
// get the template parameter type tree fn size_of<T>();
rust_assert (fntype->get_num_substitutions () == 1);
auto &param_mapping = fntype->get_substs ().at (0);
- const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
- TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
+ auto param_tyty = param_mapping.get_param_ty ();
+ auto resolved_tyty = param_tyty->resolve ();
tree template_parameter_type
= TyTyResolveCompile::compile (ctx, resolved_tyty);
diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc
index 9666990..b72e70d 100644
--- a/gcc/rust/backend/rust-compile-item.cc
+++ b/gcc/rust/backend/rust-compile-item.cc
@@ -50,33 +50,21 @@ CompileItem::visit (HIR::StaticItem &var)
tree type = TyTyResolveCompile::compile (ctx, resolved_type);
- tl::optional<Resolver::CanonicalPath> canonical_path;
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.values.to_canonical_path (var.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = ctx->get_mappings ().lookup_canonical_path (
- var.get_mappings ().get_nodeid ());
- }
-
- rust_assert (canonical_path.has_value ());
+ Resolver::CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (var.get_mappings ().get_nodeid ());
ctx->push_const_context ();
tree value
= compile_constant_item (var.get_mappings ().get_hirid (), expr_type,
- resolved_type, *canonical_path, const_value_expr,
+ resolved_type, canonical_path, const_value_expr,
var.get_locus (), const_value_expr.get_locus ());
ctx->pop_const_context ();
- std::string name = canonical_path->get ();
- std::string asm_name = ctx->mangle_item (resolved_type, *canonical_path);
+ std::string name = canonical_path.get ();
+ std::string asm_name = ctx->mangle_item (resolved_type, canonical_path);
bool is_external = false;
bool is_hidden = false;
@@ -115,24 +103,12 @@ CompileItem::visit (HIR::ConstantItem &constant)
const_value_expr.get_mappings ().get_hirid (), &expr_type);
rust_assert (ok);
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+
// canonical path
Resolver::CanonicalPath canonical_path
- = Resolver::CanonicalPath::create_empty ();
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.values.to_canonical_path (mappings.get_nodeid ()).value ();
- }
- else
- {
- canonical_path = ctx->get_mappings ()
- .lookup_canonical_path (mappings.get_nodeid ())
- .value ();
- }
+ = nr_ctx.to_canonical_path (mappings.get_nodeid ());
ctx->push_const_context ();
tree const_expr
@@ -210,26 +186,11 @@ CompileItem::visit (HIR::Function &function)
}
}
- Resolver::CanonicalPath canonical_path
- = Resolver::CanonicalPath::create_empty ();
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- auto path = nr_ctx.values.to_canonical_path (
- function.get_mappings ().get_nodeid ());
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- canonical_path = path.value ();
- }
- else
- {
- auto path = ctx->get_mappings ().lookup_canonical_path (
- function.get_mappings ().get_nodeid ());
-
- canonical_path = *path;
- }
+ Resolver::CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ());
const std::string asm_name = ctx->mangle_item (fntype, canonical_path);
@@ -300,5 +261,65 @@ CompileItem::visit (HIR::Module &module)
CompileItem::compile (item.get (), ctx);
}
+void
+CompileItem::visit (HIR::TupleStruct &tuple_struct_decl)
+{
+ TyTy::BaseType *lookup = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ tuple_struct_decl.get_mappings ().get_hirid (), &lookup))
+ {
+ rust_error_at (tuple_struct_decl.get_locus (), "failed to resolve type");
+ return;
+ }
+
+ if (lookup->is_concrete ())
+ TyTyResolveCompile::compile (ctx, lookup);
+}
+
+void
+CompileItem::visit (HIR::Enum &enum_decl)
+{
+ TyTy::BaseType *lookup = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (enum_decl.get_mappings ().get_hirid (),
+ &lookup))
+ {
+ rust_error_at (enum_decl.get_locus (), "failed to resolve type");
+ return;
+ }
+
+ if (lookup->is_concrete ())
+ TyTyResolveCompile::compile (ctx, lookup);
+}
+
+void
+CompileItem::visit (HIR::Union &union_decl)
+{
+ TyTy::BaseType *lookup = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (union_decl.get_mappings ().get_hirid (),
+ &lookup))
+ {
+ rust_error_at (union_decl.get_locus (), "failed to resolve type");
+ return;
+ }
+
+ if (lookup->is_concrete ())
+ TyTyResolveCompile::compile (ctx, lookup);
+}
+
+void
+CompileItem::visit (HIR::StructStruct &struct_decl)
+{
+ TyTy::BaseType *lookup = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (struct_decl.get_mappings ().get_hirid (),
+ &lookup))
+ {
+ rust_error_at (struct_decl.get_locus (), "failed to resolve type");
+ return;
+ }
+
+ if (lookup->is_concrete ())
+ TyTyResolveCompile::compile (ctx, lookup);
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h
index d9d946d..56baaab 100644
--- a/gcc/rust/backend/rust-compile-item.h
+++ b/gcc/rust/backend/rust-compile-item.h
@@ -44,9 +44,12 @@ public:
void visit (HIR::ImplBlock &impl_block) override;
void visit (HIR::ExternBlock &extern_block) override;
void visit (HIR::Module &module) override;
+ void visit (HIR::TupleStruct &tuple_struct) override;
+ void visit (HIR::Enum &enum_decl) override;
+ void visit (HIR::Union &union_decl) override;
+ void visit (HIR::StructStruct &struct_decl) override;
// Empty visit for unused Stmt HIR nodes.
- void visit (HIR::TupleStruct &) override {}
void visit (HIR::EnumItem &) override {}
void visit (HIR::EnumItemTuple &) override {}
void visit (HIR::EnumItemStruct &) override {}
@@ -57,9 +60,6 @@ public:
void visit (HIR::ExternCrate &) override {}
void visit (HIR::UseDeclaration &) override {}
void visit (HIR::TypeAlias &) override {}
- void visit (HIR::StructStruct &) override {}
- void visit (HIR::Enum &) override {}
- void visit (HIR::Union &) override {}
void visit (HIR::Trait &) override {}
void visit (HIR::EmptyStmt &) override {}
void visit (HIR::LetStmt &) override {}
diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index e83717b..fe65921 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -22,6 +22,11 @@
#include "rust-constexpr.h"
#include "rust-compile-type.h"
#include "print-tree.h"
+#include "rust-diagnostics.h"
+#include "rust-hir-pattern-abstract.h"
+#include "rust-hir-pattern.h"
+#include "rust-system.h"
+#include "rust-tyty.h"
namespace Rust {
namespace Compile {
@@ -107,7 +112,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound,
tree result = NULL_TREE;
switch (bound.get_bound_type ())
{
- case HIR::RangePatternBound::RangePatternBoundType::LITERAL: {
+ case HIR::RangePatternBound::RangePatternBoundType::LITERAL:
+ {
auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound);
HIR::LiteralExpr litexpr (mappings, ref.get_literal (), locus,
@@ -117,7 +123,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound,
}
break;
- case HIR::RangePatternBound::RangePatternBoundType::PATH: {
+ case HIR::RangePatternBound::RangePatternBoundType::PATH:
+ {
auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound);
result = ResolvePathRef::Compile (ref.get_path (), ctx);
@@ -127,7 +134,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound,
}
break;
- case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ case HIR::RangePatternBound::RangePatternBoundType::QUALPATH:
+ {
auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound);
result = ResolvePathRef::Compile (ref.get_qualified_path (), ctx);
@@ -204,6 +212,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
rust_assert (adt->number_of_variants () > 0);
TyTy::VariantDef *variant = nullptr;
+ tree variant_accesser_expr = nullptr;
if (adt->is_enum ())
{
// lookup the variant
@@ -218,9 +227,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
// find expected discriminant
// // need to access qualifier the field, if we use QUAL_UNION_TYPE this
- // // would be DECL_QUALIFIER i think. For now this will just access the
- // // first record field and its respective qualifier because it will
- // // always be set because this is all a big special union
+ // // would be DECL_QUALIFIER i think.
HIR::Expr &discrim_expr = variant->get_discriminant ();
tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
@@ -229,6 +236,14 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
= Backend::struct_field_expression (match_scrutinee_expr, 0,
pattern.get_path ().get_locus ());
+ // access variant data
+ tree scrutinee_union_expr
+ = Backend::struct_field_expression (match_scrutinee_expr, 1,
+ pattern.get_path ().get_locus ());
+ variant_accesser_expr
+ = Backend::struct_field_expression (scrutinee_union_expr, variant_index,
+ pattern.get_path ().get_locus ());
+
check_expr
= Backend::comparison_expression (ComparisonOperator::EQUAL,
scrutinee_expr_qualifier_expr,
@@ -240,6 +255,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
else
{
variant = adt->get_variants ().at (0);
+ variant_accesser_expr = match_scrutinee_expr;
check_expr = boolean_true_node;
}
@@ -248,13 +264,15 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
{
switch (field->get_item_type ())
{
- case HIR::StructPatternField::ItemType::TUPLE_PAT: {
+ case HIR::StructPatternField::ItemType::TUPLE_PAT:
+ {
// TODO
rust_unreachable ();
}
break;
- case HIR::StructPatternField::ItemType::IDENT_PAT: {
+ case HIR::StructPatternField::ItemType::IDENT_PAT:
+ {
HIR::StructPatternFieldIdentPat &ident
= static_cast<HIR::StructPatternFieldIdentPat &> (*field.get ());
@@ -263,11 +281,8 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
nullptr, &offs);
rust_assert (ok);
- // we may be offsetting by + 1 here since the first field in the
- // record is always the discriminator
- offs += adt->is_enum ();
tree field_expr
- = Backend::struct_field_expression (match_scrutinee_expr, offs,
+ = Backend::struct_field_expression (variant_accesser_expr, offs,
ident.get_locus ());
tree check_expr_sub
@@ -279,7 +294,8 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
}
break;
- case HIR::StructPatternField::ItemType::IDENT: {
+ case HIR::StructPatternField::ItemType::IDENT:
+ {
// ident pattern always matches - do nothing
}
break;
@@ -338,44 +354,70 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern)
HIR::TupleStructItems &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case HIR::TupleStructItems::RANGED: {
+ case HIR::TupleStructItems::RANGED:
+ {
// TODO
rust_unreachable ();
}
break;
- case HIR::TupleStructItems::MULTIPLE: {
+ case HIR::TupleStructItems::MULTIPLE:
+ {
HIR::TupleStructItemsNoRange &items_no_range
= static_cast<HIR::TupleStructItemsNoRange &> (items);
rust_assert (items_no_range.get_patterns ().size ()
== variant->num_fields ());
- size_t tuple_field_index = 0;
- for (auto &pattern : items_no_range.get_patterns ())
+ if (adt->is_enum ())
{
- // find payload union field of scrutinee
- tree payload_ref
- = Backend::struct_field_expression (match_scrutinee_expr, 1,
- pattern->get_locus ());
+ size_t tuple_field_index = 0;
+ for (auto &pattern : items_no_range.get_patterns ())
+ {
+ // find payload union field of scrutinee
+ tree payload_ref
+ = Backend::struct_field_expression (match_scrutinee_expr, 1,
+ pattern->get_locus ());
- tree variant_ref
- = Backend::struct_field_expression (payload_ref, variant_index,
- pattern->get_locus ());
+ tree variant_ref
+ = Backend::struct_field_expression (payload_ref,
+ variant_index,
+ pattern->get_locus ());
- tree field_expr
- = Backend::struct_field_expression (variant_ref,
- tuple_field_index++,
- pattern->get_locus ());
+ tree field_expr
+ = Backend::struct_field_expression (variant_ref,
+ tuple_field_index++,
+ pattern->get_locus ());
- tree check_expr_sub
- = CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx);
- check_expr = Backend::arithmetic_or_logical_expression (
- ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
- check_expr_sub, pattern->get_locus ());
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pattern, field_expr,
+ ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pattern->get_locus ());
+ }
}
+ else
+ {
+ // For non-enum TupleStructPatterns
+ size_t tuple_field_index = 0;
+ for (auto &pattern : items_no_range.get_patterns ())
+ {
+ tree field_expr
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pattern->get_locus ());
+
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pattern, field_expr,
+ ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pattern->get_locus ());
+ }
+ }
+ break;
}
- break;
}
}
@@ -386,13 +428,57 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern)
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::RANGED: {
- // TODO
- gcc_unreachable ();
+ case HIR::TuplePatternItems::RANGED:
+ {
+ auto &items
+ = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
+ size_t tuple_field_index = 0;
+
+ // lookup the type to find out number of fields
+ TyTy::BaseType *ty = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (
+ pattern.get_mappings ().get_hirid (), &ty);
+ rust_assert (ok);
+ rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);
+
+ // compile check expr for lower patterns
+ for (auto &pat : items.get_lower_patterns ())
+ {
+ tree field_expr
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pat->get_locus ());
+
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pat->get_locus ());
+ }
+
+ // skip the fields that are not checked
+ tuple_field_index = static_cast<TyTy::TupleType &> (*ty).num_fields ()
+ - items.get_upper_patterns ().size ();
+
+ // compile check expr for upper patterns
+ for (auto &pat : items.get_upper_patterns ())
+ {
+ tree field_expr
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pat->get_locus ());
+
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pat->get_locus ());
+ }
}
break;
- case HIR::TuplePatternItems::MULTIPLE: {
+ case HIR::TuplePatternItems::MULTIPLE:
+ {
auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
pattern.get_items ());
size_t tuple_field_index = 0;
@@ -414,6 +500,99 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern)
}
}
+void
+CompilePatternCheckExpr::visit (HIR::IdentifierPattern &pattern)
+{
+ if (pattern.has_subpattern ())
+ {
+ check_expr = CompilePatternCheckExpr::Compile (pattern.get_subpattern (),
+ match_scrutinee_expr, ctx);
+ }
+ else
+ {
+ check_expr = boolean_true_node;
+ }
+}
+
+void
+CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern)
+{
+ check_expr = boolean_true_node;
+
+ // lookup the type
+ TyTy::BaseType *lookup = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
+ &lookup);
+ rust_assert (ok);
+
+ // pattern must either be ArrayType or SliceType, should be already confirmed
+ // by type checking
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::ARRAY
+ || lookup->get_kind () == TyTy::TypeKind::SLICE
+ || lookup->get_kind () == TyTy::REF);
+
+ size_t array_element_index = 0;
+ switch (lookup->get_kind ())
+ {
+ case TyTy::TypeKind::ARRAY:
+ for (auto &pattern_member : pattern.get_items ())
+ {
+ tree array_index_tree
+ = Backend::size_constant_expression (array_element_index++);
+ tree element_expr
+ = Backend::array_index_expression (match_scrutinee_expr,
+ array_index_tree,
+ pattern.get_locus ());
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pattern_member, element_expr,
+ ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pattern.get_locus ());
+ }
+ break;
+ case TyTy::TypeKind::SLICE:
+ rust_sorry_at (
+ pattern.get_locus (),
+ "SlicePattern matching against non-ref slices are not yet supported");
+ break;
+ case TyTy::TypeKind::REF:
+ {
+ rust_assert (RS_DST_FLAG_P (TREE_TYPE (match_scrutinee_expr)));
+ tree size_field
+ = Backend::struct_field_expression (match_scrutinee_expr, 1,
+ pattern.get_locus ());
+
+ // First compare the size
+ check_expr = Backend::comparison_expression (
+ ComparisonOperator::EQUAL, size_field,
+ build_int_cst (size_type_node, pattern.get_items ().size ()),
+ pattern.get_locus ());
+
+ // Then compare each element in the slice pattern
+ for (auto &pattern_member : pattern.get_items ())
+ {
+ tree slice_index_tree
+ = Backend::size_constant_expression (array_element_index++);
+ tree element_expr
+ = Backend::slice_index_expression (match_scrutinee_expr,
+ slice_index_tree,
+ pattern.get_locus ());
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pattern_member, element_expr,
+ ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pattern.get_locus ());
+ }
+ }
+ break;
+ default:
+ rust_unreachable ();
+ }
+}
+
// setup the bindings
void
@@ -449,13 +628,15 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
HIR::TupleStructItems &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case HIR::TupleStructItems::RANGED: {
+ case HIR::TupleStructItems::RANGED:
+ {
// TODO
rust_unreachable ();
}
break;
- case HIR::TupleStructItems::MULTIPLE: {
+ case HIR::TupleStructItems::MULTIPLE:
+ {
HIR::TupleStructItemsNoRange &items_no_range
= static_cast<HIR::TupleStructItemsNoRange &> (items);
@@ -504,6 +685,71 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
}
}
+tree
+CompilePatternBindings::make_struct_access (TyTy::ADTType *adt,
+ TyTy::VariantDef *variant,
+ const Identifier &ident,
+ int variant_index)
+{
+ size_t offs = 0;
+ auto ok = variant->lookup_field (ident.as_string (), nullptr, &offs);
+ rust_assert (ok);
+
+ if (adt->is_enum ())
+ {
+ tree payload_accessor_union
+ = Backend::struct_field_expression (match_scrutinee_expr, 1,
+ ident.get_locus ());
+
+ tree variant_accessor
+ = Backend::struct_field_expression (payload_accessor_union,
+ variant_index, ident.get_locus ());
+
+ return Backend::struct_field_expression (variant_accessor, offs,
+ ident.get_locus ());
+ }
+ else
+ {
+ tree variant_accessor = match_scrutinee_expr;
+
+ return Backend::struct_field_expression (variant_accessor, offs,
+ ident.get_locus ());
+ }
+}
+
+void
+CompilePatternBindings::handle_struct_pattern_ident (
+ HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant,
+ int variant_index)
+{
+ HIR::StructPatternFieldIdent &ident
+ = static_cast<HIR::StructPatternFieldIdent &> (pat);
+
+ auto identifier = ident.get_identifier ();
+ tree binding = make_struct_access (adt, variant, identifier, variant_index);
+
+ ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (), binding);
+}
+
+void
+CompilePatternBindings::handle_struct_pattern_ident_pat (
+ HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant,
+ int variant_index)
+{
+ auto &pattern = static_cast<HIR::StructPatternFieldIdentPat &> (pat);
+
+ tree binding = make_struct_access (adt, variant, pattern.get_identifier (),
+ variant_index);
+ CompilePatternBindings::Compile (pattern.get_pattern (), binding, ctx);
+}
+
+void
+CompilePatternBindings::handle_struct_pattern_tuple_pat (
+ HIR::StructPatternField &pat)
+{
+ rust_unreachable ();
+}
+
void
CompilePatternBindings::visit (HIR::StructPattern &pattern)
{
@@ -539,54 +785,14 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
{
switch (field->get_item_type ())
{
- case HIR::StructPatternField::ItemType::TUPLE_PAT: {
- // TODO
- rust_unreachable ();
- }
+ case HIR::StructPatternField::ItemType::TUPLE_PAT:
+ handle_struct_pattern_tuple_pat (*field);
break;
-
- case HIR::StructPatternField::ItemType::IDENT_PAT: {
- // TODO
- rust_unreachable ();
- }
+ case HIR::StructPatternField::ItemType::IDENT_PAT:
+ handle_struct_pattern_ident_pat (*field, adt, variant, variant_index);
break;
-
- case HIR::StructPatternField::ItemType::IDENT: {
- HIR::StructPatternFieldIdent &ident
- = static_cast<HIR::StructPatternFieldIdent &> (*field.get ());
-
- size_t offs = 0;
- ok = variant->lookup_field (ident.get_identifier ().as_string (),
- nullptr, &offs);
- rust_assert (ok);
-
- tree binding = error_mark_node;
- if (adt->is_enum ())
- {
- tree payload_accessor_union
- = Backend::struct_field_expression (match_scrutinee_expr, 1,
- ident.get_locus ());
-
- tree variant_accessor
- = Backend::struct_field_expression (payload_accessor_union,
- variant_index,
- ident.get_locus ());
-
- binding
- = Backend::struct_field_expression (variant_accessor, offs,
- ident.get_locus ());
- }
- else
- {
- tree variant_accessor = match_scrutinee_expr;
- binding
- = Backend::struct_field_expression (variant_accessor, offs,
- ident.get_locus ());
- }
-
- ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (),
- binding);
- }
+ case HIR::StructPatternField::ItemType::IDENT:
+ handle_struct_pattern_ident (*field, adt, variant, variant_index);
break;
}
}
@@ -605,6 +811,12 @@ CompilePatternBindings::visit (HIR::ReferencePattern &pattern)
void
CompilePatternBindings::visit (HIR::IdentifierPattern &pattern)
{
+ if (pattern.has_subpattern ())
+ {
+ CompilePatternBindings::Compile (pattern.get_subpattern (),
+ match_scrutinee_expr, ctx);
+ }
+
if (!pattern.get_is_ref ())
{
ctx->insert_pattern_binding (pattern.get_mappings ().get_hirid (),
@@ -631,7 +843,8 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern)
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::ItemType::RANGED: {
+ case HIR::TuplePatternItems::ItemType::RANGED:
+ {
size_t tuple_idx = 0;
auto &items
= static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
@@ -674,7 +887,8 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern)
return;
}
- case HIR::TuplePatternItems::ItemType::MULTIPLE: {
+ case HIR::TuplePatternItems::ItemType::MULTIPLE:
+ {
size_t tuple_idx = 0;
auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
pattern.get_items ());
@@ -695,12 +909,67 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern)
return;
}
- default: {
+ default:
+ {
rust_unreachable ();
}
}
}
+void
+CompilePatternBindings::visit (HIR::SlicePattern &pattern)
+{
+ // lookup the type
+ TyTy::BaseType *lookup = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
+ &lookup);
+ rust_assert (ok);
+
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::ARRAY
+ || lookup->get_kind () == TyTy::TypeKind::SLICE
+ || lookup->get_kind () == TyTy::REF);
+
+ size_t array_element_index = 0;
+ switch (lookup->get_kind ())
+ {
+ case TyTy::TypeKind::ARRAY:
+ for (auto &pattern_member : pattern.get_items ())
+ {
+ tree array_index_tree
+ = Backend::size_constant_expression (array_element_index++);
+ tree element_expr
+ = Backend::array_index_expression (match_scrutinee_expr,
+ array_index_tree,
+ pattern.get_locus ());
+ CompilePatternBindings::Compile (*pattern_member, element_expr, ctx);
+ }
+ break;
+ case TyTy::TypeKind::SLICE:
+ rust_sorry_at (
+ pattern.get_locus (),
+ "SlicePattern matching against non-ref slices are not yet supported");
+ break;
+ case TyTy::TypeKind::REF:
+ {
+ for (auto &pattern_member : pattern.get_items ())
+ {
+ tree slice_index_tree
+ = Backend::size_constant_expression (array_element_index++);
+ tree element_expr
+ = Backend::slice_index_expression (match_scrutinee_expr,
+ slice_index_tree,
+ pattern.get_locus ());
+ CompilePatternBindings::Compile (*pattern_member, element_expr,
+ ctx);
+ }
+ break;
+ }
+ default:
+ rust_unreachable ();
+ }
+}
+
//
void
@@ -755,7 +1024,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern)
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::ItemType::RANGED: {
+ case HIR::TuplePatternItems::ItemType::RANGED:
+ {
size_t tuple_idx = 0;
auto &items
= static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
@@ -799,7 +1069,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern)
return;
}
- case HIR::TuplePatternItems::ItemType::MULTIPLE: {
+ case HIR::TuplePatternItems::ItemType::MULTIPLE:
+ {
size_t tuple_idx = 0;
auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
pattern.get_items ());
@@ -821,7 +1092,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern)
return;
}
- default: {
+ default:
+ {
rust_unreachable ();
}
}
diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h
index c7a62fc..233799e 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -17,7 +17,9 @@
// <http://www.gnu.org/licenses/>.
#include "rust-compile-base.h"
+#include "rust-hir-pattern.h"
#include "rust-hir-visitor.h"
+#include "rust-tyty.h"
namespace Rust {
namespace Compile {
@@ -43,12 +45,10 @@ public:
void visit (HIR::StructPattern &) override;
void visit (HIR::TupleStructPattern &) override;
void visit (HIR::TuplePattern &) override;
+ void visit (HIR::IdentifierPattern &) override;
+ void visit (HIR::SlicePattern &) override;
// Always succeeds
- void visit (HIR::IdentifierPattern &) override
- {
- check_expr = boolean_true_node;
- }
void visit (HIR::WildcardPattern &) override
{
check_expr = boolean_true_node;
@@ -56,7 +56,6 @@ public:
// Empty visit for unused Pattern HIR nodes.
void visit (HIR::QualifiedPathInExpression &) override {}
- void visit (HIR::SlicePattern &) override {}
CompilePatternCheckExpr (Context *ctx, tree match_scrutinee_expr)
: HIRCompileBase (ctx), match_scrutinee_expr (match_scrutinee_expr),
@@ -78,11 +77,25 @@ public:
pattern.accept_vis (compiler);
}
+ tree make_struct_access (TyTy::ADTType *adt, TyTy::VariantDef *variant,
+ const Identifier &ident, int variant_index);
+
+ void handle_struct_pattern_ident (HIR::StructPatternField &pat,
+ TyTy::ADTType *adt,
+ TyTy::VariantDef *variant,
+ int variant_index);
+ void handle_struct_pattern_ident_pat (HIR::StructPatternField &pat,
+ TyTy::ADTType *adt,
+ TyTy::VariantDef *variant,
+ int variant_index);
+ void handle_struct_pattern_tuple_pat (HIR::StructPatternField &pat);
+
void visit (HIR::StructPattern &pattern) override;
void visit (HIR::TupleStructPattern &pattern) override;
void visit (HIR::ReferencePattern &pattern) override;
void visit (HIR::IdentifierPattern &) override;
void visit (HIR::TuplePattern &pattern) override;
+ void visit (HIR::SlicePattern &) override;
// Empty visit for unused Pattern HIR nodes.
void visit (HIR::AltPattern &) override {}
@@ -90,7 +103,6 @@ public:
void visit (HIR::PathInExpression &) override {}
void visit (HIR::QualifiedPathInExpression &) override {}
void visit (HIR::RangePattern &) override {}
- void visit (HIR::SlicePattern &) override {}
void visit (HIR::WildcardPattern &) override {}
protected:
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index 81d2dbb..f3b9dc2 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -187,13 +187,18 @@ ResolvePathRef::resolve_with_node_id (
}
// Handle unit struct
+ tree resolved_item = error_mark_node;
if (lookup->get_kind () == TyTy::TypeKind::ADT)
- return attempt_constructor_expression_lookup (lookup, ctx, mappings,
- expr_locus);
+ resolved_item
+ = attempt_constructor_expression_lookup (lookup, ctx, mappings,
+ expr_locus);
+
+ if (!error_operand_p (resolved_item))
+ return resolved_item;
// let the query system figure it out
- tree resolved_item = query_compile (ref, lookup, final_segment, mappings,
- expr_locus, is_qualified_path);
+ resolved_item = query_compile (ref, lookup, final_segment, mappings,
+ expr_locus, is_qualified_path);
if (resolved_item != error_mark_node)
{
TREE_USED (resolved_item) = 1;
@@ -209,36 +214,24 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
{
TyTy::BaseType *lookup = nullptr;
bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup);
- rust_assert (ok);
+ if (!ok)
+ return error_mark_node;
// need to look up the reference for this identifier
// this can fail because it might be a Constructor for something
// in that case the caller should attempt ResolvePathType::Compile
- NodeId ref_node_id = UNKNOWN_NODEID;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- auto resolved = nr_ctx.lookup (mappings.get_nodeid ());
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (!resolved)
- return attempt_constructor_expression_lookup (lookup, ctx, mappings,
- expr_locus);
+ auto resolved = nr_ctx.lookup (mappings.get_nodeid ());
- ref_node_id = *resolved;
- }
- else
- {
- if (!ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (),
- &ref_node_id))
- return attempt_constructor_expression_lookup (lookup, ctx, mappings,
- expr_locus);
- }
+ if (!resolved)
+ return attempt_constructor_expression_lookup (lookup, ctx, mappings,
+ expr_locus);
return resolve_with_node_id (final_segment, mappings, expr_locus,
- is_qualified_path, ref_node_id);
+ is_qualified_path, *resolved);
}
tree
@@ -336,11 +329,18 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
rust_assert (lookup->is<TyTy::FnType> ());
auto fn = lookup->as<TyTy::FnType> ();
rust_assert (fn->get_num_type_params () > 0);
- auto &self = fn->get_substs ().at (0);
- auto receiver = self.get_param_ty ();
+ TyTy::SubstitutionParamMapping &self = fn->get_substs ().at (0);
+ TyTy::BaseGeneric *receiver = self.get_param_ty ();
+ TyTy::BaseType *r = receiver;
+ if (!receiver->can_resolve ())
+ {
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (receiver->get_ref (), &r);
+ rust_assert (ok);
+ }
+
auto candidates
- = Resolver::PathProbeImplTrait::Probe (receiver, final_segment,
- trait_ref);
+ = Resolver::PathProbeImplTrait::Probe (r, final_segment, trait_ref);
if (candidates.size () == 0)
{
// this means we are defaulting back to the trait_item if
diff --git a/gcc/rust/backend/rust-compile-stmt.cc b/gcc/rust/backend/rust-compile-stmt.cc
index a4b5a98..b520baf 100644
--- a/gcc/rust/backend/rust-compile-stmt.cc
+++ b/gcc/rust/backend/rust-compile-stmt.cc
@@ -58,6 +58,9 @@ CompileStmt::visit (HIR::LetStmt &stmt)
return;
}
+ rust_debug_loc (stmt.get_locus (), " -> LetStmt %s",
+ ty->as_string ().c_str ());
+
// setup var decl nodes
fncontext fnctx = ctx->peek_fn ();
tree fndecl = fnctx.fndecl;
diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc
index 83e5756..0622954 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -17,11 +17,11 @@
// <http://www.gnu.org/licenses/>.
#include "rust-compile-type.h"
-#include "rust-compile-expr.h"
#include "rust-constexpr.h"
-#include "rust-gcc.h"
+#include "rust-compile-base.h"
#include "tree.h"
+#include "fold-const.h"
#include "stor-layout.h"
namespace Rust {
@@ -121,6 +121,13 @@ TyTyResolveCompile::visit (const TyTy::InferType &type)
if (orig == lookup)
{
+ TyTy::BaseType *def = nullptr;
+ if (type.default_type (&def))
+ {
+ translated = TyTyResolveCompile::compile (ctx, def);
+ return;
+ }
+
translated = error_mark_node;
return;
}
@@ -135,6 +142,12 @@ TyTyResolveCompile::visit (const TyTy::ParamType &)
}
void
+TyTyResolveCompile::visit (const TyTy::ConstType &)
+{
+ translated = error_mark_node;
+}
+
+void
TyTyResolveCompile::visit (const TyTy::ProjectionType &type)
{
translated = error_mark_node;
@@ -189,7 +202,7 @@ TyTyResolveCompile::visit (const TyTy::ClosureType &type)
void
TyTyResolveCompile::visit (const TyTy::FnType &type)
{
- Backend::typed_identifier receiver;
+ Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
std::vector<Backend::typed_identifier> parameters;
std::vector<Backend::typed_identifier> results;
@@ -454,7 +467,7 @@ TyTyResolveCompile::visit (const TyTy::TupleType &type)
}
tree struct_type_record = Backend::struct_type (fields);
- translated = Backend::named_type (type.as_string (), struct_type_record,
+ translated = Backend::named_type (type.get_name (), struct_type_record,
type.get_ident ().locus);
}
@@ -463,26 +476,15 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type)
{
tree element_type
= TyTyResolveCompile::compile (ctx, type.get_element_type ());
+ TyTy::ConstType *const_capacity = type.get_capacity ();
+ tree folded_capacity_expr = const_capacity->get_value ();
- ctx->push_const_context ();
-
- HIR::Expr &hir_capacity_expr = type.get_capacity_expr ();
- TyTy::BaseType *capacity_expr_ty = nullptr;
- bool ok = ctx->get_tyctx ()->lookup_type (
- hir_capacity_expr.get_mappings ().get_hirid (), &capacity_expr_ty);
- rust_assert (ok);
- tree capacity_expr = HIRCompileBase::compile_constant_expr (
- ctx, hir_capacity_expr.get_mappings ().get_hirid (), capacity_expr_ty,
- capacity_expr_ty, Resolver::CanonicalPath::create_empty (),
- hir_capacity_expr, type.get_locus (), hir_capacity_expr.get_locus ());
-
- ctx->pop_const_context ();
-
- tree folded_capacity_expr = fold_expr (capacity_expr);
+ // build_index_type takes the maximum index, which is one less than
+ // the length.
+ tree index_type_tree = build_index_type (
+ fold_build2 (MINUS_EXPR, sizetype, folded_capacity_expr, size_one_node));
- translated = Backend::array_type (element_type, folded_capacity_expr);
- if (translated != error_mark_node)
- translated = ctx->insert_compiled_type (translated);
+ translated = build_array_type (element_type, index_type_tree, false);
}
void
@@ -755,7 +757,9 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type)
void
TyTyResolveCompile::visit (const TyTy::OpaqueType &type)
{
- translated = error_mark_node;
+ rust_assert (type.can_resolve ());
+ auto underlying = type.resolve ();
+ translated = TyTyResolveCompile::compile (ctx, underlying, trait_object_mode);
}
tree
diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h
index 7ebc4a6..0675343 100644
--- a/gcc/rust/backend/rust-compile-type.h
+++ b/gcc/rust/backend/rust-compile-type.h
@@ -50,6 +50,7 @@ public:
void visit (const TyTy::ReferenceType &) override;
void visit (const TyTy::PointerType &) override;
void visit (const TyTy::ParamType &) override;
+ void visit (const TyTy::ConstType &) override;
void visit (const TyTy::StrType &) override;
void visit (const TyTy::NeverType &) override;
void visit (const TyTy::PlaceholderType &) override;
diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h
index 4c46a7b..5c6d145 100644
--- a/gcc/rust/backend/rust-compile-var-decl.h
+++ b/gcc/rust/backend/rust-compile-var-decl.h
@@ -70,7 +70,8 @@ public:
{
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::ItemType::MULTIPLE: {
+ case HIR::TuplePatternItems::ItemType::MULTIPLE:
+ {
rust_assert (TREE_CODE (translated_type) == RECORD_TYPE);
auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
pattern.get_items ());
diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc
index dc2d6b1..d524d09 100644
--- a/gcc/rust/backend/rust-constexpr.cc
+++ b/gcc/rust/backend/rust-constexpr.cc
@@ -68,32 +68,24 @@ literal_type_p (tree t)
return false;
}
-static bool
-verify_constant (tree, bool, bool *, bool *);
-
-static HOST_WIDE_INT
-find_array_ctor_elt (tree ary, tree dindex, bool insert = false);
-static int
-array_index_cmp (tree key, tree index);
-static bool
-potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
- tsubst_flags_t flags, tree *jump_target);
-bool
-potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
- tsubst_flags_t flags);
-tree
-unshare_constructor (tree t MEM_STAT_DECL);
-void
-maybe_save_constexpr_fundef (tree fun);
-
-static bool
-returns (tree *jump_target);
-static bool
-breaks (tree *jump_target);
-static bool
-continues (tree *jump_target);
-static bool
-switches (tree *jump_target);
+static bool verify_constant (tree, bool, bool *, bool *);
+
+static HOST_WIDE_INT find_array_ctor_elt (tree ary, tree dindex,
+ bool insert = false);
+static int array_index_cmp (tree key, tree index);
+static bool potential_constant_expression_1 (tree t, bool want_rval,
+ bool strict, bool now,
+ tsubst_flags_t flags,
+ tree *jump_target);
+bool potential_constant_expression_1 (tree t, bool want_rval, bool strict,
+ bool now, tsubst_flags_t flags);
+tree unshare_constructor (tree t MEM_STAT_DECL);
+void maybe_save_constexpr_fundef (tree fun);
+
+static bool returns (tree *jump_target);
+static bool breaks (tree *jump_target);
+static bool continues (tree *jump_target);
+static bool switches (tree *jump_target);
struct constexpr_global_ctx
{
@@ -463,60 +455,52 @@ save_fundef_copy (tree fun, tree copy)
*slot = copy;
}
-static tree
-constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p,
- bool unshare_p);
-tree
-decl_constant_value (tree decl, bool unshare_p);
+static tree constant_value_1 (tree decl, bool strict_p,
+ bool return_aggregate_cst_ok_p, bool unshare_p);
+tree decl_constant_value (tree decl, bool unshare_p);
-static void
-non_const_var_error (location_t loc, tree r);
+static void non_const_var_error (location_t loc, tree r);
-static tree
-eval_constant_expression (const constexpr_ctx *ctx, tree, bool, bool *, bool *,
- tree * = NULL);
+static tree eval_constant_expression (const constexpr_ctx *ctx, tree, bool,
+ bool *, bool *, tree * = NULL);
-static tree
-constexpr_fn_retval (const constexpr_ctx *ctx, tree r);
+static tree constexpr_fn_retval (const constexpr_ctx *ctx, tree r);
-static tree
-eval_store_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *);
+static tree eval_store_expression (const constexpr_ctx *ctx, tree r, bool,
+ bool *, bool *);
-static tree
-eval_call_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *);
+static tree eval_call_expression (const constexpr_ctx *ctx, tree r, bool,
+ bool *, bool *);
-static tree
-eval_binary_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *);
+static tree eval_binary_expression (const constexpr_ctx *ctx, tree r, bool,
+ bool *, bool *);
-static tree
-get_function_named_in_call (tree t);
+static tree get_function_named_in_call (tree t);
-static tree
-eval_statement_list (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
- bool *overflow_p, tree *jump_target);
-static tree
-extract_string_elt (tree string, unsigned chars_per_elt, unsigned index);
+static tree eval_statement_list (const constexpr_ctx *ctx, tree t,
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target);
+static tree extract_string_elt (tree string, unsigned chars_per_elt,
+ unsigned index);
-static tree
-eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p,
- tree *jump_target);
+static tree eval_conditional_expression (const constexpr_ctx *ctx, tree t,
+ bool lval, bool *non_constant_p,
+ bool *overflow_p, tree *jump_target);
-static tree
-eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p);
+static tree eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval,
+ bool *non_constant_p, bool *overflow_p);
-static tree
-eval_loop_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
- bool *overflow_p, tree *jump_target);
+static tree eval_loop_expr (const constexpr_ctx *ctx, tree t,
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target);
-static tree
-eval_switch_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
- bool *overflow_p, tree *jump_target);
+static tree eval_switch_expr (const constexpr_ctx *ctx, tree t,
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target);
-static tree
-eval_unary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/,
- bool *non_constant_p, bool *overflow_p);
+static tree eval_unary_expression (const constexpr_ctx *ctx, tree t,
+ bool /*lval*/, bool *non_constant_p,
+ bool *overflow_p);
/* Variables and functions to manage constexpr call expansion context.
These do not need to be marked for PCH or GC. */
@@ -1235,7 +1219,8 @@ get_or_insert_ctor_field (tree ctor, tree index, int pos_hint = -1)
/* We fell off the end of the CONSTRUCTOR, so insert a new
entry at the end. */
- insert : {
+ insert:
+ {
constructor_elt ce = {index, NULL_TREE};
vec_safe_insert (CONSTRUCTOR_ELTS (ctor), idx, ce);
@@ -1568,10 +1553,9 @@ free_constructor (tree t)
}
}
-static tree
-eval_and_check_array_index (const constexpr_ctx *ctx, tree t,
- bool allow_one_past, bool *non_constant_p,
- bool *overflow_p);
+static tree eval_and_check_array_index (const constexpr_ctx *ctx, tree t,
+ bool allow_one_past,
+ bool *non_constant_p, bool *overflow_p);
// forked from gcc/cp/constexpr.cc cxx_eval_array_reference
@@ -1901,6 +1885,9 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
location_t loc = EXPR_LOCATION (t);
+ if (t == NULL_TREE)
+ return NULL_TREE;
+
if (CONSTANT_CLASS_P (t))
{
if (TREE_OVERFLOW (t))
@@ -1936,8 +1923,9 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
return eval_constant_expression (ctx, r, lval, non_constant_p,
overflow_p);
}
- /* fall through */
- case CONST_DECL: {
+ /* fall through */
+ case CONST_DECL:
+ {
/* We used to not check lval for CONST_DECL, but darwin.cc uses
CONST_DECL for aggregate constants. */
if (lval)
@@ -2045,7 +2033,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
overflow_p);
break;
- case TARGET_EXPR: {
+ case TARGET_EXPR:
+ {
tree type = TREE_TYPE (t);
if (!literal_type_p (type))
@@ -2129,7 +2118,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
}
break;
- case DECL_EXPR: {
+ case DECL_EXPR:
+ {
r = DECL_EXPR_DECL (t);
if (AGGREGATE_TYPE_P (TREE_TYPE (r)) || VECTOR_TYPE_P (TREE_TYPE (r)))
@@ -2201,7 +2191,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
return eval_constant_expression (ctx, OBJ_TYPE_REF_EXPR (t), lval,
non_constant_p, overflow_p);
- case EXIT_EXPR: {
+ case EXIT_EXPR:
+ {
tree cond = TREE_OPERAND (t, 0);
cond = eval_constant_expression (ctx, cond, /*lval*/ false,
non_constant_p, overflow_p);
@@ -2243,7 +2234,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
}
break;
- case ADDR_EXPR: {
+ case ADDR_EXPR:
+ {
tree oldop = TREE_OPERAND (t, 0);
tree op = eval_constant_expression (ctx, oldop,
/*lval*/ true, non_constant_p,
@@ -2261,7 +2253,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
break;
}
- case COMPOUND_EXPR: {
+ case COMPOUND_EXPR:
+ {
/* check_return_expr sometimes wraps a TARGET_EXPR in a
COMPOUND_EXPR; don't get confused. Also handle EMPTY_CLASS_EXPR
introduced by build_call_a. */
@@ -2401,7 +2394,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
non_constant_p, overflow_p, jump_target);
break;
- case CLEANUP_POINT_EXPR: {
+ case CLEANUP_POINT_EXPR:
+ {
auto_vec<tree, 2> cleanups;
vec<tree> *prev_cleanups = ctx->global->cleanups;
ctx->global->cleanups = &cleanups;
@@ -2441,7 +2435,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
/* FALLTHROUGH. */
case NOP_EXPR:
case CONVERT_EXPR:
- case VIEW_CONVERT_EXPR: {
+ case VIEW_CONVERT_EXPR:
+ {
tree oldop = TREE_OPERAND (t, 0);
tree op = eval_constant_expression (ctx, oldop, lval, non_constant_p,
@@ -2688,7 +2683,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval,
{
case BIT_FIELD_REF:
case COMPONENT_REF:
- case ARRAY_REF: {
+ case ARRAY_REF:
+ {
tree ob = TREE_OPERAND (probe, 0);
tree elt = TREE_OPERAND (probe, 1);
if (TREE_CODE (elt) == FIELD_DECL /*&& DECL_MUTABLE_P (elt)*/)
@@ -3940,7 +3936,8 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body)
{
switch (TREE_CODE (body))
{
- case STATEMENT_LIST: {
+ case STATEMENT_LIST:
+ {
tree expr = NULL_TREE;
for (tree stmt : tsi_range (body))
{
@@ -3958,13 +3955,15 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body)
return expr;
}
- case RETURN_EXPR: {
+ case RETURN_EXPR:
+ {
bool non_constant_p = false;
bool overflow_p = false;
return eval_constant_expression (ctx, body, false, &non_constant_p,
&overflow_p);
}
- case DECL_EXPR: {
+ case DECL_EXPR:
+ {
tree decl = DECL_EXPR_DECL (body);
if (TREE_CODE (decl) == USING_DECL
/* Accept __func__, __FUNCTION__, and __PRETTY_FUNCTION__. */
@@ -3976,7 +3975,8 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body)
case CLEANUP_POINT_EXPR:
return constexpr_fn_retval (ctx, TREE_OPERAND (body, 0));
- case BIND_EXPR: {
+ case BIND_EXPR:
+ {
tree b = BIND_EXPR_BODY (body);
return constexpr_fn_retval (ctx, b);
}
@@ -4136,7 +4136,8 @@ array_index_cmp (tree key, tree index)
{
case INTEGER_CST:
return tree_int_cst_compare (key, index);
- case RANGE_EXPR: {
+ case RANGE_EXPR:
+ {
tree lo = TREE_OPERAND (index, 0);
tree hi = TREE_OPERAND (index, 1);
if (tree_int_cst_lt (key, lo))
@@ -5943,7 +5944,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case BIT_FIELD_REF:
return RECUR (TREE_OPERAND (t, 0), want_rval);
- case INDIRECT_REF: {
+ case INDIRECT_REF:
+ {
tree x = TREE_OPERAND (t, 0);
STRIP_NOPS (x);
return RECUR (x, rval);
@@ -6214,7 +6216,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case INIT_EXPR:
return RECUR (TREE_OPERAND (t, 1), rval);
- case CONSTRUCTOR: {
+ case CONSTRUCTOR:
+ {
vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t);
constructor_elt *ce;
for (i = 0; vec_safe_iterate (v, i, &ce); ++i)
@@ -6223,7 +6226,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return true;
}
- case TREE_LIST: {
+ case TREE_LIST:
+ {
gcc_assert (TREE_PURPOSE (t) == NULL_TREE || DECL_P (TREE_PURPOSE (t)));
if (!RECUR (TREE_VALUE (t), want_rval))
return false;
@@ -6238,7 +6242,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case ROUND_DIV_EXPR:
case TRUNC_MOD_EXPR:
case CEIL_MOD_EXPR:
- case ROUND_MOD_EXPR: {
+ case ROUND_MOD_EXPR:
+ {
tree denom = TREE_OPERAND (t, 1);
if (!RECUR (denom, rval))
return false;
@@ -6258,7 +6263,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
}
}
- case COMPOUND_EXPR: {
+ case COMPOUND_EXPR:
+ {
/* check_return_expr sometimes wraps a TARGET_EXPR in a
COMPOUND_EXPR; don't get confused. */
tree op0 = TREE_OPERAND (t, 0);
@@ -6280,7 +6286,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case TRUTH_OR_EXPR:
case TRUTH_ORIF_EXPR:
tmp = boolean_false_node;
- truth : {
+ truth:
+ {
tree op0 = TREE_OPERAND (t, 0);
tree op1 = TREE_OPERAND (t, 1);
if (!RECUR (op0, rval))
diff --git a/gcc/rust/backend/rust-constexpr.h b/gcc/rust/backend/rust-constexpr.h
index 77a0797..27f0a2e 100644
--- a/gcc/rust/backend/rust-constexpr.h
+++ b/gcc/rust/backend/rust-constexpr.h
@@ -24,8 +24,7 @@ namespace Rust {
namespace Compile {
extern tree fold_expr (tree);
-extern void
-maybe_save_constexpr_fundef (tree fun);
+extern void maybe_save_constexpr_fundef (tree fun);
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-mangle-v0.cc b/gcc/rust/backend/rust-mangle-v0.cc
index d0df4ab..f6b1a4c 100644
--- a/gcc/rust/backend/rust-mangle-v0.cc
+++ b/gcc/rust/backend/rust-mangle-v0.cc
@@ -62,9 +62,9 @@ struct V0Path
}
};
-static std::string
-v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
- const Resolver::CanonicalPath &path);
+static std::string v0_path (Rust::Compile::Context *ctx,
+ const TyTy::BaseType *ty,
+ const Resolver::CanonicalPath &path);
static std::string
v0_tuple_prefix (const TyTy::BaseType *ty)
@@ -148,7 +148,8 @@ v0_complex_type_prefix (Context *ctx, const TyTy::BaseType *ty)
// TODO: generics
switch (ty->get_kind ())
{
- case TyTy::TypeKind::ADT: {
+ case TyTy::TypeKind::ADT:
+ {
const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (ty);
return v0_path (ctx, ty, adt->get_ident ().path);
}
@@ -387,7 +388,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
{
switch (impl_item->first->get_impl_item_type ())
{
- case HIR::ImplItem::FUNCTION: {
+ case HIR::ImplItem::FUNCTION:
+ {
HIR::Function *fn
= static_cast<HIR::Function *> (impl_item->first);
v0path
@@ -408,7 +410,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
{
switch (trait_item.value ()->get_item_kind ())
{
- case HIR::TraitItem::FUNC: {
+ case HIR::TraitItem::FUNC:
+ {
auto fn = static_cast<HIR::TraitItemFunc *> (*trait_item);
rust_unreachable ();
v0path = v0_function_path (v0path, ctx, ty,
@@ -428,7 +431,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
else if (auto item = mappings.lookup_hir_item (hir_id))
switch (item.value ()->get_item_kind ())
{
- case HIR::Item::ItemKind::Function: {
+ case HIR::Item::ItemKind::Function:
+ {
HIR::Function *fn = static_cast<HIR::Function *> (*item);
v0path
= v0_function_path (v0path, ctx, ty, fn->get_generic_params (),
diff --git a/gcc/rust/backend/rust-mangle.h b/gcc/rust/backend/rust-mangle.h
index 2a84b6b..418f2bd 100644
--- a/gcc/rust/backend/rust-mangle.h
+++ b/gcc/rust/backend/rust-mangle.h
@@ -49,13 +49,12 @@ private:
static enum MangleVersion version;
};
-std::string
-legacy_mangle_item (const TyTy::BaseType *ty,
- const Resolver::CanonicalPath &path);
+std::string legacy_mangle_item (const TyTy::BaseType *ty,
+ const Resolver::CanonicalPath &path);
-std::string
-v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
- const Resolver::CanonicalPath &path);
+std::string v0_mangle_item (Rust::Compile::Context *ctx,
+ const TyTy::BaseType *ty,
+ const Resolver::CanonicalPath &path);
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc
index 2302ffb..b86c3c8 100644
--- a/gcc/rust/backend/rust-tree.cc
+++ b/gcc/rust/backend/rust-tree.cc
@@ -268,7 +268,8 @@ convert_to_void (tree expr, impl_conv_void implicit)
return expr;
switch (TREE_CODE (expr))
{
- case COND_EXPR: {
+ case COND_EXPR:
+ {
/* The two parts of a cond expr might be separate lvalues. */
tree op1 = TREE_OPERAND (expr, 1);
tree op2 = TREE_OPERAND (expr, 2);
@@ -294,7 +295,8 @@ convert_to_void (tree expr, impl_conv_void implicit)
break;
}
- case COMPOUND_EXPR: {
+ case COMPOUND_EXPR:
+ {
/* The second part of a compound expr contains the value. */
tree op1 = TREE_OPERAND (expr, 1);
tree new_op1;
@@ -323,7 +325,8 @@ convert_to_void (tree expr, impl_conv_void implicit)
maybe_warn_nodiscard (expr, implicit);
break;
- case INDIRECT_REF: {
+ case INDIRECT_REF:
+ {
tree type = TREE_TYPE (expr);
int is_reference = TYPE_REF_P (TREE_TYPE (TREE_OPERAND (expr, 0)));
int is_volatile = TYPE_VOLATILE (type);
@@ -518,7 +521,8 @@ convert_to_void (tree expr, impl_conv_void implicit)
break;
}
- case VAR_DECL: {
+ case VAR_DECL:
+ {
/* External variables might be incomplete. */
tree type = TREE_TYPE (expr);
int is_complete = COMPLETE_TYPE_P (type);
@@ -1485,7 +1489,8 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void *data)
parameter pack. ??? Should some of these be in cp_walk_subtrees? */
switch (TREE_CODE (t))
{
- case DECL_EXPR: {
+ case DECL_EXPR:
+ {
tree decl = DECL_EXPR_DECL (t);
if (is_typedef_decl (decl))
/* Since we stop at typedefs above, we need to look through them at
@@ -1506,7 +1511,8 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void *data)
*walk_subtrees = 0;
return NULL_TREE;
- case DECLTYPE_TYPE: {
+ case DECLTYPE_TYPE:
+ {
/* When traversing a DECLTYPE_TYPE_EXPR, we need to set
type_pack_expansion_p to false so that any placeholders
within the expression don't get marked as parameter packs. */
@@ -1970,7 +1976,8 @@ rs_tree_equal (tree t1, tree t2)
case SAVE_EXPR:
return rs_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
- case CALL_EXPR: {
+ case CALL_EXPR:
+ {
if (KOENIG_LOOKUP_P (t1) != KOENIG_LOOKUP_P (t2))
return false;
@@ -1996,7 +2003,8 @@ rs_tree_equal (tree t1, tree t2)
return true;
}
- case TARGET_EXPR: {
+ case TARGET_EXPR:
+ {
tree o1 = TREE_OPERAND (t1, 0);
tree o2 = TREE_OPERAND (t2, 0);
@@ -2067,7 +2075,8 @@ rs_tree_equal (tree t1, tree t2)
case tcc_expression:
case tcc_vl_exp:
case tcc_reference:
- case tcc_statement: {
+ case tcc_statement:
+ {
int n = rs_tree_operand_length (t1);
if (TREE_CODE_CLASS (code1) == tcc_vl_exp
&& n != TREE_OPERAND_LENGTH (t2))
@@ -2095,7 +2104,11 @@ rs_tree_equal (tree t1, tree t2)
/* TRUE iff TYPE is publicly & uniquely derived from PARENT. */
-bool publicly_uniquely_derived_p (tree, tree) { return false; }
+bool
+publicly_uniquely_derived_p (tree, tree)
+{
+ return false;
+}
// forked from gcc/cp/typeck.cc comp_except_types
@@ -3375,7 +3388,11 @@ release_tree_vector (vec<tree, va_gc> *vec)
/* As above, but also check value-dependence of the expression as a whole. */
-bool instantiation_dependent_expression_p (tree) { return false; }
+bool
+instantiation_dependent_expression_p (tree)
+{
+ return false;
+}
// forked from gcc/cp/cvt.cc cp_get_callee
@@ -3425,7 +3442,11 @@ scalarish_type_p (const_tree t)
constructors are deleted. This function implements the ABI notion of
non-trivial copy, which has diverged from the one in the standard. */
-bool type_has_nontrivial_copy_init (const_tree) { return false; }
+bool
+type_has_nontrivial_copy_init (const_tree)
+{
+ return false;
+}
// forked from gcc/cp/tree.cc build_local_temp
@@ -3448,7 +3469,11 @@ build_local_temp (tree type)
/* Returns true iff DECL is a capture proxy for a normal capture
(i.e. without explicit initializer). */
-bool is_normal_capture_proxy (tree) { return false; }
+bool
+is_normal_capture_proxy (tree)
+{
+ return false;
+}
// forked from gcc/cp/c-common.cc reject_gcc_builtin
@@ -3522,7 +3547,8 @@ is_bitfield_expr_with_lowered_type (const_tree exp)
case BIT_NOT_EXPR:
return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
- case COMPONENT_REF: {
+ case COMPONENT_REF:
+ {
tree field;
field = TREE_OPERAND (exp, 1);
@@ -3909,7 +3935,8 @@ retry:
break;
case OFFSET_TYPE:
- bad_member : {
+ bad_member:
+ {
tree member = TREE_OPERAND (value, 1);
if (is_overloaded_fn (member))
member = get_first_fn (member);
@@ -3994,13 +4021,21 @@ decl_constant_var_p (tree decl)
/* Returns true iff DECL is a variable or function declared with an auto type
that has not yet been deduced to a real type. */
-bool undeduced_auto_decl (tree) { return false; }
+bool
+undeduced_auto_decl (tree)
+{
+ return false;
+}
// forked from gcc/cp/decl.cc require_deduced_type
/* Complain if DECL has an undeduced return type. */
-bool require_deduced_type (tree, tsubst_flags_t) { return true; }
+bool
+require_deduced_type (tree, tsubst_flags_t)
+{
+ return true;
+}
/* Return the location of a tree passed to %+ formats. */
@@ -4290,10 +4325,9 @@ struct GTY ((for_user)) source_location_table_entry
} // namespace Rust
-extern void
-gt_pch_nx (Rust::source_location_table_entry &);
-extern void
-gt_pch_nx (Rust::source_location_table_entry *, gt_pointer_operator, void *);
+extern void gt_pch_nx (Rust::source_location_table_entry &);
+extern void gt_pch_nx (Rust::source_location_table_entry *, gt_pointer_operator,
+ void *);
namespace Rust {
@@ -4421,7 +4455,8 @@ lvalue_kind (const_tree ref)
case VIEW_CONVERT_EXPR:
return lvalue_kind (TREE_OPERAND (ref, 0));
- case ARRAY_REF: {
+ case ARRAY_REF:
+ {
tree op1 = TREE_OPERAND (ref, 0);
if (TREE_CODE (TREE_TYPE (op1)) == ARRAY_TYPE)
{
@@ -4518,7 +4553,8 @@ lvalue_kind (const_tree ref)
op2_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 1));
break;
- case COND_EXPR: {
+ case COND_EXPR:
+ {
tree op1 = TREE_OPERAND (ref, 1);
if (!op1)
op1 = TREE_OPERAND (ref, 0);
diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h
index 3630b0e..9e859d4 100644
--- a/gcc/rust/backend/rust-tree.h
+++ b/gcc/rust/backend/rust-tree.h
@@ -1543,7 +1543,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
#if defined ENABLE_TREE_CHECKING
#define LANG_DECL_MIN_CHECK(NODE) \
- __extension__({ \
+ __extension__ ({ \
struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
if (!LANG_DECL_HAS_MIN (NODE)) \
lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
@@ -1554,7 +1554,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
template, not just on a FUNCTION_DECL. So when looking for things in
lang_decl_fn, look down through a TEMPLATE_DECL into its result. */
#define LANG_DECL_FN_CHECK(NODE) \
- __extension__({ \
+ __extension__ ({ \
struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
if (!DECL_DECLARES_FUNCTION_P (NODE) || lt->u.base.selector != lds_fn) \
lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
@@ -1562,7 +1562,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
})
#define LANG_DECL_NS_CHECK(NODE) \
- __extension__({ \
+ __extension__ ({ \
struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
if (TREE_CODE (NODE) != NAMESPACE_DECL || lt->u.base.selector != lds_ns) \
lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
@@ -1570,7 +1570,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
})
#define LANG_DECL_PARM_CHECK(NODE) \
- __extension__({ \
+ __extension__ ({ \
struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
if (TREE_CODE (NODE) != PARM_DECL || lt->u.base.selector != lds_parm) \
lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
@@ -1578,7 +1578,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
})
#define LANG_DECL_DECOMP_CHECK(NODE) \
- __extension__({ \
+ __extension__ ({ \
struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
if (!VAR_P (NODE) || lt->u.base.selector != lds_decomp) \
lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
@@ -2060,8 +2060,8 @@ struct GTY (()) rust_cxx_saved_binding
// forked from gcc/cp/name-lookup.h resort_type_member_vec
/* needed for GTY annotation */
-extern void
-resort_type_member_vec (void *, void *, gt_pointer_operator, void *);
+extern void resort_type_member_vec (void *, void *, gt_pointer_operator,
+ void *);
// forked from gcc/cp/cp-tree.h saved_scope
@@ -2895,8 +2895,7 @@ enum compare_bounds_t
bounds_first
};
-extern tree
-convert_to_void (tree expr, impl_conv_void implicit);
+extern tree convert_to_void (tree expr, impl_conv_void implicit);
// The lvalue-to-rvalue conversion (7.1) is applied if and only if the
// expression is a glvalue of volatile-qualified type and it is one of the
@@ -2911,63 +2910,52 @@ convert_to_void (tree expr, impl_conv_void implicit);
// operands are one of these expressions, or
// * comma expression (8.19) where the right operand is one of these
// expressions.
-extern tree
-mark_discarded_use (tree expr);
+extern tree mark_discarded_use (tree expr);
// Mark EXP as read, not just set, for set but not used -Wunused warning
// purposes.
-extern void
-mark_exp_read (tree exp);
+extern void mark_exp_read (tree exp);
// We've seen an actual use of EXPR. Possibly replace an outer variable
// reference inside with its constant value or a lambda capture.
-extern tree
-mark_use (tree expr, bool rvalue_p, bool read_p, location_t loc,
- bool reject_builtin);
+extern tree mark_use (tree expr, bool rvalue_p, bool read_p, location_t loc,
+ bool reject_builtin);
// Called whenever the expression EXPR is used in an rvalue context.
// When REJECT_BUILTIN is true the expression is checked to make sure
// it doesn't make it possible to obtain the address of a GCC built-in
// function with no library fallback (or any of its bits, such as in
// a conversion to bool).
-extern tree
-mark_rvalue_use (tree, location_t = UNKNOWN_LOCATION,
- bool reject_builtin = true);
+extern tree mark_rvalue_use (tree, location_t = UNKNOWN_LOCATION,
+ bool reject_builtin = true);
// Called whenever an expression is used in an lvalue context.
-extern tree
-mark_lvalue_use (tree expr);
+extern tree mark_lvalue_use (tree expr);
// As above, but don't consider this use a read.
-extern tree
-mark_lvalue_use_nonread (tree expr);
+extern tree mark_lvalue_use_nonread (tree expr);
// We are using a reference VAL for its value. Bash that reference all the way
// down to its lowest form.
-extern tree
-convert_from_reference (tree val);
+extern tree convert_from_reference (tree val);
// Subroutine of convert_to_void. Warn if we're discarding something with
// attribute [[nodiscard]].
-extern void
-maybe_warn_nodiscard (tree expr, impl_conv_void implicit);
+extern void maybe_warn_nodiscard (tree expr, impl_conv_void implicit);
-extern location_t
-expr_loc_or_loc (const_tree t, location_t or_loc);
+extern location_t expr_loc_or_loc (const_tree t, location_t or_loc);
-extern location_t
-expr_loc_or_input_loc (const_tree t);
+extern location_t expr_loc_or_input_loc (const_tree t);
// FN is the callee of a CALL_EXPR or AGGR_INIT_EXPR; return the FUNCTION_DECL
// if we can.
-extern tree
-get_fndecl_from_callee (tree fn);
+extern tree get_fndecl_from_callee (tree fn);
// FIXME some helpers from HIRCompileBase could probably be moved here over time
// Return an expression for the address of BASE[INDEX], used in offset intrinsic
-extern tree
-pointer_offset_expression (tree base_tree, tree index_tree, location_t locus);
+extern tree pointer_offset_expression (tree base_tree, tree index_tree,
+ location_t locus);
/* A tree node, together with a location, so that we can track locations
(and ranges) during parsing.
@@ -2978,11 +2966,9 @@ pointer_offset_expression (tree base_tree, tree index_tree, location_t locus);
extern location_t rs_expr_location (const_tree);
-extern int
-is_empty_class (tree type);
+extern int is_empty_class (tree type);
-extern bool
-is_really_empty_class (tree, bool);
+extern bool is_really_empty_class (tree, bool);
extern bool builtin_valid_in_constant_expr_p (const_tree);
@@ -2990,15 +2976,13 @@ extern bool maybe_constexpr_fn (tree);
extern bool var_in_maybe_constexpr_fn (tree);
-extern int
-rs_type_quals (const_tree type);
+extern int rs_type_quals (const_tree type);
inline bool type_unknown_p (const_tree);
extern bool decl_maybe_constant_var_p (tree);
-extern void
-init_modules ();
+extern void init_modules ();
extern bool var_in_constexpr_fn (tree);
@@ -3006,11 +2990,9 @@ inline tree ovl_first (tree) ATTRIBUTE_PURE;
inline bool type_unknown_p (const_tree);
-extern tree
-lookup_add (tree fns, tree lookup);
+extern tree lookup_add (tree fns, tree lookup);
-extern tree
-ovl_make (tree fn, tree next = NULL_TREE);
+extern tree ovl_make (tree fn, tree next = NULL_TREE);
extern int is_overloaded_fn (tree) ATTRIBUTE_PURE;
@@ -3024,19 +3006,15 @@ extern tree make_conv_op_name (tree);
extern int type_memfn_quals (const_tree);
-struct c_fileinfo *
-get_fileinfo (const char *);
+struct c_fileinfo *get_fileinfo (const char *);
-extern tree
-cxx_make_type (enum tree_code CXX_MEM_STAT_INFO);
+extern tree cxx_make_type (enum tree_code CXX_MEM_STAT_INFO);
-extern tree
-build_cplus_array_type (tree, tree, int is_dep = -1);
+extern tree build_cplus_array_type (tree, tree, int is_dep = -1);
extern bool is_byte_access_type (tree);
-extern bool
-comptypes (tree, tree, int);
+extern bool comptypes (tree, tree, int);
extern tree canonical_eh_spec (tree);
@@ -3046,8 +3024,7 @@ extern bool rs_tree_equal (tree, tree);
extern bool compparms (const_tree, const_tree);
-extern tree
-rs_build_qualified_type_real (tree, int, tsubst_flags_t);
+extern tree rs_build_qualified_type_real (tree, int, tsubst_flags_t);
#define rs_build_qualified_type(TYPE, QUALS) \
rs_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error)
extern bool cv_qualified_p (const_tree);
@@ -3056,21 +3033,18 @@ extern bool similar_type_p (tree, tree);
extern bool rs_tree_equal (tree, tree);
-extern bool
-vector_targets_convertible_p (const_tree t1, const_tree t2);
+extern bool vector_targets_convertible_p (const_tree t1, const_tree t2);
extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree);
extern bool comp_ptr_ttypes_const (tree, tree, compare_bounds_t);
-extern tree
-get_class_binding_direct (tree, tree, bool want_type = false);
+extern tree get_class_binding_direct (tree, tree, bool want_type = false);
extern tree skip_artificial_parms_for (const_tree, tree);
-extern void
-lang_check_failed (const char *, int,
- const char *) ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void lang_check_failed (const char *, int,
+ const char *) ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
extern tree default_init_uninitialized_part (tree);
@@ -3088,8 +3062,7 @@ extern tree in_class_defaulted_default_constructor (tree);
extern bool is_instantiation_of_constexpr (tree);
-extern bool
-check_for_uninitialized_const_var (tree, bool, tsubst_flags_t);
+extern bool check_for_uninitialized_const_var (tree, bool, tsubst_flags_t);
extern bool reduced_constant_expression_p (tree);
@@ -3108,19 +3081,17 @@ extern tree is_bitfield_expr_with_lowered_type (const_tree);
extern tree convert_bitfield_to_declared_type (tree);
-extern tree
-cp_fold_maybe_rvalue (tree, bool);
+extern tree cp_fold_maybe_rvalue (tree, bool);
extern tree maybe_undo_parenthesized_ref (tree);
-extern tree
-fold_offsetof (tree, tree = size_type_node, tree_code ctx = ERROR_MARK);
+extern tree fold_offsetof (tree, tree = size_type_node,
+ tree_code ctx = ERROR_MARK);
extern tree cp_truthvalue_conversion (tree, tsubst_flags_t);
-extern tree
-fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error,
- bool = false, tree = NULL_TREE);
+extern tree fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error,
+ bool = false, tree = NULL_TREE);
extern int char_type_p (tree);
@@ -3163,13 +3134,11 @@ extern tree build_new_constexpr_heap_type (tree, tree, tree);
extern bool is_empty_field (tree);
-extern bool
-in_immediate_context ();
+extern bool in_immediate_context ();
extern tree cp_get_callee_fndecl_nofold (tree);
-extern bool
-cxx_mark_addressable (tree, bool = false);
+extern bool cxx_mark_addressable (tree, bool = false);
extern tree fold_builtin_source_location (location_t);
@@ -3183,25 +3152,22 @@ extern bool glvalue_p (const_tree);
extern cp_lvalue_kind lvalue_kind (const_tree);
-extern tree
-decl_constant_value (tree, bool);
+extern tree decl_constant_value (tree, bool);
extern tree lookup_enumerator (tree, tree);
-extern int
-is_class_type (tree, int);
+extern int is_class_type (tree, int);
extern tree braced_lists_to_strings (tree, tree);
-extern tree
-fold_builtin_is_pointer_inverconvertible_with_class (location_t, int, tree *);
+extern tree fold_builtin_is_pointer_inverconvertible_with_class (location_t,
+ int, tree *);
extern bool layout_compatible_type_p (tree, tree);
extern tree finish_underlying_type (tree);
-extern tree
-c_common_type_for_mode (machine_mode, int);
+extern tree c_common_type_for_mode (machine_mode, int);
extern bool std_layout_type_p (const_tree);
@@ -3213,25 +3179,21 @@ extern void note_failed_type_completion_for_satisfaction (tree);
extern tree complete_type_or_maybe_complain (tree, tree, tsubst_flags_t);
-extern bool
-next_common_initial_seqence (tree &, tree &);
+extern bool next_common_initial_seqence (tree &, tree &);
extern bool null_member_pointer_value_p (tree);
-extern tree
-fold_builtin_is_corresponding_member (location_t, int, tree *);
+extern tree fold_builtin_is_corresponding_member (location_t, int, tree *);
extern tree cp_fold_rvalue (tree);
-extern tree
-maybe_constant_value (tree, tree = NULL_TREE, bool = false);
+extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false);
extern tree lvalue_type (tree);
extern void lvalue_error (location_t, enum lvalue_use);
-extern tree
-cp_fold_maybe_rvalue (tree, bool);
+extern tree cp_fold_maybe_rvalue (tree, bool);
extern tree get_first_fn (tree) ATTRIBUTE_PURE;
@@ -3253,13 +3215,12 @@ enum
ce_exact
};
-extern tree
-rs_build_qualified_type_real (tree, int, tsubst_flags_t);
+extern tree rs_build_qualified_type_real (tree, int, tsubst_flags_t);
#define rs_build_qualified_type(TYPE, QUALS) \
rs_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error)
-extern tree
-rs_walk_subtrees (tree *, int *, walk_tree_fn, void *, hash_set<tree> *);
+extern tree rs_walk_subtrees (tree *, int *, walk_tree_fn, void *,
+ hash_set<tree> *);
#define rs_walk_tree(tp, func, data, pset) \
walk_tree_1 (tp, func, data, pset, rs_walk_subtrees)
#define rs_walk_tree_without_duplicates(tp, func, data) \
@@ -3351,11 +3312,9 @@ gnu_vector_type_p (const_tree type)
return TREE_CODE (type) == VECTOR_TYPE && !TYPE_INDIVISIBLE_P (type);
}
-extern vec<tree, va_gc> *
-make_tree_vector (void);
+extern vec<tree, va_gc> *make_tree_vector (void);
-extern void
-release_tree_vector (vec<tree, va_gc> *);
+extern void release_tree_vector (vec<tree, va_gc> *);
/* Simplified unique_ptr clone to release a tree vec on exit. */
@@ -3373,7 +3332,7 @@ public:
releasing_vec &operator= (const releasing_vec &);
vec_t &operator* () const { return *v; }
- vec_t *operator-> () const { return v; }
+ vec_t *operator->() const { return v; }
vec_t *get () const { return v; }
operator vec_t * () const { return v; }
vec_t **operator& () { return &v; }
@@ -3442,8 +3401,7 @@ cxx_incomplete_type_error (const_tree value, const_tree type)
cxx_incomplete_type_diagnostic (value, type, diagnostics::kind::error);
}
-extern location_t
-location_of (tree t);
+extern location_t location_of (tree t);
/* Helpers for IMPLICIT_RVALUE_P to look through automatic dereference. */
@@ -3465,23 +3423,18 @@ set_implicit_rvalue_p (tree ot)
}
namespace Compile {
-extern tree
-maybe_constant_init (tree, tree = NULL_TREE, bool = false);
+extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false);
-extern void
-explain_invalid_constexpr_fn (tree fun);
+extern void explain_invalid_constexpr_fn (tree fun);
extern bool potential_constant_expression (tree);
-extern bool
-literal_type_p (tree t);
+extern bool literal_type_p (tree t);
-extern bool
-maybe_constexpr_fn (tree t);
+extern bool maybe_constexpr_fn (tree t);
-extern tree
-fold_non_dependent_init (tree, tsubst_flags_t = tf_warning_or_error,
- bool = false, tree = NULL_TREE);
+extern tree fold_non_dependent_init (tree, tsubst_flags_t = tf_warning_or_error,
+ bool = false, tree = NULL_TREE);
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h
index 0ce2142..0434bcf 100644
--- a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h
+++ b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h
@@ -239,31 +239,25 @@ struct Facts
*
* Output is not yet implemented and is only dumped to stdout.
*/
-extern "C" FFI::Output
-polonius_run (FFI::FactsView input, bool dump_enabled);
+extern "C" FFI::Output polonius_run (FFI::FactsView input, bool dump_enabled);
// Helper functions for FFIVector to be used on Rust side
extern "C" {
-FFI::FFIVector<size_t> *
-FFIVector__new ();
+FFI::FFIVector<size_t> *FFIVector__new ();
-FFI::FFIVectorPair *
-FFIVector__new_vec_pair ();
+FFI::FFIVectorPair *FFIVector__new_vec_pair ();
-FFI::FFIVectorTriple *
-FFIVector__new_vec_triple ();
+FFI::FFIVectorTriple *FFIVector__new_vec_triple ();
-void
-FFIVector__push (FFI::FFIVector<size_t> *vector, size_t element);
+void FFIVector__push (FFI::FFIVector<size_t> *vector, size_t element);
void
FFIVector__push_vec_pair (FFI::FFIVectorPair *vector,
FFI::Pair<size_t, FFI::FFIVector<size_t> *> element);
-void
-FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector,
- FFI::Triple<size_t, size_t, size_t> element);
+void FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector,
+ FFI::Triple<size_t, size_t, size_t> element);
}
} // namespace Polonius
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
index 6b8b2e9..5b22c1a 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
@@ -240,7 +240,8 @@ ExprStmtBuilder::visit (HIR::ArrayExpr &expr)
auto &elems = expr.get_internal_elements ();
switch (elems.get_array_expr_type ())
{
- case HIR::ArrayElems::VALUES: {
+ case HIR::ArrayElems::VALUES:
+ {
auto &elem_vals = (static_cast<HIR::ArrayElemsValues &> (elems));
auto init_values = visit_list (elem_vals.get_values ());
// collect locations
@@ -254,7 +255,8 @@ ExprStmtBuilder::visit (HIR::ArrayExpr &expr)
lookup_type (expr), expr.get_locus ());
break;
}
- case HIR::ArrayElems::COPIED: {
+ case HIR::ArrayElems::COPIED:
+ {
auto &elem_copied = (static_cast<HIR::ArrayElemsCopied &> (elems));
auto init = visit_expr (elem_copied.get_elem_to_copy ());
return_expr (new InitializerExpr ({init}), lookup_type (expr),
@@ -329,6 +331,10 @@ ExprStmtBuilder::visit (HIR::LlvmInlineAsm &expr)
{}
void
+ExprStmtBuilder::visit (HIR::OffsetOf &expr)
+{}
+
+void
ExprStmtBuilder::visit (HIR::MethodCallExpr &expr)
{}
@@ -415,6 +421,18 @@ ExprStmtBuilder::visit (HIR::BlockExpr &block)
}
void
+ExprStmtBuilder::visit (HIR::AnonConst &block)
+{
+ rust_unreachable ();
+}
+
+void
+ExprStmtBuilder::visit (HIR::ConstBlock &block)
+{
+ rust_unreachable ();
+}
+
+void
ExprStmtBuilder::visit (HIR::ContinueExpr &cont)
{
LoopAndLabelCtx info = cont.has_label () ? get_label_ctx (cont.get_label ())
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
index 5cab3c4..ba5db8b 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
@@ -19,6 +19,7 @@
#ifndef RUST_BIR_BUILDER_EXPR_H
#define RUST_BIR_BUILDER_EXPR_H
+#include "rust-hir-expr.h"
#include "rust-hir-visitor.h"
#include "rust-bir-builder-internal.h"
@@ -84,6 +85,8 @@ protected: // Expr
void visit (HIR::MethodCallExpr &expr) override;
void visit (HIR::FieldAccessExpr &expr) override;
void visit (HIR::BlockExpr &block) override;
+ void visit (HIR::AnonConst &block) override;
+ void visit (HIR::ConstBlock &block) override;
void visit (HIR::ContinueExpr &cont) override;
void visit (HIR::BreakExpr &brk) override;
void visit (HIR::RangeFromToExpr &range) override;
@@ -101,6 +104,7 @@ protected: // Expr
void visit (HIR::IfExprConseqElse &expr) override;
void visit (HIR::InlineAsm &expr) override;
void visit (HIR::LlvmInlineAsm &expr) override;
+ void visit (HIR::OffsetOf &expr) override;
void visit (HIR::MatchExpr &expr) override;
void visit (HIR::AwaitExpr &expr) override;
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
index 4df0e14..e2cc2dd 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
@@ -27,6 +27,8 @@
#include "rust-name-resolver.h"
#include "rust-bir.h"
#include "rust-bir-free-region.h"
+#include "rust-immutable-name-resolution-context.h"
+#include "options.h"
namespace Rust {
@@ -402,19 +404,40 @@ protected: // HIR resolution helpers
template <typename T> NodeId resolve_label (T &expr)
{
NodeId resolved_label;
- bool ok
- = ctx.resolver.lookup_resolved_label (expr.get_mappings ().get_nodeid (),
- &resolved_label);
- rust_assert (ok);
+ if (flag_name_resolution_2_0)
+ {
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto res = nr_ctx.lookup (expr.get_mappings ().get_nodeid ());
+ rust_assert (res.has_value ());
+ resolved_label = res.value ();
+ }
+ else
+ {
+ bool ok = ctx.resolver.lookup_resolved_label (
+ expr.get_mappings ().get_nodeid (), &resolved_label);
+ rust_assert (ok);
+ }
return resolved_label;
}
template <typename T> PlaceId resolve_variable (T &variable)
{
NodeId variable_id;
- bool ok = ctx.resolver.lookup_resolved_name (
- variable.get_mappings ().get_nodeid (), &variable_id);
- rust_assert (ok);
+ if (flag_name_resolution_2_0)
+ {
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ());
+ rust_assert (res.has_value ());
+ variable_id = res.value ();
+ }
+ else
+ {
+ bool ok = ctx.resolver.lookup_resolved_name (
+ variable.get_mappings ().get_nodeid (), &variable_id);
+ rust_assert (ok);
+ }
return ctx.place_db.lookup_variable (variable_id);
}
@@ -425,9 +448,20 @@ protected: // HIR resolution helpers
// Unlike variables,
// functions do not have to be declared in PlaceDB before use.
NodeId variable_id;
- bool ok = ctx.resolver.lookup_resolved_name (
- variable.get_mappings ().get_nodeid (), &variable_id);
- rust_assert (ok);
+ if (flag_name_resolution_2_0)
+ {
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ());
+ rust_assert (res.has_value ());
+ variable_id = res.value ();
+ }
+ else
+ {
+ bool ok = ctx.resolver.lookup_resolved_name (
+ variable.get_mappings ().get_nodeid (), &variable_id);
+ rust_assert (ok);
+ }
if (ty->is<TyTy::FnType> ())
return ctx.place_db.get_constant (ty);
else
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
index b7a1555..9108009 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
@@ -169,6 +169,14 @@ public:
{
return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
}
+ void visit (HIR::AnonConst &expr) override
+ {
+ return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
+ }
+ void visit (HIR::ConstBlock &expr) override
+ {
+ return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
+ }
void visit (HIR::UnsafeBlockExpr &expr) override
{
return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
@@ -208,6 +216,7 @@ public:
void visit (HIR::InlineAsm &expr) override {}
void visit (HIR::LlvmInlineAsm &expr) override {}
+ void visit (HIR::OffsetOf &expr) override {}
protected: // Illegal at this position.
void visit (HIR::StructExprFieldIdentifier &field) override
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
index ee37bb0..2d655f9 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
@@ -101,7 +101,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern)
{
switch (field->get_item_type ())
{
- case HIR::StructPatternField::TUPLE_PAT: {
+ case HIR::StructPatternField::TUPLE_PAT:
+ {
auto tuple
= static_cast<HIR::StructPatternFieldTuplePat *> (field.get ());
@@ -123,7 +124,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern)
tuple->get_tuple_pattern ().accept_vis (*this);
break;
}
- case HIR::StructPatternField::IDENT_PAT: {
+ case HIR::StructPatternField::IDENT_PAT:
+ {
auto ident_field
= static_cast<HIR::StructPatternFieldIdentPat *> (field.get ());
TyTy::StructFieldType *field_ty = nullptr;
@@ -139,7 +141,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern)
ident_field->get_pattern ().accept_vis (*this);
break;
}
- case HIR::StructPatternField::IDENT: {
+ case HIR::StructPatternField::IDENT:
+ {
auto ident_field
= static_cast<HIR::StructPatternFieldIdent *> (field.get ());
TyTy::StructFieldType *field_ty = nullptr;
@@ -199,13 +202,15 @@ PatternBindingBuilder::visit (HIR::TuplePattern &pattern)
size_t index = 0;
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::MULTIPLE: {
+ case HIR::TuplePatternItems::MULTIPLE:
+ {
auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
pattern.get_items ());
visit_tuple_fields (items.get_patterns (), saved, index);
break;
}
- case HIR::TuplePatternItems::RANGED: {
+ case HIR::TuplePatternItems::RANGED:
+ {
auto &items
= static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
@@ -244,7 +249,8 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern)
size_t index = 0;
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TupleStructItems::RANGED: {
+ case HIR::TupleStructItems::RANGED:
+ {
auto &items
= static_cast<HIR::TupleStructItemsRange &> (pattern.get_items ());
@@ -261,7 +267,8 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern)
visit_tuple_fields (items.get_upper_patterns (), saved, index);
break;
}
- case HIR::TupleStructItems::MULTIPLE: {
+ case HIR::TupleStructItems::MULTIPLE:
+ {
auto &items
= static_cast<HIR::TupleStructItemsNoRange &> (pattern.get_items ());
visit_tuple_fields (items.get_patterns (), saved, index);
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
index 84311cc..d87ff8c 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
@@ -21,6 +21,7 @@
#include "rust-bir-builder-internal.h"
#include "rust-bir-builder-expr-stmt.h"
+#include "rust-hir-expr.h"
namespace Rust {
namespace BIR {
@@ -133,6 +134,8 @@ protected:
void visit (HIR::MethodCallExpr &expr) override { rust_unreachable (); }
void visit (HIR::FieldAccessExpr &expr) override { rust_unreachable (); }
void visit (HIR::BlockExpr &expr) override { rust_unreachable (); }
+ void visit (HIR::AnonConst &expr) override { rust_unreachable (); }
+ void visit (HIR::ConstBlock &expr) override { rust_unreachable (); }
void visit (HIR::ClosureExpr &expr) override { rust_unreachable (); }
void visit (HIR::ContinueExpr &expr) override { rust_unreachable (); }
void visit (HIR::BreakExpr &expr) override { rust_unreachable (); }
@@ -154,6 +157,7 @@ protected:
void visit (HIR::AsyncBlockExpr &expr) override { rust_unreachable (); }
void visit (HIR::InlineAsm &expr) override { rust_unreachable (); }
void visit (HIR::LlvmInlineAsm &expr) override { rust_unreachable (); }
+ void visit (HIR::OffsetOf &expr) override { rust_unreachable (); }
void visit (HIR::TypeParam &param) override { rust_unreachable (); }
void visit (HIR::ConstGenericParam &param) override { rust_unreachable (); }
void visit (HIR::LifetimeWhereClauseItem &item) override
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
index 3864b81..9a7bb20 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
@@ -182,7 +182,8 @@ Dump::visit (const Statement &stmt)
statement_place = stmt.get_place ();
switch (stmt.get_kind ())
{
- case Statement::Kind::ASSIGNMENT: {
+ case Statement::Kind::ASSIGNMENT:
+ {
visit_place (stmt.get_place ());
stream << " = ";
stmt.get_expr ().accept_vis (*this);
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h
index 32a4cd7..4462d77 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h
@@ -232,42 +232,50 @@ protected: // Main collection entry points (for different categories).
{
switch (stmt.get_kind ())
{
- case Statement::Kind::ASSIGNMENT: {
+ case Statement::Kind::ASSIGNMENT:
+ {
// TODO: for unwind, must had hadning for non-panic-only assignements
issue_write_deep (stmt.get_place ());
visit_assignment_expr (stmt.get_place (), stmt.get_expr ());
break;
}
- case Statement::Kind::SWITCH: {
+ case Statement::Kind::SWITCH:
+ {
issue_read_move (stmt.get_place ());
issue_jumps ();
}
break;
- case Statement::Kind::GOTO: {
+ case Statement::Kind::GOTO:
+ {
issue_jumps ();
}
break;
- case Statement::Kind::RETURN: {
+ case Statement::Kind::RETURN:
+ {
issue_place_access (RETURN_VALUE_PLACE);
issue_locals_dealloc ();
break;
}
- case Statement::Kind::STORAGE_DEAD: {
+ case Statement::Kind::STORAGE_DEAD:
+ {
facts.path_moved_at_base.emplace_back (stmt.get_place ().value,
get_current_point_mid ());
facts.var_defined_at.emplace_back (stmt.get_place ().value,
get_current_point_mid ());
break;
}
- case Statement::Kind::STORAGE_LIVE: {
+ case Statement::Kind::STORAGE_LIVE:
+ {
issue_write_deep (stmt.get_place (), true);
break;
}
- case Statement::Kind::USER_TYPE_ASCRIPTION: {
+ case Statement::Kind::USER_TYPE_ASCRIPTION:
+ {
issue_user_type_constraints (stmt.get_place (), stmt.get_type ());
break;
}
- case Statement::Kind::FAKE_READ: {
+ case Statement::Kind::FAKE_READ:
+ {
issue_place_access (stmt.get_place ());
break;
}
@@ -791,7 +799,8 @@ protected: // Subset helpers.
type->as<const TyTy::SliceType> ()->get_element_type (), region_start,
regions);
case TyTy::FNDEF:
- case TyTy::TUPLE: {
+ case TyTy::TUPLE:
+ {
for (auto &field : type->as<const TyTy::TupleType> ()->get_fields ())
sanitize_constraints (field.get_tyty (), region_start, regions);
}
@@ -815,6 +824,7 @@ protected: // Subset helpers.
case TyTy::PLACEHOLDER:
case TyTy::INFER:
case TyTy::PARAM:
+ case TyTy::CONST:
case TyTy::OPAQUE:
rust_unreachable ();
}
@@ -874,7 +884,7 @@ protected: // Subset helpers.
return region_end;
}
-}; // namespace BIR
+};
} // namespace BIR
} // namespace Rust
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
index dd9e672..2e9103f 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
@@ -53,7 +53,7 @@ using Variance = TyTy::VarianceAnalysis::Variance;
/** A unique identifier for a loan in the BIR. */
struct LoanId
{
- uint32_t value;
+ size_t value;
// some overloads for comparision
bool operator== (const LoanId &rhs) const { return value == rhs.value; }
bool operator!= (const LoanId &rhs) const { return !(operator== (rhs)); }
@@ -217,7 +217,7 @@ public:
const T &operator[] (I pid) const { return internal_vector[pid.value]; }
void push_back (T &&param) { internal_vector.push_back (std::move (param)); }
- template <typename... Args> void emplace_back (Args &&... args)
+ template <typename... Args> void emplace_back (Args &&...args)
{
internal_vector.emplace_back (std::forward<Args> (args)...);
}
@@ -471,14 +471,16 @@ private:
case TyTy::FNDEF:
case TyTy::NEVER:
return true;
- case TyTy::TUPLE: {
+ case TyTy::TUPLE:
+ {
auto &fields = ty->as<TyTy::TupleType> ()->get_fields ();
return std::all_of (fields.begin (), fields.end (),
[] (const TyTy::TyVar &field) {
return is_type_copy (field.get_tyty ());
});
}
- case TyTy::ARRAY: {
+ case TyTy::ARRAY:
+ {
return is_type_copy (ty->as<TyTy::ArrayType> ()->get_element_type ());
}
case TyTy::INFER:
@@ -491,6 +493,7 @@ private:
case TyTy::PROJECTION: // TODO: DUNNO
case TyTy::CLOSURE: // TODO: DUNNO
case TyTy::DYNAMIC: // TODO: dunno
+ case TyTy::CONST:
case TyTy::OPAQUE:
return false;
}
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h
index 5dac89e..d405569 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h
@@ -51,7 +51,7 @@ template <typename BASE, typename T> class VisitableImpl : public BASE
{
public:
template <typename... Args>
- explicit VisitableImpl (Args &&... args) : BASE (std::forward<Args> (args)...)
+ explicit VisitableImpl (Args &&...args) : BASE (std::forward<Args> (args)...)
{}
void accept_vis (Visitor &visitor) override
diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
index 7cf0952..86f96c1 100644
--- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h
+++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
@@ -19,6 +19,7 @@
#ifndef RUST_HIR_FUNCTION_COLLECTOR_H
#define RUST_HIR_FUNCTION_COLLECTOR_H
+#include "rust-hir-expr.h"
#include "rust-hir-item.h"
#include "rust-hir-visitor.h"
#include "rust-hir.h"
@@ -104,6 +105,8 @@ public:
void visit (HIR::MethodCallExpr &expr) override {}
void visit (HIR::FieldAccessExpr &expr) override {}
void visit (HIR::BlockExpr &expr) override {}
+ void visit (HIR::AnonConst &expr) override {}
+ void visit (HIR::ConstBlock &expr) override {}
void visit (HIR::ContinueExpr &expr) override {}
void visit (HIR::BreakExpr &expr) override {}
void visit (HIR::RangeFromToExpr &expr) override {}
@@ -124,6 +127,7 @@ public:
void visit (HIR::AsyncBlockExpr &expr) override {}
void visit (HIR::InlineAsm &expr) override {}
void visit (HIR::LlvmInlineAsm &expr) override {}
+ void visit (HIR::OffsetOf &expr) override {}
void visit (HIR::TypeParam &param) override {}
void visit (HIR::ConstGenericParam &param) override {}
void visit (HIR::LifetimeWhereClauseItem &item) override {}
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
index 3d25459..5291276 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
@@ -25,8 +25,7 @@
#include "rust-pub-restricted-visitor.h"
#include "rust-privacy-reporter.h"
-extern bool
-saw_errors (void);
+extern bool saw_errors (void);
namespace Rust {
namespace Privacy {
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h b/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h
index a506613f..9699ac4 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h
@@ -71,8 +71,7 @@ private:
#if CHECKING_P
namespace selftest {
-void
-rust_privacy_ctx_test (void);
+void rust_privacy_ctx_test (void);
}
#endif // !CHECKING_P
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
index 2a10053..4af9639 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
@@ -157,7 +157,8 @@ PrivacyReporter::check_for_privacy_violation (const NodeId &use_id,
{
case ModuleVisibility::Public:
break;
- case ModuleVisibility::Restricted: {
+ case ModuleVisibility::Restricted:
+ {
// If we are in the crate, everything is restricted correctly, but we
// can't get a module for it
if (!current_module.has_value ())
@@ -215,12 +216,14 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings,
case TyTy::USIZE:
case TyTy::ISIZE:
case TyTy::ADT:
- case TyTy::STR: {
+ case TyTy::STR:
+ {
auto ref_id = ty->get_ref ();
if (auto lookup_id = mappings.lookup_hir_to_node (ref_id))
return check_for_privacy_violation (*lookup_id, locus);
- rust_unreachable ();
}
+ break;
+
case TyTy::REF:
return recursive_check (
static_cast<const TyTy::ReferenceType *> (ty)->get_base ());
@@ -243,7 +246,8 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings,
static_cast<const TyTy::TupleType *> (ty)->get_fields ())
recursive_check (param.get_tyty ());
return;
- case TyTy::PLACEHOLDER: {
+ case TyTy::PLACEHOLDER:
+ {
const auto p = static_cast<const TyTy::PlaceholderType *> (ty);
if (!p->can_resolve ())
return;
@@ -273,6 +277,8 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings,
return;
case TyTy::OPAQUE:
return;
+ case TyTy::CONST:
+ return;
case TyTy::ERROR:
return;
}
@@ -310,6 +316,12 @@ PrivacyReporter::visit (HIR::LlvmInlineAsm &)
{}
void
+PrivacyReporter::visit (HIR::OffsetOf &expr)
+{
+ // TODO: Do we have to do anything?
+}
+
+void
PrivacyReporter::visit (HIR::TypePath &path)
{
check_for_privacy_violation (path.get_mappings ().get_nodeid (),
@@ -413,7 +425,8 @@ PrivacyReporter::visit (HIR::ArrayExpr &expr)
HIR::ArrayElems &elements = expr.get_internal_elements ();
switch (elements.get_array_expr_type ())
{
- case HIR::ArrayElems::ArrayExprType::VALUES: {
+ case HIR::ArrayElems::ArrayExprType::VALUES:
+ {
auto &elems = static_cast<HIR::ArrayElemsValues &> (elements);
for (auto &value : elems.get_values ())
value->accept_vis (*this);
@@ -518,6 +531,18 @@ PrivacyReporter::visit (HIR::BlockExpr &expr)
}
void
+PrivacyReporter::visit (HIR::AnonConst &expr)
+{
+ expr.get_inner_expr ().accept_vis (*this);
+}
+
+void
+PrivacyReporter::visit (HIR::ConstBlock &expr)
+{
+ expr.get_const_expr ().accept_vis (*this);
+}
+
+void
PrivacyReporter::visit (HIR::ContinueExpr &)
{}
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
index 7df2cf4..72716a6 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
@@ -19,6 +19,7 @@
#ifndef RUST_PRIVACY_REPORTER_H
#define RUST_PRIVACY_REPORTER_H
+#include "rust-hir-expr.h"
#include "rust-hir-map.h"
#include "rust-hir-visitor.h"
#include "rust-mapping-common.h"
@@ -106,6 +107,8 @@ types
virtual void visit (HIR::MethodCallExpr &expr);
virtual void visit (HIR::FieldAccessExpr &expr);
virtual void visit (HIR::BlockExpr &expr);
+ virtual void visit (HIR::AnonConst &expr);
+ virtual void visit (HIR::ConstBlock &expr);
virtual void visit (HIR::ContinueExpr &expr);
virtual void visit (HIR::BreakExpr &expr);
virtual void visit (HIR::RangeFromToExpr &expr);
@@ -126,6 +129,7 @@ types
virtual void visit (HIR::AsyncBlockExpr &expr);
virtual void visit (HIR::InlineAsm &expr);
virtual void visit (HIR::LlvmInlineAsm &expr);
+ virtual void visit (HIR::OffsetOf &expr);
virtual void visit (HIR::EnumItemTuple &);
virtual void visit (HIR::EnumItemStruct &);
diff --git a/gcc/rust/checks/errors/privacy/rust-reachability.cc b/gcc/rust/checks/errors/privacy/rust-reachability.cc
index 1e57674..223c77b 100644
--- a/gcc/rust/checks/errors/privacy/rust-reachability.cc
+++ b/gcc/rust/checks/errors/privacy/rust-reachability.cc
@@ -158,7 +158,8 @@ ReachabilityVisitor::visit (HIR::Enum &enum_item)
switch (variant->get_enum_item_kind ())
{
- case HIR::EnumItem::Tuple: {
+ case HIR::EnumItem::Tuple:
+ {
// Should we update the fields only if they are public? Similarly to
// what we do in the ReachabilityVisitor for HIR::TupleStruct?
auto tuple_variant
@@ -167,7 +168,8 @@ ReachabilityVisitor::visit (HIR::Enum &enum_item)
ctx.update_reachability (field.get_mappings (), variant_reach);
break;
}
- case HIR::EnumItem::Struct: {
+ case HIR::EnumItem::Struct:
+ {
// Should we update the fields only if they are public? Similarly to
// what we do in the ReachabilityVisitor for HIR::StructStruct?
auto struct_variant
diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
index f0da745..c59763d 100644
--- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
+++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
@@ -127,7 +127,8 @@ VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility,
case HIR::Visibility::PUBLIC:
to_resolve = ModuleVisibility::create_public ();
return true;
- case HIR::Visibility::RESTRICTED: {
+ case HIR::Visibility::RESTRICTED:
+ {
// FIXME: We also need to handle 2015 vs 2018 edition conflicts
auto id = UNKNOWN_DEFID;
auto result = resolve_module_path (visibility.get_path (), id);
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc
index 3716ea5..c40f9db 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -417,6 +417,26 @@ ConstChecker::visit (BlockExpr &expr)
}
void
+ConstChecker::visit (AnonConst &expr)
+{
+ const_context.enter (expr.get_mappings ().get_hirid ());
+
+ expr.get_inner_expr ().accept_vis (*this);
+
+ const_context.exit ();
+}
+
+void
+ConstChecker::visit (ConstBlock &expr)
+{
+ const_context.enter (expr.get_mappings ().get_hirid ());
+
+ expr.get_const_expr ().accept_vis (*this);
+
+ const_context.exit ();
+}
+
+void
ConstChecker::visit (ContinueExpr &)
{}
@@ -541,6 +561,10 @@ ConstChecker::visit (LlvmInlineAsm &)
{}
void
+ConstChecker::visit (OffsetOf &)
+{}
+
+void
ConstChecker::visit (TypeParam &)
{}
diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h
index b954330..eb63095 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -113,6 +113,8 @@ private:
virtual void visit (FieldAccessExpr &expr) override;
virtual void visit (ClosureExpr &expr) override;
virtual void visit (BlockExpr &expr) override;
+ virtual void visit (AnonConst &expr) override;
+ virtual void visit (ConstBlock &expr) override;
virtual void visit (ContinueExpr &expr) override;
virtual void visit (BreakExpr &expr) override;
virtual void visit (RangeFromToExpr &expr) override;
@@ -133,6 +135,7 @@ private:
virtual void visit (AsyncBlockExpr &expr) override;
virtual void visit (InlineAsm &expr) override;
virtual void visit (LlvmInlineAsm &expr) override;
+ virtual void visit (OffsetOf &expr) override;
virtual void visit (TypeParam &param) override;
virtual void visit (ConstGenericParam &param) override;
diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/rust-feature.cc
index 441a1b2..071d3f8 100644
--- a/gcc/rust/checks/errors/rust-feature.cc
+++ b/gcc/rust/checks/errors/rust-feature.cc
@@ -84,7 +84,7 @@ const std::map<std::string, Feature::Name> Feature::name_hash_map = {
{"exclusive_range_pattern", Feature::Name::EXCLUSIVE_RANGE_PATTERN},
{"prelude_import", Feature::Name::PRELUDE_IMPORT},
{"min_specialization", Feature::Name::MIN_SPECIALIZATION},
-}; // namespace Rust
+};
tl::optional<Feature::Name>
Feature::as_name (const std::string &name)
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index 648bc07..2566971 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -295,6 +295,18 @@ PatternChecker::visit (BlockExpr &expr)
}
void
+PatternChecker::visit (AnonConst &expr)
+{
+ expr.get_inner_expr ().accept_vis (*this);
+}
+
+void
+PatternChecker::visit (ConstBlock &expr)
+{
+ expr.get_const_expr ().accept_vis (*this);
+}
+
+void
PatternChecker::visit (ContinueExpr &)
{}
@@ -427,6 +439,10 @@ PatternChecker::visit (LlvmInlineAsm &expr)
{}
void
+PatternChecker::visit (OffsetOf &expr)
+{}
+
+void
PatternChecker::visit (TypeParam &)
{}
@@ -728,23 +744,27 @@ Constructor::is_covered_by (const Constructor &o) const
switch (kind)
{
- case ConstructorKind::VARIANT: {
+ case ConstructorKind::VARIANT:
+ {
rust_assert (kind == ConstructorKind::VARIANT);
return variant_idx == o.variant_idx;
}
break;
- case ConstructorKind::INT_RANGE: {
+ case ConstructorKind::INT_RANGE:
+ {
rust_assert (kind == ConstructorKind::INT_RANGE);
return int_range.lo >= o.int_range.lo && int_range.hi <= o.int_range.hi;
}
break;
- case ConstructorKind::WILDCARD: {
+ case ConstructorKind::WILDCARD:
+ {
// TODO: wildcard is covered by a variant of enum with a single
// variant
return false;
}
break;
- case ConstructorKind::STRUCT: {
+ case ConstructorKind::STRUCT:
+ {
// Struct pattern is always covered by a other struct constructor.
return true;
}
@@ -900,19 +920,22 @@ PlaceInfo::specialize (const Constructor &c) const
switch (c.get_kind ())
{
case Constructor::ConstructorKind::WILDCARD:
- case Constructor::ConstructorKind::INT_RANGE: {
+ case Constructor::ConstructorKind::INT_RANGE:
+ {
return {};
}
break;
case Constructor::ConstructorKind::STRUCT:
- case Constructor::ConstructorKind::VARIANT: {
+ case Constructor::ConstructorKind::VARIANT:
+ {
rust_assert (ty->get_kind () == TyTy::TypeKind::ADT);
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
switch (adt->get_adt_kind ())
{
case TyTy::ADTType::ADTKind::ENUM:
case TyTy::ADTType::ADTKind::STRUCT_STRUCT:
- case TyTy::ADTType::ADTKind::TUPLE_STRUCT: {
+ case TyTy::ADTType::ADTKind::TUPLE_STRUCT:
+ {
TyTy::VariantDef *variant
= adt->get_variants ().at (c.get_variant_index ());
if (variant->get_variant_type ()
@@ -926,14 +949,16 @@ PlaceInfo::specialize (const Constructor &c) const
return new_place_infos;
}
break;
- case TyTy::ADTType::ADTKind::UNION: {
+ case TyTy::ADTType::ADTKind::UNION:
+ {
// TODO: support unions
rust_unreachable ();
}
}
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
break;
@@ -991,7 +1016,8 @@ WitnessPat::to_string () const
{
switch (ctor.get_kind ())
{
- case Constructor::ConstructorKind::STRUCT: {
+ case Constructor::ConstructorKind::STRUCT:
+ {
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
TyTy::VariantDef *variant
= adt->get_variants ().at (ctor.get_variant_index ());
@@ -1016,7 +1042,8 @@ WitnessPat::to_string () const
return buf;
}
break;
- case Constructor::ConstructorKind::VARIANT: {
+ case Constructor::ConstructorKind::VARIANT:
+ {
std::string buf;
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
buf += adt->get_identifier ();
@@ -1026,11 +1053,13 @@ WitnessPat::to_string () const
switch (variant->get_variant_type ())
{
- case TyTy::VariantDef::VariantType::NUM: {
+ case TyTy::VariantDef::VariantType::NUM:
+ {
return buf;
}
break;
- case TyTy::VariantDef::VariantType::TUPLE: {
+ case TyTy::VariantDef::VariantType::TUPLE:
+ {
buf += "(";
for (size_t i = 0; i < fields.size (); i++)
{
@@ -1042,7 +1071,8 @@ WitnessPat::to_string () const
return buf;
}
break;
- case TyTy::VariantDef::VariantType::STRUCT: {
+ case TyTy::VariantDef::VariantType::STRUCT:
+ {
buf += " {";
if (!fields.empty ())
buf += " ";
@@ -1061,7 +1091,8 @@ WitnessPat::to_string () const
buf += "}";
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
break;
@@ -1069,21 +1100,25 @@ WitnessPat::to_string () const
return buf;
}
break;
- case Constructor::ConstructorKind::INT_RANGE: {
+ case Constructor::ConstructorKind::INT_RANGE:
+ {
// TODO: implement
rust_unreachable ();
}
break;
- case Constructor::ConstructorKind::WILDCARD: {
+ case Constructor::ConstructorKind::WILDCARD:
+ {
return "_";
}
break;
- case Constructor::ConstructorKind::REFERENCE: {
+ case Constructor::ConstructorKind::REFERENCE:
+ {
// TODO: implement
rust_unreachable ();
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
break;
@@ -1100,12 +1135,14 @@ WitnessMatrix::apply_constructor (const Constructor &ctor,
// TODO: only support struct and variant ctor for now.
switch (ctor.get_kind ())
{
- case Constructor::ConstructorKind::WILDCARD: {
+ case Constructor::ConstructorKind::WILDCARD:
+ {
arity = 0;
}
break;
case Constructor::ConstructorKind::STRUCT:
- case Constructor::ConstructorKind::VARIANT: {
+ case Constructor::ConstructorKind::VARIANT:
+ {
if (ty->get_kind () == TyTy::TypeKind::ADT)
{
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
@@ -1118,7 +1155,8 @@ WitnessMatrix::apply_constructor (const Constructor &ctor,
}
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
}
@@ -1160,9 +1198,9 @@ WitnessMatrix::extend (const WitnessMatrix &other)
}
// forward declarations
-static DeconstructedPat
-lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern,
- TyTy::BaseType *scrutinee_ty);
+static DeconstructedPat lower_pattern (Resolver::TypeCheckContext *ctx,
+ HIR::Pattern &pattern,
+ TyTy::BaseType *scrutinee_ty);
static DeconstructedPat
lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
@@ -1175,7 +1213,8 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
std::vector<DeconstructedPat> fields;
switch (elems.get_item_type ())
{
- case HIR::TupleStructItems::ItemType::MULTIPLE: {
+ case HIR::TupleStructItems::ItemType::MULTIPLE:
+ {
HIR::TupleStructItemsNoRange &multiple
= static_cast<HIR::TupleStructItemsNoRange &> (elems);
@@ -1191,12 +1230,14 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
}
break;
- case HIR::TupleStructItems::ItemType::RANGED: {
+ case HIR::TupleStructItems::ItemType::RANGED:
+ {
// TODO: ranged tuple struct items
rust_unreachable ();
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
}
@@ -1227,7 +1268,8 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx,
{
switch (elem->get_item_type ())
{
- case HIR::StructPatternField::ItemType::IDENT: {
+ case HIR::StructPatternField::ItemType::IDENT:
+ {
HIR::StructPatternFieldIdent *ident
= static_cast<HIR::StructPatternFieldIdent *> (elem.get ());
int field_idx
@@ -1236,7 +1278,8 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx,
= DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::StructPatternField::ItemType::IDENT_PAT: {
+ case HIR::StructPatternField::ItemType::IDENT_PAT:
+ {
HIR::StructPatternFieldIdentPat *ident_pat
= static_cast<HIR::StructPatternFieldIdentPat *> (elem.get ());
int field_idx
@@ -1246,12 +1289,14 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx,
variant->get_fields ().at (field_idx)->get_field_type ());
}
break;
- case HIR::StructPatternField::ItemType::TUPLE_PAT: {
+ case HIR::StructPatternField::ItemType::TUPLE_PAT:
+ {
// TODO: tuple: pat
rust_unreachable ();
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
}
@@ -1268,11 +1313,13 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern,
switch (pat_type)
{
case HIR::Pattern::PatternType::WILDCARD:
- case HIR::Pattern::PatternType::IDENTIFIER: {
+ case HIR::Pattern::PatternType::IDENTIFIER:
+ {
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::PATH: {
+ case HIR::Pattern::PatternType::PATH:
+ {
// TODO: support constants, associated constants, enum variants and
// structs
// https://doc.rust-lang.org/reference/patterns.html#path-patterns
@@ -1280,13 +1327,15 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern,
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::REFERENCE: {
+ case HIR::Pattern::PatternType::REFERENCE:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
case HIR::Pattern::PatternType::STRUCT:
- case HIR::Pattern::PatternType::TUPLE_STRUCT: {
+ case HIR::Pattern::PatternType::TUPLE_STRUCT:
+ {
HirId path_id = UNKNOWN_HIRID;
if (pat_type == HIR::Pattern::PatternType::STRUCT)
{
@@ -1343,37 +1392,44 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern,
}
}
break;
- case HIR::Pattern::PatternType::TUPLE: {
+ case HIR::Pattern::PatternType::TUPLE:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::SLICE: {
+ case HIR::Pattern::PatternType::SLICE:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::ALT: {
+ case HIR::Pattern::PatternType::ALT:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::LITERAL: {
+ case HIR::Pattern::PatternType::LITERAL:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::RANGE: {
+ case HIR::Pattern::PatternType::RANGE:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::GROUPED: {
+ case HIR::Pattern::PatternType::GROUPED:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
}
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
index 6d60ced..dd44abc 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
@@ -33,9 +33,9 @@ namespace Analysis {
using namespace HIR;
-void
-check_match_usefulness (Resolver::TypeCheckContext *ctx,
- TyTy::BaseType *scrutinee_ty, HIR::MatchExpr &expr);
+void check_match_usefulness (Resolver::TypeCheckContext *ctx,
+ TyTy::BaseType *scrutinee_ty,
+ HIR::MatchExpr &expr);
class PatternChecker : public HIR::HIRFullVisitor
{
@@ -86,6 +86,8 @@ private:
virtual void visit (MethodCallExpr &expr) override;
virtual void visit (FieldAccessExpr &expr) override;
virtual void visit (BlockExpr &expr) override;
+ virtual void visit (AnonConst &expr) override;
+ virtual void visit (ConstBlock &expr) override;
virtual void visit (ClosureExpr &expr) override;
virtual void visit (ContinueExpr &expr) override;
virtual void visit (BreakExpr &expr) override;
@@ -107,6 +109,7 @@ private:
virtual void visit (AsyncBlockExpr &expr) override;
virtual void visit (InlineAsm &expr) override;
virtual void visit (LlvmInlineAsm &expr) override;
+ virtual void visit (OffsetOf &expr) override;
virtual void visit (TypeParam &param) override;
virtual void visit (ConstGenericParam &param) override;
virtual void visit (LifetimeWhereClauseItem &item) override;
diff --git a/gcc/rust/checks/errors/rust-readonly-check2.cc b/gcc/rust/checks/errors/rust-readonly-check2.cc
new file mode 100644
index 0000000..2fa92ae
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-readonly-check2.cc
@@ -0,0 +1,253 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-readonly-check2.h"
+#include "rust-hir-expr.h"
+#include "rust-hir-node.h"
+#include "rust-hir-path.h"
+#include "rust-hir-map.h"
+#include "rust-hir-pattern.h"
+#include "rust-mapping-common.h"
+#include "rust-system.h"
+#include "rust-immutable-name-resolution-context.h"
+#include "rust-tyty.h"
+
+namespace Rust {
+namespace HIR {
+
+static std::set<HirId> already_assigned_variables = {};
+
+ReadonlyChecker::ReadonlyChecker ()
+ : resolver (*Resolver::Resolver::get ()),
+ mappings (Analysis::Mappings::get ()),
+ context (*Resolver::TypeCheckContext::get ())
+{}
+
+void
+ReadonlyChecker::go (Crate &crate)
+{
+ for (auto &item : crate.get_items ())
+ item->accept_vis (*this);
+}
+
+void
+ReadonlyChecker::visit (AssignmentExpr &expr)
+{
+ Expr &lhs = expr.get_lhs ();
+ mutable_context.enter (expr.get_mappings ().get_hirid ());
+ lhs.accept_vis (*this);
+ mutable_context.exit ();
+}
+
+void
+ReadonlyChecker::visit (PathInExpression &expr)
+{
+ if (!mutable_context.is_in_context ())
+ return;
+
+ NodeId ast_node_id = expr.get_mappings ().get_nodeid ();
+ NodeId def_id;
+
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ if (auto id = nr_ctx.lookup (ast_node_id))
+ def_id = *id;
+ else
+ return;
+
+ auto hir_id = mappings.lookup_node_to_hir (def_id);
+ if (!hir_id)
+ return;
+
+ // Check if the local variable is mutable.
+ auto maybe_pattern = mappings.lookup_hir_pattern (*hir_id);
+ if (maybe_pattern
+ && maybe_pattern.value ()->get_pattern_type ()
+ == HIR::Pattern::PatternType::IDENTIFIER)
+ check_variable (static_cast<IdentifierPattern *> (maybe_pattern.value ()),
+ expr.get_locus ());
+
+ // Check if the static item is mutable.
+ auto maybe_item = mappings.lookup_hir_item (*hir_id);
+ if (maybe_item
+ && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Static)
+ {
+ auto static_item = static_cast<HIR::StaticItem *> (*maybe_item);
+ if (!static_item->is_mut ())
+ rust_error_at (expr.get_locus (),
+ "assignment of read-only location '%s'",
+ static_item->get_identifier ().as_string ().c_str ());
+ }
+
+ // Check if the constant item is mutable.
+ if (maybe_item
+ && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant)
+ {
+ auto const_item = static_cast<HIR::ConstantItem *> (*maybe_item);
+ rust_error_at (expr.get_locus (), "assignment of read-only location '%s'",
+ const_item->get_identifier ().as_string ().c_str ());
+ }
+}
+
+void
+ReadonlyChecker::check_variable (IdentifierPattern *pattern,
+ location_t assigned_loc)
+{
+ if (!mutable_context.is_in_context ())
+ return;
+ if (pattern->is_mut ())
+ return;
+
+ auto hir_id = pattern->get_mappings ().get_hirid ();
+ if (already_assigned_variables.count (hir_id) > 0)
+ rust_error_at (assigned_loc, "assignment of read-only variable '%s'",
+ pattern->as_string ().c_str ());
+ already_assigned_variables.insert (hir_id);
+}
+
+void
+ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern,
+ bool has_init_expr)
+{
+ if (has_init_expr)
+ {
+ HirId pattern_id = pattern.get_mappings ().get_hirid ();
+ already_assigned_variables.insert (pattern_id);
+ }
+}
+
+void
+ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern,
+ bool has_init_expr)
+{
+ switch (tuple_pattern.get_items ().get_item_type ())
+ {
+ case HIR::TuplePatternItems::ItemType::MULTIPLE:
+ {
+ auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
+ tuple_pattern.get_items ());
+ for (auto &sub : items.get_patterns ())
+ {
+ collect_assignment (*sub, has_init_expr);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void
+ReadonlyChecker::collect_assignment (Pattern &pattern, bool has_init_expr)
+{
+ switch (pattern.get_pattern_type ())
+ {
+ case HIR::Pattern::PatternType::IDENTIFIER:
+ {
+ collect_assignment_identifier (static_cast<IdentifierPattern &> (
+ pattern),
+ has_init_expr);
+ }
+ break;
+ case HIR::Pattern::PatternType::TUPLE:
+ {
+ auto &tuple_pattern = static_cast<HIR::TuplePattern &> (pattern);
+ collect_assignment_tuple (tuple_pattern, has_init_expr);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void
+ReadonlyChecker::visit (LetStmt &stmt)
+{
+ HIR::Pattern &pattern = stmt.get_pattern ();
+ collect_assignment (pattern, stmt.has_init_expr ());
+}
+
+void
+ReadonlyChecker::visit (FieldAccessExpr &expr)
+{
+ if (mutable_context.is_in_context ())
+ {
+ expr.get_receiver_expr ().accept_vis (*this);
+ }
+}
+
+void
+ReadonlyChecker::visit (TupleIndexExpr &expr)
+{
+ if (mutable_context.is_in_context ())
+ {
+ expr.get_tuple_expr ().accept_vis (*this);
+ }
+}
+
+void
+ReadonlyChecker::visit (ArrayIndexExpr &expr)
+{
+ if (mutable_context.is_in_context ())
+ {
+ expr.get_array_expr ().accept_vis (*this);
+ }
+}
+
+void
+ReadonlyChecker::visit (TupleExpr &expr)
+{
+ if (mutable_context.is_in_context ())
+ {
+ // TODO: Add check for tuple expression
+ }
+}
+
+void
+ReadonlyChecker::visit (LiteralExpr &expr)
+{
+ if (mutable_context.is_in_context ())
+ {
+ rust_error_at (expr.get_locus (), "assignment of read-only location");
+ }
+}
+
+void
+ReadonlyChecker::visit (DereferenceExpr &expr)
+{
+ if (!mutable_context.is_in_context ())
+ return;
+ TyTy::BaseType *to_deref_type;
+ auto to_deref = expr.get_expr ().get_mappings ().get_hirid ();
+ if (!context.lookup_type (to_deref, &to_deref_type))
+ return;
+ if (to_deref_type->get_kind () == TyTy::TypeKind::REF)
+ {
+ auto ref_type = static_cast<TyTy::ReferenceType *> (to_deref_type);
+ if (!ref_type->is_mutable ())
+ rust_error_at (expr.get_locus (), "assignment of read-only location");
+ }
+ if (to_deref_type->get_kind () == TyTy::TypeKind::POINTER)
+ {
+ auto ptr_type = static_cast<TyTy::PointerType *> (to_deref_type);
+ if (!ptr_type->is_mutable ())
+ rust_error_at (expr.get_locus (), "assignment of read-only location");
+ }
+}
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/checks/errors/rust-readonly-check2.h b/gcc/rust/checks/errors/rust-readonly-check2.h
new file mode 100644
index 0000000..06af9db
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-readonly-check2.h
@@ -0,0 +1,67 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-visitor.h"
+#include "rust-name-resolver.h"
+#include "rust-stacked-contexts.h"
+#include "rust-hir-type-check.h"
+
+namespace Rust {
+namespace HIR {
+class ReadonlyChecker : public DefaultHIRVisitor
+{
+public:
+ ReadonlyChecker ();
+
+ void go (HIR::Crate &crate);
+
+private:
+ enum class lvalue_use
+ {
+ assign,
+ increment,
+ decrement,
+ };
+
+ Resolver::Resolver &resolver;
+ Analysis::Mappings &mappings;
+ Resolver::TypeCheckContext &context;
+ StackedContexts<HirId> mutable_context;
+
+ using DefaultHIRVisitor::visit;
+
+ virtual void visit (AssignmentExpr &expr) override;
+ virtual void visit (PathInExpression &expr) override;
+ virtual void visit (FieldAccessExpr &expr) override;
+ virtual void visit (ArrayIndexExpr &expr) override;
+ virtual void visit (TupleExpr &expr) override;
+ virtual void visit (TupleIndexExpr &expr) override;
+ virtual void visit (LetStmt &stmt) override;
+ virtual void visit (LiteralExpr &expr) override;
+ virtual void visit (DereferenceExpr &expr) override;
+
+ void collect_assignment (Pattern &pattern, bool has_init_expr);
+ void collect_assignment_identifier (IdentifierPattern &pattern,
+ bool has_init_expr);
+ void collect_assignment_tuple (TuplePattern &pattern, bool has_init_expr);
+
+ void check_variable (IdentifierPattern *pattern, location_t assigned_loc);
+};
+
+} // namespace HIR
+} // namespace Rust \ 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 46eef11..405c59b 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -540,6 +540,18 @@ UnsafeChecker::visit (BlockExpr &expr)
}
void
+UnsafeChecker::visit (AnonConst &expr)
+{
+ expr.get_inner_expr ().accept_vis (*this);
+}
+
+void
+UnsafeChecker::visit (ConstBlock &expr)
+{
+ expr.get_const_expr ().accept_vis (*this);
+}
+
+void
UnsafeChecker::visit (ContinueExpr &)
{}
@@ -682,6 +694,12 @@ UnsafeChecker::visit (LlvmInlineAsm &expr)
}
void
+UnsafeChecker::visit (OffsetOf &expr)
+{
+ // nothing to do, offset_of!() is safe
+}
+
+void
UnsafeChecker::visit (TypeParam &)
{}
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h
index 9a8fb7c..dc3b482 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.h
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.h
@@ -95,6 +95,8 @@ private:
virtual void visit (FieldAccessExpr &expr) override;
virtual void visit (ClosureExpr &expr) override;
virtual void visit (BlockExpr &expr) override;
+ virtual void visit (AnonConst &expr) override;
+ virtual void visit (ConstBlock &expr) override;
virtual void visit (ContinueExpr &expr) override;
virtual void visit (BreakExpr &expr) override;
virtual void visit (RangeFromToExpr &expr) override;
@@ -115,6 +117,7 @@ private:
virtual void visit (AsyncBlockExpr &expr) override;
virtual void visit (InlineAsm &expr) override;
virtual void visit (LlvmInlineAsm &expr) override;
+ virtual void visit (OffsetOf &expr) override;
virtual void visit (TypeParam &param) override;
virtual void visit (ConstGenericParam &param) override;
virtual void visit (LifetimeWhereClauseItem &item) override;
diff --git a/gcc/rust/checks/lints/rust-lint-unused-var.cc b/gcc/rust/checks/lints/rust-lint-unused-var.cc
index 896eeb0..08596f1 100644
--- a/gcc/rust/checks/lints/rust-lint-unused-var.cc
+++ b/gcc/rust/checks/lints/rust-lint-unused-var.cc
@@ -31,6 +31,7 @@ check_decl (tree *t)
tree var_name = DECL_NAME (*t);
const char *var_name_ptr = IDENTIFIER_POINTER (var_name);
bool starts_with_under_score = strncmp (var_name_ptr, "_", 1) == 0;
+ bool is_self = strcmp (var_name_ptr, "self") == 0;
bool is_constant = TREE_CODE (*t) == CONST_DECL;
// if (!is_constant)
@@ -43,7 +44,8 @@ check_decl (tree *t)
// starts_with_under_score ? "true" : "false", var_name_ptr);
// }
- if (!TREE_USED (*t) && !DECL_ARTIFICIAL (*t) && !starts_with_under_score)
+ if (!TREE_USED (*t) && !DECL_ARTIFICIAL (*t) && !starts_with_under_score
+ && !is_self)
{
warning_at (DECL_SOURCE_LOCATION (*t),
is_constant ? OPT_Wunused_const_variable_
diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc
index a8c3ca5..58d8071 100644
--- a/gcc/rust/expand/rust-cfg-strip.cc
+++ b/gcc/rust/expand/rust-cfg-strip.cc
@@ -289,7 +289,8 @@ CfgStrip::maybe_strip_generic_args (AST::GenericArgs &args)
{
switch (arg.get_kind ())
{
- case AST::GenericArg::Kind::Type: {
+ case AST::GenericArg::Kind::Type:
+ {
auto &type = arg.get_type ();
type.accept_vis (*this);
@@ -298,7 +299,8 @@ CfgStrip::maybe_strip_generic_args (AST::GenericArgs &args)
"cannot strip type in this position");
break;
}
- case AST::GenericArg::Kind::Const: {
+ case AST::GenericArg::Kind::Const:
+ {
auto &expr = arg.get_expression ();
expr.accept_vis (*this);
@@ -1190,7 +1192,7 @@ CfgStrip::visit (AST::ClosureExprInnerTyped &expr)
rust_error_at (type.get_locus (), "cannot strip type in this position");
// can't strip expression itself, but can strip sub-expressions
- auto &definition_block = expr.get_definition_block ();
+ auto &definition_block = expr.get_definition_expr ();
definition_block.accept_vis (*this);
if (definition_block.is_marked_for_strip ())
rust_error_at (definition_block.get_locus (),
@@ -1763,16 +1765,17 @@ CfgStrip::visit (AST::Module &module)
return;
}
- // A loaded module might have inner attributes
- if (module.get_kind () == AST::Module::ModuleKind::LOADED)
+ if (module.get_kind () == AST::Module::UNLOADED)
{
- // strip test based on inner attrs
- expand_cfg_attrs (module.get_inner_attrs ());
- if (fails_cfg_with_expand (module.get_inner_attrs ()))
- {
- module.mark_for_strip ();
- return;
- }
+ module.load_items ();
+ }
+
+ // strip test based on inner attrs
+ expand_cfg_attrs (module.get_inner_attrs ());
+ if (fails_cfg_with_expand (module.get_inner_attrs ()))
+ {
+ module.mark_for_strip ();
+ return;
}
// strip items if required
@@ -2260,12 +2263,12 @@ void
CfgStrip::visit (AST::IdentifierPattern &pattern)
{
// can only strip sub-patterns of the inner pattern to bind
- if (!pattern.has_pattern_to_bind ())
+ if (!pattern.has_subpattern ())
return;
AST::DefaultASTVisitor::visit (pattern);
- auto &sub_pattern = pattern.get_pattern_to_bind ();
+ auto &sub_pattern = pattern.get_subpattern ();
if (sub_pattern.is_marked_for_strip ())
rust_error_at (sub_pattern.get_locus (),
"cannot strip pattern in this position");
@@ -2475,20 +2478,44 @@ CfgStrip::visit (AST::GroupedPattern &pattern)
}
void
-CfgStrip::visit (AST::SlicePattern &pattern)
+CfgStrip::visit (AST::SlicePatternItemsNoRest &items)
{
- AST::DefaultASTVisitor::visit (pattern);
+ AST::DefaultASTVisitor::visit (items);
// can't strip individual patterns, only sub-patterns
- for (auto &item : pattern.get_items ())
+ for (auto &pattern : items.get_patterns ())
{
- if (item->is_marked_for_strip ())
- rust_error_at (item->get_locus (),
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus (),
"cannot strip pattern in this position");
- // TODO: quit stripping now? or keep going?
}
}
void
+CfgStrip::visit (AST::SlicePatternItemsHasRest &items)
+{
+ AST::DefaultASTVisitor::visit (items);
+ // can't strip individual patterns, only sub-patterns
+ for (auto &pattern : items.get_lower_patterns ())
+ {
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus (),
+ "cannot strip pattern in this position");
+ }
+ for (auto &pattern : items.get_upper_patterns ())
+ {
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus (),
+ "cannot strip pattern in this position");
+ }
+}
+
+void
+CfgStrip::visit (AST::SlicePattern &pattern)
+{
+ AST::DefaultASTVisitor::visit (pattern);
+}
+
+void
CfgStrip::visit (AST::AltPattern &pattern)
{
AST::DefaultASTVisitor::visit (pattern);
diff --git a/gcc/rust/expand/rust-cfg-strip.h b/gcc/rust/expand/rust-cfg-strip.h
index 4900ae8..767cf28 100644
--- a/gcc/rust/expand/rust-cfg-strip.h
+++ b/gcc/rust/expand/rust-cfg-strip.h
@@ -172,6 +172,8 @@ public:
void visit (AST::TuplePatternItemsMultiple &tuple_items) override;
void visit (AST::TuplePatternItemsRanged &tuple_items) override;
void visit (AST::GroupedPattern &pattern) override;
+ void visit (AST::SlicePatternItemsNoRest &items) override;
+ void visit (AST::SlicePatternItemsHasRest &items) override;
void visit (AST::SlicePattern &pattern) override;
void visit (AST::AltPattern &pattern) override;
diff --git a/gcc/rust/expand/rust-derive-clone.h b/gcc/rust/expand/rust-derive-clone.h
index 61224ba..a3320c7 100644
--- a/gcc/rust/expand/rust-derive-clone.h
+++ b/gcc/rust/expand/rust-derive-clone.h
@@ -29,7 +29,7 @@ class DeriveClone : DeriveVisitor
public:
DeriveClone (location_t loc);
- std::unique_ptr<AST::Item> go (Item &item);
+ std::unique_ptr<Item> go (Item &item);
private:
std::unique_ptr<Item> expanded;
@@ -80,10 +80,10 @@ private:
MatchCase clone_enum_struct (PathInExpression variant_path,
const EnumItemStruct &variant);
- virtual void visit_struct (StructStruct &item);
- virtual void visit_tuple (TupleStruct &item);
- virtual void visit_enum (Enum &item);
- virtual void visit_union (Union &item);
+ virtual void visit_struct (StructStruct &item) override;
+ virtual void visit_tuple (TupleStruct &item) override;
+ virtual void visit_enum (Enum &item) override;
+ virtual void visit_union (Union &item) override;
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-derive-cmp-common.cc b/gcc/rust/expand/rust-derive-cmp-common.cc
new file mode 100644
index 0000000..22ca16f
--- /dev/null
+++ b/gcc/rust/expand/rust-derive-cmp-common.cc
@@ -0,0 +1,191 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-derive-cmp-common.h"
+#include "rust-ast-builder.h"
+#include "rust-item.h"
+
+namespace Rust {
+namespace AST {
+
+SelfOther
+SelfOther::index (Builder builder, int idx)
+{
+ return SelfOther{
+ builder.tuple_idx ("self", idx),
+ builder.tuple_idx ("other", idx),
+ };
+}
+
+std::vector<SelfOther>
+SelfOther::indexes (Builder builder, const std::vector<TupleField> &fields)
+{
+ std::vector<SelfOther> vec;
+
+ for (size_t i = 0; i < fields.size (); i++)
+ vec.emplace_back (SelfOther::index (builder, i));
+
+ return vec;
+}
+
+SelfOther
+SelfOther::field (Builder builder, const std::string &field_name)
+{
+ return SelfOther{
+ builder.field_access (builder.identifier ("self"), field_name),
+ builder.field_access (builder.identifier ("other"), field_name),
+ };
+}
+
+std::vector<SelfOther>
+SelfOther::fields (Builder builder, const std::vector<StructField> &fields)
+{
+ std::vector<SelfOther> vec;
+
+ for (const auto &field : fields)
+ vec.emplace_back (
+ SelfOther::field (builder, field.get_field_name ().as_string ()));
+
+ return vec;
+}
+
+MatchCase
+EnumMatchBuilder::tuple (EnumItem &variant_raw)
+{
+ auto &variant = static_cast<EnumItemTuple &> (variant_raw);
+
+ auto self_patterns = std::vector<std::unique_ptr<Pattern>> ();
+ auto other_patterns = std::vector<std::unique_ptr<Pattern>> ();
+
+ auto self_other_exprs = std::vector<SelfOther> ();
+
+ for (size_t i = 0; i < variant.get_tuple_fields ().size (); i++)
+ {
+ // The patterns we're creating for each field are `self_<i>` and
+ // `other_<i>` where `i` is the index of the field. It doesn't actually
+ // matter what we use, as long as it's ordered, unique, and that we can
+ // reuse it in the match case's return expression to check that they are
+ // equal.
+
+ auto self_pattern_str = "__self_" + std::to_string (i);
+ auto other_pattern_str = "__other_" + std::to_string (i);
+
+ self_patterns.emplace_back (
+ builder.identifier_pattern (self_pattern_str));
+ other_patterns.emplace_back (
+ builder.identifier_pattern (other_pattern_str));
+
+ self_other_exprs.emplace_back (SelfOther{
+ builder.identifier (self_pattern_str),
+ builder.identifier (other_pattern_str),
+ });
+ }
+
+ // TODO: Replace with `reconstruct()` instead of building these twice
+ auto self_variant_path = builder.variant_path (enum_path, variant_path);
+ auto other_variant_path = builder.variant_path (enum_path, variant_path);
+
+ auto self_pattern_items = std::unique_ptr<TupleStructItems> (
+ new TupleStructItemsNoRange (std::move (self_patterns)));
+ auto other_pattern_items = std::unique_ptr<TupleStructItems> (
+ new TupleStructItemsNoRange (std::move (other_patterns)));
+
+ auto self_pattern = std::unique_ptr<Pattern> (
+ new ReferencePattern (std::unique_ptr<Pattern> (new TupleStructPattern (
+ self_variant_path, std::move (self_pattern_items))),
+ false, false, builder.loc));
+ auto other_pattern = std::unique_ptr<Pattern> (new ReferencePattern (
+ std::unique_ptr<Pattern> (new TupleStructPattern (
+ other_variant_path, std::move (other_pattern_items))),
+ false, false, builder.loc));
+
+ auto tuple_items = std::make_unique<TuplePatternItemsMultiple> (
+ vec (std::move (self_pattern), std::move (other_pattern)));
+
+ auto pattern
+ = std::make_unique<TuplePattern> (std::move (tuple_items), builder.loc);
+
+ auto expr = fn (std::move (self_other_exprs));
+
+ return builder.match_case (std::move (pattern), std::move (expr));
+}
+
+MatchCase
+EnumMatchBuilder::strukt (EnumItem &variant_raw)
+{
+ auto &variant = static_cast<EnumItemStruct &> (variant_raw);
+
+ auto self_fields = std::vector<std::unique_ptr<StructPatternField>> ();
+ auto other_fields = std::vector<std::unique_ptr<StructPatternField>> ();
+
+ auto self_other_exprs = std::vector<SelfOther> ();
+
+ for (auto &field : variant.get_struct_fields ())
+ {
+ // The patterns we're creating for each field are `self_<field>` and
+ // `other_<field>` where `field` is the name of the field. It doesn't
+ // actually matter what we use, as long as it's ordered, unique, and that
+ // we can reuse it in the match case's return expression to check that
+ // they are equal.
+
+ auto field_name = field.get_field_name ().as_string ();
+
+ auto self_pattern_str = "__self_" + field_name;
+ auto other_pattern_str = "__other_" + field_name;
+
+ self_fields.emplace_back (builder.struct_pattern_ident_pattern (
+ field_name, builder.identifier_pattern (self_pattern_str)));
+ other_fields.emplace_back (builder.struct_pattern_ident_pattern (
+ field_name, builder.identifier_pattern (other_pattern_str)));
+
+ self_other_exprs.emplace_back (SelfOther{
+ builder.identifier (self_pattern_str),
+ builder.identifier (other_pattern_str),
+ });
+ }
+
+ // TODO: Replace with `reconstruct()` instead of building these twice
+ auto self_variant_path = builder.variant_path (enum_path, variant_path);
+ auto other_variant_path = builder.variant_path (enum_path, variant_path);
+
+ auto self_elts = StructPatternElements (std::move (self_fields));
+ auto other_elts = StructPatternElements (std::move (other_fields));
+
+ auto self_pattern = std::unique_ptr<Pattern> (new ReferencePattern (
+ std::unique_ptr<Pattern> (new StructPattern (self_variant_path, builder.loc,
+ std::move (self_elts))),
+ false, false, builder.loc));
+ auto other_pattern = std::unique_ptr<Pattern> (
+ new ReferencePattern (std::unique_ptr<Pattern> (
+ new StructPattern (other_variant_path, builder.loc,
+ std::move (other_elts))),
+ false, false, builder.loc));
+
+ auto tuple_items = std::make_unique<TuplePatternItemsMultiple> (
+ vec (std::move (self_pattern), std::move (other_pattern)));
+
+ auto pattern
+ = std::make_unique<TuplePattern> (std::move (tuple_items), builder.loc);
+
+ auto expr = fn (std::move (self_other_exprs));
+
+ return builder.match_case (std::move (pattern), std::move (expr));
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-derive-cmp-common.h b/gcc/rust/expand/rust-derive-cmp-common.h
new file mode 100644
index 0000000..4efbed8
--- /dev/null
+++ b/gcc/rust/expand/rust-derive-cmp-common.h
@@ -0,0 +1,99 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_DERIVE_CMP_COMMON_H
+#define RUST_DERIVE_CMP_COMMON_H
+
+#include "rust-ast.h"
+#include "rust-ast-builder.h"
+#include "rust-item.h"
+#include "rust-path.h"
+
+namespace Rust {
+namespace AST {
+
+/**
+ * A pair of two expressions from each instance being compared. E.g. this
+ * could be `self.0` and `other.0`, or `self.field` and `other.field`
+ */
+struct SelfOther
+{
+ std::unique_ptr<Expr> self_expr;
+ std::unique_ptr<Expr> other_expr;
+
+ /* Create a <self.i> and an <other.i> expression */
+ static SelfOther index (Builder builder, int idx);
+ static std::vector<SelfOther> indexes (Builder builder,
+ const std::vector<TupleField> &fields);
+
+ /* Create a <self.field> and an <other.field> expression */
+ static SelfOther field (Builder builder, const std::string &field_name);
+ static std::vector<SelfOther> fields (Builder builder,
+ const std::vector<StructField> &fields);
+};
+
+/**
+ * Builder for common match cases used when comparing two enum instances. This
+ * builder takes care of creating the unique patterns for the `self` instance
+ * and `other` instance, as well as the entire `MatchCase` required for building
+ * a proper comparision expression for an implementation of a comparision trait
+ * for an enum type. The functions take a lambda to use when creating the
+ * expression of the generated `MatchCase`.
+ */
+class EnumMatchBuilder
+{
+public:
+ /**
+ * The type of functions to call when creating the resulting expression in the
+ * generated `MatchCase`
+ */
+ using ExprFn
+ = std::function<std::unique_ptr<Expr> (std::vector<SelfOther> &&)>;
+
+ EnumMatchBuilder (const std::string &enum_path,
+ const std::string &variant_path, ExprFn fn,
+ Builder &builder)
+ : enum_path (enum_path), variant_path (variant_path), fn (fn),
+ builder (builder)
+ {}
+
+ /**
+ * Generate a `MatchCase` for an enum tuple variant
+ *
+ * (&Enum::Tuple(self0, self1), &Enum::Tuple(other0, other1)) => <fn>
+ */
+ MatchCase tuple (EnumItem &variant);
+
+ /**
+ * Generate a `MatchCase` for an enum struct variant
+ *
+ * (&Enum::Struct { a: self_a }, &Enum::Struct { a: other_a }) => <fn>
+ */
+ MatchCase strukt (EnumItem &variant);
+
+private:
+ const std::string &enum_path;
+ const std::string &variant_path;
+ ExprFn fn;
+ Builder &builder;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DERIVE_CMP_COMMON_H
diff --git a/gcc/rust/expand/rust-derive-copy.h b/gcc/rust/expand/rust-derive-copy.h
index 71972eb..664a8e0 100644
--- a/gcc/rust/expand/rust-derive-copy.h
+++ b/gcc/rust/expand/rust-derive-copy.h
@@ -44,10 +44,10 @@ private:
copy_impl (std::string name,
const std::vector<std::unique_ptr<GenericParam>> &type_generics);
- virtual void visit_struct (StructStruct &item);
- virtual void visit_tuple (TupleStruct &item);
- virtual void visit_enum (Enum &item);
- virtual void visit_union (Union &item);
+ virtual void visit_struct (StructStruct &item) override;
+ virtual void visit_tuple (TupleStruct &item) override;
+ virtual void visit_enum (Enum &item) override;
+ virtual void visit_union (Union &item) override;
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-derive-default.cc b/gcc/rust/expand/rust-derive-default.cc
index 2e8b456..26ee546 100644
--- a/gcc/rust/expand/rust-derive-default.cc
+++ b/gcc/rust/expand/rust-derive-default.cc
@@ -98,7 +98,8 @@ DeriveDefault::visit_struct (StructStruct &item)
for (auto &field : item.get_fields ())
{
auto name = field.get_field_name ().as_string ();
- auto expr = default_call (field.get_field_type ().clone_type ());
+ auto type = field.get_field_type ().reconstruct ();
+ auto expr = default_call (std::move (type));
cloned_fields.emplace_back (
builder.struct_expr_field (std::move (name), std::move (expr)));
@@ -119,7 +120,7 @@ DeriveDefault::visit_tuple (TupleStruct &tuple_item)
for (auto &field : tuple_item.get_fields ())
{
- auto type = field.get_field_type ().clone_type ();
+ auto type = field.get_field_type ().reconstruct ();
defaulted_fields.emplace_back (default_call (std::move (type)));
}
diff --git a/gcc/rust/expand/rust-derive-eq.cc b/gcc/rust/expand/rust-derive-eq.cc
index 5e7a894..7da137f 100644
--- a/gcc/rust/expand/rust-derive-eq.cc
+++ b/gcc/rust/expand/rust-derive-eq.cc
@@ -142,7 +142,7 @@ DeriveEq::visit_tuple (TupleStruct &item)
auto types = std::vector<std::unique_ptr<Type>> ();
for (auto &field : item.get_fields ())
- types.emplace_back (field.get_field_type ().clone_type ());
+ types.emplace_back (field.get_field_type ().reconstruct ());
expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
item.get_identifier ().as_string (),
@@ -155,7 +155,7 @@ DeriveEq::visit_struct (StructStruct &item)
auto types = std::vector<std::unique_ptr<Type>> ();
for (auto &field : item.get_fields ())
- types.emplace_back (field.get_field_type ().clone_type ());
+ types.emplace_back (field.get_field_type ().reconstruct ());
expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
item.get_identifier ().as_string (),
@@ -175,19 +175,20 @@ DeriveEq::visit_enum (Enum &item)
case EnumItem::Kind::Discriminant:
// nothing to do as they contain no inner types
continue;
- case EnumItem::Kind::Tuple: {
+ case EnumItem::Kind::Tuple:
+ {
auto &tuple = static_cast<EnumItemTuple &> (*variant);
for (auto &field : tuple.get_tuple_fields ())
- types.emplace_back (field.get_field_type ().clone_type ());
-
+ types.emplace_back (field.get_field_type ().reconstruct ());
break;
}
- case EnumItem::Kind::Struct: {
+ case EnumItem::Kind::Struct:
+ {
auto &tuple = static_cast<EnumItemStruct &> (*variant);
for (auto &field : tuple.get_struct_fields ())
- types.emplace_back (field.get_field_type ().clone_type ());
+ types.emplace_back (field.get_field_type ().reconstruct ());
break;
}
@@ -205,7 +206,7 @@ DeriveEq::visit_union (Union &item)
auto types = std::vector<std::unique_ptr<Type>> ();
for (auto &field : item.get_variants ())
- types.emplace_back (field.get_field_type ().clone_type ());
+ types.emplace_back (field.get_field_type ().reconstruct ());
expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
item.get_identifier ().as_string (),
diff --git a/gcc/rust/expand/rust-derive-eq.h b/gcc/rust/expand/rust-derive-eq.h
index 17af526..fb187cc 100644
--- a/gcc/rust/expand/rust-derive-eq.h
+++ b/gcc/rust/expand/rust-derive-eq.h
@@ -31,7 +31,7 @@ class DeriveEq : DeriveVisitor
public:
DeriveEq (location_t loc);
- std::vector<std::unique_ptr<AST::Item>> go (Item &item);
+ std::vector<std::unique_ptr<Item>> go (Item &item);
private:
std::vector<std::unique_ptr<Item>> expanded;
@@ -70,10 +70,10 @@ private:
*/
std::unique_ptr<Stmt> assert_type_is_eq (std::unique_ptr<Type> &&type);
- virtual void visit_struct (StructStruct &item);
- virtual void visit_tuple (TupleStruct &item);
- virtual void visit_enum (Enum &item);
- virtual void visit_union (Union &item);
+ virtual void visit_struct (StructStruct &item) override;
+ virtual void visit_tuple (TupleStruct &item) override;
+ virtual void visit_enum (Enum &item) override;
+ virtual void visit_union (Union &item) override;
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-derive-hash.cc b/gcc/rust/expand/rust-derive-hash.cc
index 0c9b0f7..94aede2 100644
--- a/gcc/rust/expand/rust-derive-hash.cc
+++ b/gcc/rust/expand/rust-derive-hash.cc
@@ -231,14 +231,7 @@ DeriveHash::visit_enum (Enum &item)
auto cases = std::vector<MatchCase> ();
auto type_name = item.get_identifier ().as_string ();
- auto intrinsic = ptrify (
- builder.path_in_expression ({"core", "intrinsics", "discriminant_value"},
- true));
-
- auto let_discr
- = builder.let (builder.identifier_pattern (DeriveHash::discr), nullptr,
- builder.call (std::move (intrinsic),
- builder.identifier ("self")));
+ auto let_discr = builder.discriminant_value (DeriveHash::discr);
auto discr_hash = builder.statementify (
hash_call (builder.ref (builder.identifier (DeriveHash::discr))));
diff --git a/gcc/rust/expand/rust-derive-hash.h b/gcc/rust/expand/rust-derive-hash.h
index 02b0bee..67170d0 100644
--- a/gcc/rust/expand/rust-derive-hash.h
+++ b/gcc/rust/expand/rust-derive-hash.h
@@ -29,7 +29,7 @@ class DeriveHash : DeriveVisitor
public:
DeriveHash (location_t loc);
- std::unique_ptr<AST::Item> go (Item &item);
+ std::unique_ptr<Item> go (Item &item);
private:
std::unique_ptr<Item> expanded;
@@ -49,10 +49,10 @@ private:
MatchCase match_enum_struct (PathInExpression variant_path,
const EnumItemStruct &variant);
- virtual void visit_struct (StructStruct &item);
- virtual void visit_tuple (TupleStruct &item);
- virtual void visit_enum (Enum &item);
- virtual void visit_union (Union &item);
+ virtual void visit_struct (StructStruct &item) override;
+ virtual void visit_tuple (TupleStruct &item) override;
+ virtual void visit_enum (Enum &item) override;
+ virtual void visit_union (Union &item) override;
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc
new file mode 100644
index 0000000..afc4b71
--- /dev/null
+++ b/gcc/rust/expand/rust-derive-ord.cc
@@ -0,0 +1,323 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-derive-ord.h"
+#include "rust-ast.h"
+#include "rust-derive-cmp-common.h"
+#include "rust-derive.h"
+#include "rust-item.h"
+#include "rust-system.h"
+
+namespace Rust {
+namespace AST {
+
+DeriveOrd::DeriveOrd (Ordering ordering, location_t loc)
+ : DeriveVisitor (loc), ordering (ordering)
+{}
+
+std::unique_ptr<Item>
+DeriveOrd::go (Item &item)
+{
+ item.accept_vis (*this);
+
+ return std::move (expanded);
+}
+
+std::unique_ptr<Expr>
+DeriveOrd::cmp_call (std::unique_ptr<Expr> &&self_expr,
+ std::unique_ptr<Expr> &&other_expr)
+{
+ auto cmp_fn_path = builder.path_in_expression (
+ {"core", "cmp", trait (ordering), fn (ordering)}, true);
+
+ return builder.call (ptrify (cmp_fn_path),
+ vec (builder.ref (std::move (self_expr)),
+ builder.ref (std::move (other_expr))));
+}
+
+std::unique_ptr<Item>
+DeriveOrd::cmp_impl (
+ std::unique_ptr<BlockExpr> &&fn_block, Identifier type_name,
+ const std::vector<std::unique_ptr<GenericParam>> &type_generics)
+{
+ auto fn = cmp_fn (std::move (fn_block), type_name);
+
+ auto trait = ordering == Ordering::Partial ? "PartialOrd" : "Ord";
+ auto trait_path = builder.type_path ({"core", "cmp", trait}, true);
+
+ auto trait_bound
+ = builder.trait_bound (builder.type_path ({"core", "cmp", trait}, true));
+
+ auto trait_items = vec (std::move (fn));
+
+ auto cmp_generics
+ = setup_impl_generics (type_name.as_string (), type_generics,
+ std::move (trait_bound));
+
+ return builder.trait_impl (trait_path, std::move (cmp_generics.self_type),
+ std::move (trait_items),
+ std::move (cmp_generics.impl));
+}
+
+std::unique_ptr<AssociatedItem>
+DeriveOrd::cmp_fn (std::unique_ptr<BlockExpr> &&block, Identifier type_name)
+{
+ // Ordering
+ auto return_type = builder.type_path ({"core", "cmp", "Ordering"}, true);
+
+ // In the case of PartialOrd, we return an Option<Ordering>
+ if (ordering == Ordering::Partial)
+ {
+ auto generic = GenericArg::create_type (ptrify (return_type));
+
+ auto generic_seg = builder.type_path_segment_generic (
+ "Option", GenericArgs ({}, {generic}, {}, loc));
+ auto core = builder.type_path_segment ("core");
+ auto option = builder.type_path_segment ("option");
+
+ return_type
+ = builder.type_path (vec (std::move (core), std::move (option),
+ std::move (generic_seg)),
+ true);
+ }
+
+ // &self, other: &Self
+ auto params = vec (
+ builder.self_ref_param (),
+ builder.function_param (builder.identifier_pattern ("other"),
+ builder.reference_type (ptrify (
+ builder.type_path (type_name.as_string ())))));
+
+ auto function_name = fn (ordering);
+
+ return builder.function (function_name, std::move (params),
+ ptrify (return_type), std::move (block));
+}
+
+std::unique_ptr<Pattern>
+DeriveOrd::make_equal ()
+{
+ std::unique_ptr<Pattern> equal = ptrify (
+ builder.path_in_expression ({"core", "cmp", "Ordering", "Equal"}, true));
+
+ // We need to wrap the pattern in Option::Some if we are doing partial
+ // ordering
+ if (ordering == Ordering::Partial)
+ {
+ auto pattern_items = std::unique_ptr<TupleStructItems> (
+ new TupleStructItemsNoRange (vec (std::move (equal))));
+
+ equal
+ = std::make_unique<TupleStructPattern> (builder.path_in_expression (
+ LangItem::Kind::OPTION_SOME),
+ std::move (pattern_items));
+ }
+
+ return equal;
+}
+
+std::pair<MatchArm, MatchArm>
+DeriveOrd::make_cmp_arms ()
+{
+ // All comparison results other than Ordering::Equal
+ auto non_equal = builder.identifier_pattern (DeriveOrd::not_equal);
+ auto equal = make_equal ();
+
+ return {builder.match_arm (std::move (equal)),
+ builder.match_arm (std::move (non_equal))};
+}
+
+std::unique_ptr<Expr>
+DeriveOrd::recursive_match (std::vector<SelfOther> &&members)
+{
+ if (members.empty ())
+ {
+ std::unique_ptr<Expr> value = ptrify (
+ builder.path_in_expression ({"core", "cmp", "Ordering", "Equal"},
+ true));
+
+ if (ordering == Ordering::Partial)
+ value = builder.call (ptrify (builder.path_in_expression (
+ LangItem::Kind::OPTION_SOME)),
+ std::move (value));
+
+ return value;
+ }
+
+ std::unique_ptr<Expr> final_expr = nullptr;
+
+ for (auto it = members.rbegin (); it != members.rend (); it++)
+ {
+ auto &member = *it;
+
+ auto call = cmp_call (std::move (member.self_expr),
+ std::move (member.other_expr));
+
+ // For the last member (so the first iterator), we just create a call
+ // expression
+ if (it == members.rbegin ())
+ {
+ final_expr = std::move (call);
+ continue;
+ }
+
+ // If we aren't dealing with the last member, then we need to wrap all of
+ // that in a big match expression and keep going
+ auto match_arms = make_cmp_arms ();
+
+ auto match_cases
+ = {builder.match_case (std::move (match_arms.first),
+ std::move (final_expr)),
+ builder.match_case (std::move (match_arms.second),
+ builder.identifier (DeriveOrd::not_equal))};
+
+ final_expr = builder.match (std::move (call), std::move (match_cases));
+ }
+
+ return final_expr;
+}
+
+// we need to do a recursive match expression for all of the fields used in a
+// struct so for something like struct Foo { a: i32, b: i32, c: i32 } we must
+// first compare each `a` field, then `b`, then `c`, like this:
+//
+// match cmp_fn(self.<field>, other.<field>) {
+// Ordering::Equal => <recurse>,
+// cmp => cmp,
+// }
+//
+// and the recurse will be the exact same expression, on the next field. so that
+// our result looks like this:
+//
+// match cmp_fn(self.a, other.a) {
+// Ordering::Equal => match cmp_fn(self.b, other.b) {
+// Ordering::Equal =>cmp_fn(self.c, other.c),
+// cmp => cmp,
+// }
+// cmp => cmp,
+// }
+//
+// the last field comparison needs not to be a match but just the function call.
+// this is going to be annoying lol
+void
+DeriveOrd::visit_struct (StructStruct &item)
+{
+ auto fields = SelfOther::fields (builder, item.get_fields ());
+
+ auto match_expr = recursive_match (std::move (fields));
+
+ expanded = cmp_impl (builder.block (std::move (match_expr)),
+ item.get_identifier (), item.get_generic_params ());
+}
+
+// same as structs, but for each field index instead of each field name -
+// straightforward once we have `visit_struct` working
+void
+DeriveOrd::visit_tuple (TupleStruct &item)
+{
+ auto fields = SelfOther::indexes (builder, item.get_fields ());
+
+ auto match_expr = recursive_match (std::move (fields));
+
+ expanded = cmp_impl (builder.block (std::move (match_expr)),
+ item.get_identifier (), item.get_generic_params ());
+}
+
+// for enums, we need to generate a match for each of the enum's variant that
+// contains data and then do the same thing as visit_struct or visit_enum. if
+// the two aren't the same variant, then compare the two discriminant values for
+// all the dataless enum variants and in the general case.
+//
+// so for enum Foo { A(i32, i32), B, C } we need to do the following
+//
+// match (self, other) {
+// (A(self_0, self_1), A(other_0, other_1)) => {
+// match cmp_fn(self_0, other_0) {
+// Ordering::Equal => cmp_fn(self_1, other_1),
+// cmp => cmp,
+// },
+// _ => cmp_fn(discr_value(self), discr_value(other))
+// }
+void
+DeriveOrd::visit_enum (Enum &item)
+{
+ // NOTE: We can factor this even further with DerivePartialEq, but this is
+ // getting out of scope for this PR surely
+
+ auto cases = std::vector<MatchCase> ();
+ auto type_name = item.get_identifier ().as_string ();
+
+ auto let_sd = builder.discriminant_value (DeriveOrd::self_discr, "self");
+ auto let_od = builder.discriminant_value (DeriveOrd::other_discr, "other");
+
+ auto discr_cmp = cmp_call (builder.identifier (DeriveOrd::self_discr),
+ builder.identifier (DeriveOrd::other_discr));
+
+ auto recursive_match_fn = [this] (std::vector<SelfOther> &&fields) {
+ return recursive_match (std::move (fields));
+ };
+
+ for (auto &variant : item.get_variants ())
+ {
+ auto enum_builder
+ = EnumMatchBuilder (type_name, variant->get_identifier ().as_string (),
+ recursive_match_fn, builder);
+
+ switch (variant->get_enum_item_kind ())
+ {
+ case EnumItem::Kind::Struct:
+ cases.emplace_back (enum_builder.strukt (*variant));
+ break;
+ case EnumItem::Kind::Tuple:
+ cases.emplace_back (enum_builder.tuple (*variant));
+ break;
+ case EnumItem::Kind::Identifier:
+ case EnumItem::Kind::Discriminant:
+ // We don't need to do anything for these, as they are handled by the
+ // discriminant value comparison
+ break;
+ }
+ }
+
+ // Add the last case which compares the discriminant values in case `self` and
+ // `other` are actually different variants of the enum
+ cases.emplace_back (
+ builder.match_case (builder.wildcard (), std::move (discr_cmp)));
+
+ auto match
+ = builder.match (builder.tuple (vec (builder.identifier ("self"),
+ builder.identifier ("other"))),
+ std::move (cases));
+
+ expanded
+ = cmp_impl (builder.block (vec (std::move (let_sd), std::move (let_od)),
+ std::move (match)),
+ type_name, item.get_generic_params ());
+}
+
+void
+DeriveOrd::visit_union (Union &item)
+{
+ auto trait_name = trait (ordering);
+
+ rust_error_at (item.get_locus (), "derive(%s) cannot be used on unions",
+ trait_name.c_str ());
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-derive-ord.h b/gcc/rust/expand/rust-derive-ord.h
new file mode 100644
index 0000000..90ce9c8
--- /dev/null
+++ b/gcc/rust/expand/rust-derive-ord.h
@@ -0,0 +1,122 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_DERIVE_ORD_H
+#define RUST_DERIVE_ORD_H
+
+#include "rust-ast.h"
+#include "rust-derive-cmp-common.h"
+#include "rust-derive.h"
+
+namespace Rust {
+namespace AST {
+
+/**
+ * DeriveOrd is a bit special as the expansion of both `PartialOrd` and `Ord`
+ * is extremely similar. The only difference is that `PartialOrd` concerns
+ * partial-ordering, and thus its main method returns an `Option<Ordering>`,
+ * while `Ord` concerns total-ordering, and its main method returns an
+ * `Ordering`. Otherwise, the expansion logic is the same, so we factor both
+ * derives into one.
+ */
+class DeriveOrd : public DeriveVisitor
+{
+public:
+ enum class Ordering
+ {
+ Total,
+ Partial
+ };
+
+ std::string fn (Ordering ordering)
+ {
+ if (ordering == Ordering::Total)
+ return "cmp";
+ else
+ return "partial_cmp";
+ }
+
+ std::string trait (Ordering ordering)
+ {
+ if (ordering == Ordering::Total)
+ return "Ord";
+ else
+ return "PartialOrd";
+ }
+
+ DeriveOrd (Ordering ordering, location_t loc);
+
+ std::unique_ptr<Item> go (Item &item);
+
+private:
+ std::unique_ptr<Item> expanded;
+
+ Ordering ordering;
+
+ /* Identifier patterns for the non-equal match arms */
+ constexpr static const char *not_equal = "#non_eq";
+ constexpr static const char *self_discr = "#self_discr";
+ constexpr static const char *other_discr = "#other_discr";
+
+ /**
+ * Create the recursive matching structure used when implementing the
+ * comparison function on multiple sub items (fields, tuple indexes...)
+ */
+ std::unique_ptr<Expr> recursive_match (std::vector<SelfOther> &&members);
+
+ /**
+ * Create a pattern for the `Ordering::Equal` case. In the case of partial
+ * ordering, `Option::Some(Ordering::Equal)`.
+ */
+ std::unique_ptr<Pattern> make_equal ();
+
+ /**
+ * Make the match arms for one inner match in a comparison function block.
+ * This returns the "equal" match arm and the "rest" match arm, so something
+ * like `Ordering::Equal` and `non_eq` in the following match expression:
+ *
+ * match cmp(...) {
+ * Ordering::Equal => match cmp(...) { ... }
+ * non_eq => non_eq,
+ * }
+ */
+ std::pair<MatchArm, MatchArm> make_cmp_arms ();
+
+ /**
+ * Generate a call to the proper trait function, based on the ordering, in
+ * order to compare two given expressions
+ */
+ std::unique_ptr<Expr> cmp_call (std::unique_ptr<Expr> &&self_expr,
+ std::unique_ptr<Expr> &&other_expr);
+
+ std::unique_ptr<Item>
+ cmp_impl (std::unique_ptr<BlockExpr> &&fn_block, Identifier type_name,
+ const std::vector<std::unique_ptr<GenericParam>> &type_generics);
+ std::unique_ptr<AssociatedItem> cmp_fn (std::unique_ptr<BlockExpr> &&block,
+ Identifier type_name);
+
+ virtual void visit_struct (StructStruct &item) override;
+ virtual void visit_tuple (TupleStruct &item) override;
+ virtual void visit_enum (Enum &item) override;
+ virtual void visit_union (Union &item) override;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DERIVE_ORD_H
diff --git a/gcc/rust/expand/rust-derive-partial-eq.cc b/gcc/rust/expand/rust-derive-partial-eq.cc
index ff66faa..a0bf87a 100644
--- a/gcc/rust/expand/rust-derive-partial-eq.cc
+++ b/gcc/rust/expand/rust-derive-partial-eq.cc
@@ -64,11 +64,9 @@ DerivePartialEq::partialeq_impls (
}
std::unique_ptr<AssociatedItem>
-DerivePartialEq::eq_fn (std::unique_ptr<Expr> &&cmp_expression,
+DerivePartialEq::eq_fn (std::unique_ptr<BlockExpr> &&block,
std::string type_name)
{
- auto block = builder.block (tl::nullopt, std::move (cmp_expression));
-
auto self_type
= std::unique_ptr<TypeNoBounds> (new TypePath (builder.type_path ("Self")));
@@ -83,24 +81,6 @@ DerivePartialEq::eq_fn (std::unique_ptr<Expr> &&cmp_expression,
std::move (block));
}
-DerivePartialEq::SelfOther
-DerivePartialEq::tuple_indexes (int idx)
-{
- return SelfOther{
- builder.tuple_idx ("self", idx),
- builder.tuple_idx ("other", idx),
- };
-}
-
-DerivePartialEq::SelfOther
-DerivePartialEq::field_acccesses (const std::string &field_name)
-{
- return SelfOther{
- builder.field_access (builder.identifier ("self"), field_name),
- builder.field_access (builder.identifier ("other"), field_name),
- };
-}
-
std::unique_ptr<Expr>
DerivePartialEq::build_eq_expression (
std::vector<SelfOther> &&field_expressions)
@@ -134,12 +114,10 @@ void
DerivePartialEq::visit_tuple (TupleStruct &item)
{
auto type_name = item.get_struct_name ().as_string ();
- auto fields = std::vector<SelfOther> ();
-
- for (size_t idx = 0; idx < item.get_fields ().size (); idx++)
- fields.emplace_back (tuple_indexes (idx));
+ auto fields = SelfOther::indexes (builder, item.get_fields ());
- auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name);
+ auto fn = eq_fn (builder.block (build_eq_expression (std::move (fields))),
+ type_name);
expanded
= partialeq_impls (std::move (fn), type_name, item.get_generic_params ());
@@ -149,13 +127,10 @@ void
DerivePartialEq::visit_struct (StructStruct &item)
{
auto type_name = item.get_struct_name ().as_string ();
- auto fields = std::vector<SelfOther> ();
+ auto fields = SelfOther::fields (builder, item.get_fields ());
- for (auto &field : item.get_fields ())
- fields.emplace_back (
- field_acccesses (field.get_field_name ().as_string ()));
-
- auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name);
+ auto fn = eq_fn (builder.block (build_eq_expression (std::move (fields))),
+ type_name);
expanded
= partialeq_impls (std::move (fn), type_name, item.get_generic_params ());
@@ -199,8 +174,6 @@ DerivePartialEq::match_enum_tuple (PathInExpression variant_path,
auto self_pattern_str = "__self_" + std::to_string (i);
auto other_pattern_str = "__other_" + std::to_string (i);
- rust_debug ("]ARTHUR[ %s", self_pattern_str.c_str ());
-
self_patterns.emplace_back (
builder.identifier_pattern (self_pattern_str));
other_patterns.emplace_back (
@@ -240,15 +213,55 @@ MatchCase
DerivePartialEq::match_enum_struct (PathInExpression variant_path,
const EnumItemStruct &variant)
{
- // NOTE: We currently do not support compiling struct patterns where an
- // identifier is assigned a new pattern, e.g. Bloop { f0: x }
- // This is what we should be using to compile PartialEq for enum struct
- // variants, as we need to be comparing the field of each instance meaning we
- // need to give two different names to two different instances of the same
- // field. We cannot just use the field's name like we do when deriving
- // `Clone`.
-
- rust_unreachable ();
+ auto self_fields = std::vector<std::unique_ptr<StructPatternField>> ();
+ auto other_fields = std::vector<std::unique_ptr<StructPatternField>> ();
+
+ auto self_other_exprs = std::vector<SelfOther> ();
+
+ for (auto &field : variant.get_struct_fields ())
+ {
+ // The patterns we're creating for each field are `self_<field>` and
+ // `other_<field>` where `field` is the name of the field. It doesn't
+ // actually matter what we use, as long as it's ordered, unique, and that
+ // we can reuse it in the match case's return expression to check that
+ // they are equal.
+
+ auto field_name = field.get_field_name ().as_string ();
+
+ auto self_pattern_str = "__self_" + field_name;
+ auto other_pattern_str = "__other_" + field_name;
+
+ self_fields.emplace_back (builder.struct_pattern_ident_pattern (
+ field_name, builder.identifier_pattern (self_pattern_str)));
+ other_fields.emplace_back (builder.struct_pattern_ident_pattern (
+ field_name, builder.identifier_pattern (other_pattern_str)));
+
+ self_other_exprs.emplace_back (SelfOther{
+ builder.identifier (self_pattern_str),
+ builder.identifier (other_pattern_str),
+ });
+ }
+
+ auto self_elts = StructPatternElements (std::move (self_fields));
+ auto other_elts = StructPatternElements (std::move (other_fields));
+
+ auto self_pattern = std::unique_ptr<Pattern> (
+ new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern (
+ variant_path, loc, std::move (self_elts))),
+ false, false, loc));
+ auto other_pattern = std::unique_ptr<Pattern> (
+ new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern (
+ variant_path, loc, std::move (other_elts))),
+ false, false, loc));
+
+ auto tuple_items = std::make_unique<TuplePatternItemsMultiple> (
+ vec (std::move (self_pattern), std::move (other_pattern)));
+
+ auto pattern = std::make_unique<TuplePattern> (std::move (tuple_items), loc);
+
+ auto expr = build_eq_expression (std::move (self_other_exprs));
+
+ return builder.match_case (std::move (pattern), std::move (expr));
}
void
@@ -257,46 +270,56 @@ DerivePartialEq::visit_enum (Enum &item)
auto cases = std::vector<MatchCase> ();
auto type_name = item.get_identifier ().as_string ();
+ auto eq_expr_fn = [this] (std::vector<SelfOther> &&fields) {
+ return build_eq_expression (std::move (fields));
+ };
+
+ auto let_sd
+ = builder.discriminant_value (DerivePartialEq::self_discr, "self");
+ auto let_od
+ = builder.discriminant_value (DerivePartialEq::other_discr, "other");
+
+ auto discr_cmp
+ = builder.comparison_expr (builder.identifier (DerivePartialEq::self_discr),
+ builder.identifier (
+ DerivePartialEq::other_discr),
+ ComparisonOperator::EQUAL);
+
for (auto &variant : item.get_variants ())
{
- auto variant_path
- = builder.variant_path (type_name,
- variant->get_identifier ().as_string ());
+ auto enum_builder
+ = EnumMatchBuilder (type_name, variant->get_identifier ().as_string (),
+ eq_expr_fn, builder);
switch (variant->get_enum_item_kind ())
{
- case EnumItem::Kind::Identifier:
- case EnumItem::Kind::Discriminant:
- cases.emplace_back (match_enum_identifier (variant_path, variant));
- break;
case EnumItem::Kind::Tuple:
- cases.emplace_back (
- match_enum_tuple (variant_path,
- static_cast<EnumItemTuple &> (*variant)));
+ cases.emplace_back (enum_builder.tuple (*variant));
break;
case EnumItem::Kind::Struct:
- rust_sorry_at (
- item.get_locus (),
- "cannot derive(PartialEq) for enum struct variants yet");
+ cases.emplace_back (enum_builder.strukt (*variant));
+ break;
+ case EnumItem::Kind::Identifier:
+ case EnumItem::Kind::Discriminant:
+ // We don't need to do anything for these, as they are handled by the
+ // discriminant value comparison
break;
}
}
- // NOTE: Mention using discriminant_value and skipping that last case, and
- // instead skipping all identifiers/discriminant enum items and returning
- // `true` in the wildcard case
-
// In case the two instances of `Self` don't have the same discriminant,
// automatically return false.
cases.emplace_back (
- builder.match_case (builder.wildcard (), builder.literal_bool (false)));
+ builder.match_case (builder.wildcard (), std::move (discr_cmp)));
auto match
= builder.match (builder.tuple (vec (builder.identifier ("self"),
builder.identifier ("other"))),
std::move (cases));
- auto fn = eq_fn (std::move (match), type_name);
+ auto fn = eq_fn (builder.block (vec (std::move (let_sd), std::move (let_od)),
+ std::move (match)),
+ type_name);
expanded
= partialeq_impls (std::move (fn), type_name, item.get_generic_params ());
diff --git a/gcc/rust/expand/rust-derive-partial-eq.h b/gcc/rust/expand/rust-derive-partial-eq.h
index ac963a6..7985414 100644
--- a/gcc/rust/expand/rust-derive-partial-eq.h
+++ b/gcc/rust/expand/rust-derive-partial-eq.h
@@ -21,6 +21,7 @@
#include "rust-derive.h"
#include "rust-path.h"
+#include "rust-derive-cmp-common.h"
namespace Rust {
namespace AST {
@@ -30,7 +31,7 @@ class DerivePartialEq : DeriveVisitor
public:
DerivePartialEq (location_t loc);
- std::vector<std::unique_ptr<AST::Item>> go (Item &item);
+ std::vector<std::unique_ptr<Item>> go (Item &item);
private:
std::vector<std::unique_ptr<Item>> expanded;
@@ -43,23 +44,10 @@ private:
std::unique_ptr<AssociatedItem> &&eq_fn, std::string name,
const std::vector<std::unique_ptr<GenericParam>> &type_generics);
- std::unique_ptr<AssociatedItem> eq_fn (std::unique_ptr<Expr> &&cmp_expression,
+ std::unique_ptr<AssociatedItem> eq_fn (std::unique_ptr<BlockExpr> &&block,
std::string type_name);
/**
- * A pair of two expressions from each instance being compared. E.g. this
- * could be `self.0` and `other.0`, or `self.field` and `other.field`
- */
- struct SelfOther
- {
- std::unique_ptr<Expr> self_expr;
- std::unique_ptr<Expr> other_expr;
- };
-
- SelfOther tuple_indexes (int idx);
- SelfOther field_acccesses (const std::string &field_name);
-
- /**
* Build a suite of equality arithmetic expressions chained together by a
* boolean AND operator
*/
@@ -73,10 +61,13 @@ private:
MatchCase match_enum_struct (PathInExpression variant_path,
const EnumItemStruct &variant);
- virtual void visit_struct (StructStruct &item);
- virtual void visit_tuple (TupleStruct &item);
- virtual void visit_enum (Enum &item);
- virtual void visit_union (Union &item);
+ constexpr static const char *self_discr = "#self_discr";
+ constexpr static const char *other_discr = "#other_discr";
+
+ virtual void visit_struct (StructStruct &item) override;
+ virtual void visit_tuple (TupleStruct &item) override;
+ virtual void visit_enum (Enum &item) override;
+ virtual void visit_union (Union &item) override;
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc
index 015b81e..55147df 100644
--- a/gcc/rust/expand/rust-derive.cc
+++ b/gcc/rust/expand/rust-derive.cc
@@ -22,6 +22,7 @@
#include "rust-derive-debug.h"
#include "rust-derive-default.h"
#include "rust-derive-eq.h"
+#include "rust-derive-ord.h"
#include "rust-derive-partial-eq.h"
#include "rust-derive-hash.h"
@@ -59,10 +60,11 @@ DeriveVisitor::derive (Item &item, const Attribute &attr,
case BuiltinMacro::Hash:
return vec (DeriveHash (loc).go (item));
case BuiltinMacro::Ord:
+ return vec (DeriveOrd (DeriveOrd::Ordering::Total, loc).go (item));
case BuiltinMacro::PartialOrd:
+ return vec (DeriveOrd (DeriveOrd::Ordering::Partial, loc).go (item));
default:
- rust_sorry_at (loc, "unimplemented builtin derive macro");
- return {};
+ rust_unreachable ();
};
}
@@ -79,7 +81,8 @@ DeriveVisitor::setup_impl_generics (
{
switch (generic->get_kind ())
{
- case GenericParam::Kind::Lifetime: {
+ case GenericParam::Kind::Lifetime:
+ {
LifetimeParam &lifetime_param = (LifetimeParam &) *generic.get ();
Lifetime l = builder.new_lifetime (lifetime_param.get_lifetime ());
@@ -91,7 +94,8 @@ DeriveVisitor::setup_impl_generics (
}
break;
- case GenericParam::Kind::Type: {
+ case GenericParam::Kind::Type:
+ {
TypeParam &type_param = (TypeParam &) *generic.get ();
std::unique_ptr<Type> associated_type = builder.single_type_path (
@@ -104,7 +108,8 @@ DeriveVisitor::setup_impl_generics (
std::vector<std::unique_ptr<TypeParamBound>> extra_bounds;
if (extra_bound)
- extra_bounds.emplace_back (std::move (*extra_bound));
+ extra_bounds.emplace_back (
+ extra_bound.value ()->clone_type_param_bound ());
auto impl_type_param
= builder.new_type_param (type_param, std::move (extra_bounds));
@@ -113,17 +118,20 @@ DeriveVisitor::setup_impl_generics (
}
break;
- case GenericParam::Kind::Const: {
- rust_unreachable ();
+ case GenericParam::Kind::Const:
+ {
+ ConstGenericParam &const_param
+ = (ConstGenericParam &) *generic.get ();
- // TODO
- // const ConstGenericParam *const_param
- // = (const ConstGenericParam *) generic.get ();
- // std::unique_ptr<Expr> const_expr = nullptr;
+ std::unique_ptr<Type> associated_type
+ = builder.single_type_path (const_param.get_name ().as_string ());
- // GenericArg type_arg
- // = GenericArg::create_const (std::move (const_expr));
- // generic_args.push_back (std::move (type_arg));
+ GenericArg type_arg
+ = GenericArg::create_type (std::move (associated_type));
+ generic_args.push_back (std::move (type_arg));
+
+ auto impl_const_param = builder.new_const_param (const_param);
+ impl_generics.push_back (std::move (impl_const_param));
}
break;
}
diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h
index 5fca49c..10c146c 100644
--- a/gcc/rust/expand/rust-derive.h
+++ b/gcc/rust/expand/rust-derive.h
@@ -118,7 +118,7 @@ private:
virtual void visit (LiteralExpr &expr) override final{};
virtual void visit (AttrInputLiteral &attr_input) override final{};
virtual void visit (MetaItemLitExpr &meta_item) override final{};
- virtual void visit (MetaItemPathLit &meta_item) override final{};
+ virtual void visit (MetaItemPathExpr &meta_item) override final{};
virtual void visit (BorrowExpr &expr) override final{};
virtual void visit (DereferenceExpr &expr) override final{};
virtual void visit (ErrorPropagationExpr &expr) override final{};
@@ -147,6 +147,8 @@ private:
virtual void visit (FieldAccessExpr &expr) override final{};
virtual void visit (ClosureExprInner &expr) override final{};
virtual void visit (BlockExpr &expr) override final{};
+ virtual void visit (AnonConst &expr) override final{};
+ virtual void visit (ConstBlock &expr) override final{};
virtual void visit (ClosureExprInnerTyped &expr) override final{};
virtual void visit (ContinueExpr &expr) override final{};
virtual void visit (BreakExpr &expr) override final{};
@@ -157,6 +159,7 @@ private:
virtual void visit (RangeFromToInclExpr &expr) override final{};
virtual void visit (RangeToInclExpr &expr) override final{};
virtual void visit (ReturnExpr &expr) override final{};
+ virtual void visit (TryExpr &expr) override final{};
virtual void visit (BoxExpr &expr) override final{};
virtual void visit (UnsafeBlockExpr &expr) override final{};
virtual void visit (LoopExpr &expr) override final{};
@@ -228,6 +231,8 @@ private:
virtual void visit (TuplePatternItemsRanged &tuple_items) override final{};
virtual void visit (TuplePattern &pattern) override final{};
virtual void visit (GroupedPattern &pattern) override final{};
+ virtual void visit (SlicePatternItemsNoRest &items) override final{};
+ virtual void visit (SlicePatternItemsHasRest &items) override final{};
virtual void visit (SlicePattern &pattern) override final{};
virtual void visit (AltPattern &pattern) override final{};
virtual void visit (EmptyStmt &stmt) override final{};
@@ -251,6 +256,7 @@ private:
virtual void visit (FunctionParam &param) override final{};
virtual void visit (VariadicParam &param) override final{};
virtual void visit (FormatArgs &param) override final{};
+ virtual void visit (OffsetOf &param) override final{};
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-expand-format-args.cc b/gcc/rust/expand/rust-expand-format-args.cc
index af6182f..bda28dd 100644
--- a/gcc/rust/expand/rust-expand-format-args.cc
+++ b/gcc/rust/expand/rust-expand-format-args.cc
@@ -85,11 +85,13 @@ expand_format_args (AST::FormatArgs &fmt,
static_pieces.emplace_back (
builder.literal_string (node.string._0.to_string ()));
break;
- case ffi::Piece::Tag::NextArgument: {
+ case ffi::Piece::Tag::NextArgument:
+ {
auto next_argument = node.next_argument._0;
switch (node.next_argument._0.position.tag)
{
- case ffi::Position::Tag::ArgumentImplicitlyIs: {
+ case ffi::Position::Tag::ArgumentImplicitlyIs:
+ {
auto idx = next_argument.position.argument_implicitly_is._0;
auto trait = next_argument.format;
auto arg = arguments.at (idx);
diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc
index 42df5e1..8f6e7fa 100644
--- a/gcc/rust/expand/rust-expand-visitor.cc
+++ b/gcc/rust/expand/rust-expand-visitor.cc
@@ -233,10 +233,7 @@ ExpandVisitor::expand_inner_items (
}
}
- std::function<std::unique_ptr<AST::Item> (AST::SingleASTNode)> extractor
- = [] (AST::SingleASTNode node) { return node.take_item (); };
-
- expand_macro_children (items, extractor);
+ expand_macro_children (items, &AST::SingleASTNode::take_item);
expander.pop_context ();
}
@@ -324,10 +321,7 @@ ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr)
if (!expr.has_tail_expr ())
expr.normalize_tail_expr ();
- std::function<std::unique_ptr<AST::Stmt> (AST::SingleASTNode)> extractor
- = [] (AST::SingleASTNode node) { return node.take_stmt (); };
-
- expand_macro_children (stmts, extractor);
+ expand_macro_children (stmts, &AST::SingleASTNode::take_stmt);
expander.pop_context ();
}
@@ -544,7 +538,7 @@ ExpandVisitor::visit (AST::MetaItemLitExpr &)
{}
void
-ExpandVisitor::visit (AST::MetaItemPathLit &)
+ExpandVisitor::visit (AST::MetaItemPathExpr &)
{}
void
@@ -641,7 +635,7 @@ ExpandVisitor::visit (AST::ClosureExprInnerTyped &expr)
maybe_expand_type (expr.get_return_type_ptr ());
- visit (expr.get_definition_block ());
+ visit (expr.get_definition_expr ());
}
void
@@ -866,12 +860,9 @@ ExpandVisitor::visit (AST::Trait &trait)
expander.push_context (MacroExpander::ContextType::TRAIT);
- std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)>
- extractor
- = [] (AST::SingleASTNode node) { return node.take_assoc_item (); };
-
expand_macro_children (MacroExpander::ContextType::TRAIT,
- trait.get_trait_items (), extractor);
+ trait.get_trait_items (),
+ &AST::SingleASTNode::take_assoc_item);
expander.pop_context ();
}
@@ -894,12 +885,9 @@ ExpandVisitor::visit (AST::InherentImpl &impl)
if (impl.has_where_clause ())
expand_where_clause (impl.get_where_clause ());
- std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)>
- extractor
- = [] (AST::SingleASTNode node) { return node.take_assoc_item (); };
-
expand_macro_children (MacroExpander::ContextType::IMPL,
- impl.get_impl_items (), extractor);
+ impl.get_impl_items (),
+ &AST::SingleASTNode::take_assoc_item);
}
void
@@ -922,12 +910,9 @@ ExpandVisitor::visit (AST::TraitImpl &impl)
if (impl.has_where_clause ())
expand_where_clause (impl.get_where_clause ());
- std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)>
- extractor
- = [] (AST::SingleASTNode node) { return node.take_assoc_item (); };
-
expand_macro_children (MacroExpander::ContextType::TRAIT_IMPL,
- impl.get_impl_items (), extractor);
+ impl.get_impl_items (),
+ &AST::SingleASTNode::take_assoc_item);
}
void
@@ -944,12 +929,10 @@ void
ExpandVisitor::visit (AST::ExternBlock &block)
{
visit_inner_attrs (block);
- std::function<std::unique_ptr<AST::ExternalItem> (AST::SingleASTNode)>
- extractor
- = [] (AST::SingleASTNode node) { return node.take_external_item (); };
expand_macro_children (MacroExpander::ContextType::EXTERN,
- block.get_extern_items (), extractor);
+ block.get_extern_items (),
+ &AST::SingleASTNode::take_external_item);
}
void
diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h
index ad237c0..845e10c 100644
--- a/gcc/rust/expand/rust-expand-visitor.h
+++ b/gcc/rust/expand/rust-expand-visitor.h
@@ -28,14 +28,12 @@ namespace Rust {
/**
* Whether or not an attribute is a derive attribute
*/
-bool
-is_derive (AST::Attribute &attr);
+bool is_derive (AST::Attribute &attr);
/**
* Whether or not an attribute is builtin
*/
-bool
-is_builtin (AST::Attribute &attr);
+bool is_builtin (AST::Attribute &attr);
class ExpandVisitor : public AST::DefaultASTVisitor
{
@@ -107,7 +105,7 @@ public:
*/
template <typename T, typename U>
void expand_macro_children (MacroExpander::ContextType ctx, T &values,
- std::function<U (AST::SingleASTNode)> extractor)
+ U (AST::SingleASTNode::*extractor) (void))
{
expander.push_context (ctx);
@@ -123,7 +121,7 @@ public:
*/
template <typename T, typename U>
void expand_macro_children (T &values,
- std::function<U (AST::SingleASTNode)> extractor)
+ U (AST::SingleASTNode::*extractor) (void))
{
for (auto it = values.begin (); it != values.end ();)
{
@@ -140,7 +138,7 @@ public:
it = values.erase (it);
for (auto &node : final_fragment.get_nodes ())
{
- U new_node = extractor (node);
+ U new_node = (node.*extractor) ();
if (new_node != nullptr)
{
it = values.insert (it, std::move (new_node));
@@ -211,7 +209,7 @@ public:
void visit (AST::AttrInputLiteral &) override;
void visit (AST::AttrInputMacro &) override;
void visit (AST::MetaItemLitExpr &) override;
- void visit (AST::MetaItemPathLit &) override;
+ void visit (AST::MetaItemPathExpr &) override;
void visit (AST::ErrorPropagationExpr &expr) override;
void visit (AST::ArithmeticOrLogicalExpr &expr) override;
void visit (AST::ComparisonExpr &expr) override;
diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc
index e255729..61222db 100644
--- a/gcc/rust/expand/rust-macro-builtins-asm.cc
+++ b/gcc/rust/expand/rust-macro-builtins-asm.cc
@@ -25,18 +25,6 @@
#include "rust-parse.h"
namespace Rust {
-std::map<AST::InlineAsmOption, std::string> InlineAsmOptionMap{
- {AST::InlineAsmOption::PURE, "pure"},
- {AST::InlineAsmOption::NOMEM, "nomem"},
- {AST::InlineAsmOption::READONLY, "readonly"},
- {AST::InlineAsmOption::PRESERVES_FLAGS, "preserves_flags"},
- {AST::InlineAsmOption::NORETURN, "noreturn"},
- {AST::InlineAsmOption::NOSTACK, "nostack"},
- {AST::InlineAsmOption::MAY_UNWIND, "may_unwind"},
- {AST::InlineAsmOption::ATT_SYNTAX, "att_syntax"},
- {AST::InlineAsmOption::RAW, "raw"},
-};
-
std::set<std::string> potentially_nonpromoted_keywords
= {"in", "out", "lateout", "inout", "inlateout", "const", "sym", "label"};
@@ -396,6 +384,7 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx)
{
auto &parser = inline_asm_ctx.parser;
auto token = parser.peek_current_token ();
+ location_t locus = token->get_locus ();
if (!inline_asm_ctx.is_global_asm () && check_identifier (parser, "inout"))
{
@@ -413,10 +402,8 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx)
// TODO: Is error propogation our top priority, the ? in rust's asm.rs is
// doing a lot of work.
- // TODO: Not sure how to use parse_expr
- if (!check_identifier (parser, ""))
- rust_unreachable ();
- // auto expr = parse_format_string (inline_asm_ctx);
+ std::unique_ptr<AST::Expr> in_expr = parser.parse_expr ();
+ rust_assert (in_expr != nullptr);
std::unique_ptr<AST::Expr> out_expr;
@@ -426,11 +413,19 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx)
{
// auto result = parse_format_string (inline_asm_ctx);
- if (!check_identifier (parser, ""))
- rust_unreachable ();
- // out_expr = parser.parse_expr();
+ out_expr = parser.parse_expr ();
+
+ AST::InlineAsmOperand::SplitInOut splitinout (
+ reg, false, std::move (in_expr), std::move (out_expr));
+
+ inline_asm_ctx.inline_asm.operands.emplace_back (splitinout,
+ locus);
+
+ return inline_asm_ctx;
}
+ rust_unreachable ();
+
// TODO: Rembmer to pass in clone_expr() instead of nullptr
// https://github.com/rust-lang/rust/blob/a3167859f2fd8ff2241295469876a2b687280bdc/compiler/rustc_builtin_macros/src/asm.rs#L135
// RUST VERSION: ast::InlineAsmOperand::SplitInOut { reg, in_expr:
@@ -444,6 +439,8 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx)
}
else
{
+ AST::InlineAsmOperand::InOut inout (reg, false, std::move (in_expr));
+ inline_asm_ctx.inline_asm.operands.emplace_back (inout, locus);
// https://github.com/rust-lang/rust/blob/a3167859f2fd8ff2241295469876a2b687280bdc/compiler/rustc_builtin_macros/src/asm.rs#L137
// RUST VERSION: ast::InlineAsmOperand::InOut { reg, expr, late: false
// }
@@ -500,7 +497,7 @@ parse_reg_operand_unexpected (InlineAsmContext inline_asm_ctx)
}
void
-check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option)
+check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsm::Option option)
{
auto &parser = inline_asm_ctx.parser;
auto &inline_asm = inline_asm_ctx.inline_asm;
@@ -509,7 +506,7 @@ check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option)
// TODO: report an error of duplication
rust_error_at (parser.peek_current_token ()->get_locus (),
"the %qs option was already provided",
- InlineAsmOptionMap[option].c_str ());
+ AST::InlineAsm::option_to_string (option).c_str ());
return;
}
else
@@ -536,39 +533,40 @@ parse_options (InlineAsmContext &inline_asm_ctx)
{
if (!is_global_asm && check_identifier (parser, "pure"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::PURE);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::PURE);
}
else if (!is_global_asm && check_identifier (parser, "nomem"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::NOMEM);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NOMEM);
}
else if (!is_global_asm && check_identifier (parser, "readonly"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::READONLY);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::READONLY);
}
else if (!is_global_asm && check_identifier (parser, "preserves_flags"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::PRESERVES_FLAGS);
+ check_and_set (inline_asm_ctx,
+ AST::InlineAsm::Option::PRESERVES_FLAGS);
}
else if (!is_global_asm && check_identifier (parser, "noreturn"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::NORETURN);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NORETURN);
}
else if (!is_global_asm && check_identifier (parser, "nostack"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::NOSTACK);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NOSTACK);
}
else if (!is_global_asm && check_identifier (parser, "may_unwind"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::MAY_UNWIND);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::MAY_UNWIND);
}
else if (check_identifier (parser, "att_syntax"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::ATT_SYNTAX);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::ATT_SYNTAX);
}
else if (check_identifier (parser, "raw"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::RAW);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::RAW);
}
else
{
@@ -807,7 +805,8 @@ expand_inline_asm_strings (InlineAsmContext inline_asm_ctx)
auto next_argument = piece.next_argument._0;
switch (piece.next_argument._0.position.tag)
{
- case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs: {
+ case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs:
+ {
auto idx = next_argument.position.argument_implicitly_is._0;
/*auto trait = next_argument.format;*/
/*auto arg = arguments.at (idx);*/
@@ -829,6 +828,11 @@ expand_inline_asm_strings (InlineAsmContext inline_asm_ctx)
}
break;
case Fmt::ffi::Position::Tag::ArgumentIs:
+ {
+ auto idx = next_argument.position.argument_is._0;
+ transformed_template_str += "%" + std::to_string (idx);
+ break;
+ }
case Fmt::ffi::Position::Tag::ArgumentNamed:
rust_sorry_at (inline_asm.get_locus (),
"unhandled argument position specifier");
@@ -933,7 +937,9 @@ parse_format_strings (InlineAsmContext inline_asm_ctx)
{
if (!parser.skip_token (COMMA))
{
- break;
+ rust_error_at (parser.peek_current_token ()->get_locus (),
+ "expected token %qs", ";");
+ return tl::unexpected<InlineAsmParseError> (COMMITTED);
}
// Ok after the comma is good, we better be parsing correctly
// everything in here, which is formatted string in ABNF
diff --git a/gcc/rust/expand/rust-macro-builtins-asm.h b/gcc/rust/expand/rust-macro-builtins-asm.h
index bd64a7f..3196a5a 100644
--- a/gcc/rust/expand/rust-macro-builtins-asm.h
+++ b/gcc/rust/expand/rust-macro-builtins-asm.h
@@ -142,16 +142,16 @@ tl::expected<InlineAsmContext, InlineAsmParseError>
parse_reg_operand_unexpected (InlineAsmContext inline_asm_ctx);
WARN_UNUSED_RESULT
-tl::optional<AST::Fragment>
-parse_asm (location_t invoc_locus, AST::MacroInvocData &invoc,
- AST::InvocKind semicolon, AST::AsmKind is_global_asm);
+tl::optional<AST::Fragment> parse_asm (location_t invoc_locus,
+ AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon,
+ AST::AsmKind is_global_asm);
WARN_UNUSED_RESULT
-bool
-check_identifier (Parser<MacroInvocLexer> &parser, std::string ident);
+bool check_identifier (Parser<MacroInvocLexer> &parser, std::string ident);
-void
-check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option);
+void check_and_set (InlineAsmContext &inline_asm_ctx,
+ AST::InlineAsm::Option option);
// From rustc
WARN_UNUSED_RESULT
@@ -168,9 +168,9 @@ tl::optional<std::string>
parse_format_string (InlineAsmContext &inline_asm_ctx);
WARN_UNUSED_RESULT
-tl::optional<std::string>
-parse_label (Parser<MacroInvocLexer> &parser, TokenId last_token_id,
- InlineAsmContext &inline_asm_ctx);
+tl::optional<std::string> parse_label (Parser<MacroInvocLexer> &parser,
+ TokenId last_token_id,
+ InlineAsmContext &inline_asm_ctx);
// LLVM ASM bits
@@ -188,17 +188,13 @@ public:
{}
};
-void
-parse_llvm_outputs (LlvmAsmContext &ctx);
+void parse_llvm_outputs (LlvmAsmContext &ctx);
-void
-parse_llvm_inputs (LlvmAsmContext &ctx);
+void parse_llvm_inputs (LlvmAsmContext &ctx);
-void
-parse_llvm_clobbers (LlvmAsmContext &ctx);
+void parse_llvm_clobbers (LlvmAsmContext &ctx);
-void
-parse_llvm_options (LlvmAsmContext &ctx);
+void parse_llvm_options (LlvmAsmContext &ctx);
WARN_UNUSED_RESULT tl::optional<AST::Fragment>
parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc,
diff --git a/gcc/rust/expand/rust-macro-builtins-format-args.cc b/gcc/rust/expand/rust-macro-builtins-format-args.cc
index 3e1249d..b20c849 100644
--- a/gcc/rust/expand/rust-macro-builtins-format-args.cc
+++ b/gcc/rust/expand/rust-macro-builtins-format-args.cc
@@ -52,8 +52,15 @@ format_args_parse_arguments (AST::MacroInvocData &invoc)
// TODO: Handle the case where we're not parsing a string literal (macro
// invocation for e.g.)
- if (parser.peek_current_token ()->get_id () == STRING_LITERAL)
- format_expr = parser.parse_literal_expr ();
+ switch (parser.peek_current_token ()->get_id ())
+ {
+ case STRING_LITERAL:
+ case RAW_STRING_LITERAL:
+ format_expr = parser.parse_literal_expr ();
+ default:
+ // do nothing
+ ;
+ }
rust_assert (format_expr);
diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.cc b/gcc/rust/expand/rust-macro-builtins-helpers.cc
index 864379a..ee01f65 100644
--- a/gcc/rust/expand/rust-macro-builtins-helpers.cc
+++ b/gcc/rust/expand/rust-macro-builtins-helpers.cc
@@ -68,6 +68,7 @@ make_eager_builtin_invocation (
{
auto path_str = make_macro_path_str (kind);
+ auto token_stream = arguments.to_token_stream ();
std::unique_ptr<AST::Expr> node = AST::MacroInvocation::Builtin (
kind,
AST::MacroInvocData (AST::SimplePath (
@@ -76,7 +77,7 @@ make_eager_builtin_invocation (
{}, locus, std::move (pending_invocations));
return AST::Fragment ({AST::SingleASTNode (std::move (node))},
- arguments.to_token_stream ());
+ std::move (token_stream));
}
/* Match the end token of a macro given the start delimiter of the macro */
@@ -110,9 +111,9 @@ std::unique_ptr<AST::LiteralExpr>
try_extract_string_literal_from_fragment (const location_t &parent_locus,
std::unique_ptr<AST::Expr> &node)
{
- auto maybe_lit = static_cast<AST::LiteralExpr *> (node.get ());
if (!node || !node->is_literal ()
- || maybe_lit->get_lit_type () != AST::Literal::STRING)
+ || static_cast<AST::LiteralExpr &> (*node).get_lit_type ()
+ != AST::Literal::STRING)
{
rust_error_at (parent_locus, "argument must be a string literal");
if (node)
diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.h b/gcc/rust/expand/rust-macro-builtins-helpers.h
index 429537e..32cf58f 100644
--- a/gcc/rust/expand/rust-macro-builtins-helpers.h
+++ b/gcc/rust/expand/rust-macro-builtins-helpers.h
@@ -33,29 +33,23 @@
#include "rust-token.h"
namespace Rust {
-std::string
-make_macro_path_str (BuiltinMacro kind);
+std::string make_macro_path_str (BuiltinMacro kind);
-std::vector<std::unique_ptr<AST::MacroInvocation>>
-check_for_eager_invocations (
+std::vector<std::unique_ptr<AST::MacroInvocation>> check_for_eager_invocations (
std::vector<std::unique_ptr<AST::Expr>> &expressions);
// Shorthand function for creating unique_ptr tokens
-std::unique_ptr<AST::Token>
-make_token (const TokenPtr tok);
+std::unique_ptr<AST::Token> make_token (const TokenPtr tok);
-std::unique_ptr<AST::Expr>
-make_string (location_t locus, std::string value);
+std::unique_ptr<AST::Expr> make_string (location_t locus, std::string value);
// TODO: Is this correct?
-AST::Fragment
-make_eager_builtin_invocation (
+AST::Fragment make_eager_builtin_invocation (
BuiltinMacro kind, location_t locus, AST::DelimTokenTree arguments,
std::vector<std::unique_ptr<AST::MacroInvocation>> &&pending_invocations);
// Match the end token of a macro given the start delimiter of the macro
-TokenId
-macro_end_token (AST::DelimTokenTree &invoc_token_tree,
- Parser<MacroInvocLexer> &parser);
+TokenId macro_end_token (AST::DelimTokenTree &invoc_token_tree,
+ Parser<MacroInvocLexer> &parser);
// Expand and then extract a string literal from the macro
std::unique_ptr<AST::LiteralExpr>
try_extract_string_literal_from_fragment (const location_t &parent_locus,
@@ -70,21 +64,18 @@ try_expand_many_expr (Parser<MacroInvocLexer> &parser,
// and return the LiteralExpr for it. Allow for an optional trailing comma,
// but otherwise enforce that these are the only tokens.
-std::unique_ptr<AST::Expr>
-parse_single_string_literal (BuiltinMacro kind,
- AST::DelimTokenTree &invoc_token_tree,
- location_t invoc_locus, MacroExpander *expander,
- bool is_semicoloned = false);
+std::unique_ptr<AST::Expr> parse_single_string_literal (
+ BuiltinMacro kind, AST::DelimTokenTree &invoc_token_tree,
+ location_t invoc_locus, MacroExpander *expander, bool is_semicoloned = false);
// Treat PATH as a path relative to the source file currently being
// compiled, and return the absolute path for it.
-std::string
-source_relative_path (std::string path, location_t locus);
+std::string source_relative_path (std::string path, location_t locus);
// Read the full contents of the file FILENAME and return them in a vector.
// FIXME: platform specific.
-tl::optional<std::vector<uint8_t>>
-load_file_bytes (location_t invoc_locus, const char *filename);
+tl::optional<std::vector<uint8_t>> load_file_bytes (location_t invoc_locus,
+ const char *filename);
} // namespace Rust
#endif // GCCRS_RUST_MACRO_BUILTINS_HELPERS_H
diff --git a/gcc/rust/expand/rust-macro-builtins-offset-of.cc b/gcc/rust/expand/rust-macro-builtins-offset-of.cc
new file mode 100644
index 0000000..53efe74
--- /dev/null
+++ b/gcc/rust/expand/rust-macro-builtins-offset-of.cc
@@ -0,0 +1,78 @@
+// Copyright (C) 2020-2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "optional.h"
+#include "rust-ast-fragment.h"
+#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
+#include "rust-diagnostics.h"
+#include "rust-macro-builtins-helpers.h"
+#include "rust-macro-builtins.h"
+#include "rust-macro-invoc-lexer.h"
+#include "rust-parse.h"
+
+namespace Rust {
+
+tl::optional<AST::Fragment>
+MacroBuiltin::offset_of_handler (location_t invoc_locus,
+ AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon)
+{
+ MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
+ Parser<MacroInvocLexer> parser (lex);
+
+ auto last_token = macro_end_token (invoc.get_delim_tok_tree (), parser);
+
+ auto type = parser.parse_type ();
+
+ // if we don't see a type, there might be an eager macro expansion missing
+ // FIXME: handle that
+ if (!type)
+ {
+ rust_error_at (invoc_locus, "could not parse type argument for %qs",
+ "offset_of");
+
+ // we skip so we can still parse the field arg and check if it is correct
+ while (parser.peek_current_token ()->get_id () != COMMA
+ && parser.peek_current_token ()->get_id () != last_token)
+ parser.skip_token ();
+ }
+
+ parser.skip_token (COMMA);
+
+ auto field_tok = parser.parse_identifier_or_keyword_token ();
+ auto invalid_field = !field_tok || !field_tok->has_str ();
+
+ if (invalid_field)
+ rust_error_at (invoc_locus, "could not parse field argument for %qs",
+ "offset_of");
+
+ if (!type || invalid_field)
+ return tl::nullopt;
+
+ auto field = Identifier (field_tok->get_str ());
+
+ // FIXME: Do we need to do anything to handle the optional comma at the end?
+ parser.maybe_skip_token (COMMA);
+
+ return AST::Fragment ({AST::SingleASTNode (std::make_unique<AST::OffsetOf> (
+ std::move (type), field, invoc_locus))},
+ invoc.get_delim_tok_tree ().to_token_stream ());
+}
+
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index b58ed71..a7ae220 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -162,6 +162,9 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc>
{"Ord", MacroBuiltin::proc_macro_builtin},
{"PartialOrd", MacroBuiltin::proc_macro_builtin},
{"Hash", MacroBuiltin::proc_macro_builtin},
+ /* offset_of is not declared in Rust 1.49 but still needed for
+ Rust-for-Linux, so we still create a transcriber and warn the user */
+ {"offset_of", MacroBuiltin::offset_of_handler},
};
tl::optional<BuiltinMacro>
diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h
index 541e956..b6c2907 100644
--- a/gcc/rust/expand/rust-macro-builtins.h
+++ b/gcc/rust/expand/rust-macro-builtins.h
@@ -19,6 +19,7 @@
#ifndef RUST_MACRO_BUILTINS_H
#define RUST_MACRO_BUILTINS_H
+#include "optional.h"
#include "rust-ast.h"
#include "rust-builtin-ast-nodes.h"
#include "rust-ast-fragment.h"
@@ -188,6 +189,9 @@ public:
format_args_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
AST::InvocKind semicolon, AST::FormatArgs::Newline nl);
+ static tl::optional<AST::Fragment>
+ offset_of_handler (location_t, AST::MacroInvocData &, AST::InvocKind);
+
static tl::optional<AST::Fragment> sorry (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 673b8fb..4c54cef 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -19,6 +19,7 @@
#include "rust-macro-expand.h"
#include "optional.h"
#include "rust-ast-fragment.h"
+#include "rust-macro-builtins.h"
#include "rust-macro-substitute-ctx.h"
#include "rust-ast-full.h"
#include "rust-ast-visitor.h"
@@ -287,6 +288,26 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc,
// lookup the rules
auto rules_def = mappings.lookup_macro_invocation (invoc);
+ // We special case the `offset_of!()` macro if the flag is here and manually
+ // resolve to the builtin transcriber we have specified
+ auto assume_builtin_offset_of
+ = flag_assume_builtin_offset_of
+ && (invoc.get_invoc_data ().get_path ().as_string () == "offset_of")
+ && !rules_def;
+
+ // TODO: This is *massive hack* which should be removed as we progress to
+ // Rust 1.71 when offset_of gets added to core
+ if (assume_builtin_offset_of)
+ {
+ fragment = MacroBuiltin::offset_of_handler (invoc.get_locus (),
+ invoc_data, semicolon)
+ .value_or (AST::Fragment::create_empty ());
+
+ set_expanded_fragment (std::move (fragment));
+
+ return;
+ }
+
// If there's no rule associated with the invocation, we can simply return
// early. The early name resolver will have already emitted an error.
if (!rules_def)
@@ -430,7 +451,8 @@ MacroExpander::match_fragment (Parser<MacroInvocLexer> &parser,
parser.parse_visibility ();
break;
- case AST::MacroFragSpec::STMT: {
+ case AST::MacroFragSpec::STMT:
+ {
auto restrictions = ParseRestrictions ();
restrictions.consume_semi = false;
parser.parse_stmt (restrictions);
@@ -480,19 +502,22 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser,
// this is used so we can check that we delimit the stream correctly.
switch (delimiter->get_id ())
{
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
if (!check_delim (AST::DelimType::PARENS))
return false;
}
break;
- case LEFT_SQUARE: {
+ case LEFT_SQUARE:
+ {
if (!check_delim (AST::DelimType::SQUARE))
return false;
}
break;
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
if (!check_delim (AST::DelimType::CURLY))
return false;
}
@@ -510,7 +535,8 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser,
switch (match->get_macro_match_type ())
{
- case AST::MacroMatch::MacroMatchType::Fragment: {
+ case AST::MacroMatch::MacroMatchType::Fragment:
+ {
AST::MacroMatchFragment *fragment
= static_cast<AST::MacroMatchFragment *> (match.get ());
if (!match_fragment (parser, *fragment))
@@ -524,14 +550,16 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser,
}
break;
- case AST::MacroMatch::MacroMatchType::Tok: {
+ case AST::MacroMatch::MacroMatchType::Tok:
+ {
AST::Token *tok = static_cast<AST::Token *> (match.get ());
if (!match_token (parser, *tok))
return false;
}
break;
- case AST::MacroMatch::MacroMatchType::Repetition: {
+ case AST::MacroMatch::MacroMatchType::Repetition:
+ {
AST::MacroMatchRepetition *rep
= static_cast<AST::MacroMatchRepetition *> (match.get ());
if (!match_repetition (parser, *rep))
@@ -539,7 +567,8 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser,
}
break;
- case AST::MacroMatch::MacroMatchType::Matcher: {
+ case AST::MacroMatch::MacroMatchType::Matcher:
+ {
AST::MacroMatcher *m
= static_cast<AST::MacroMatcher *> (match.get ());
expansion_depth++;
@@ -556,19 +585,22 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser,
switch (delimiter->get_id ())
{
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
if (!parser.skip_token (RIGHT_PAREN))
return false;
}
break;
- case LEFT_SQUARE: {
+ case LEFT_SQUARE:
+ {
if (!parser.skip_token (RIGHT_SQUARE))
return false;
}
break;
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
if (!parser.skip_token (RIGHT_CURLY))
return false;
}
@@ -617,7 +649,8 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
size_t offs_begin = source.get_offs ();
switch (match->get_macro_match_type ())
{
- case AST::MacroMatch::MacroMatchType::Fragment: {
+ case AST::MacroMatch::MacroMatchType::Fragment:
+ {
AST::MacroMatchFragment *fragment
= static_cast<AST::MacroMatchFragment *> (match.get ());
valid_current_match = match_fragment (parser, *fragment);
@@ -632,20 +665,23 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
}
break;
- case AST::MacroMatch::MacroMatchType::Tok: {
+ case AST::MacroMatch::MacroMatchType::Tok:
+ {
AST::Token *tok = static_cast<AST::Token *> (match.get ());
valid_current_match = match_token (parser, *tok);
}
break;
- case AST::MacroMatch::MacroMatchType::Repetition: {
+ case AST::MacroMatch::MacroMatchType::Repetition:
+ {
AST::MacroMatchRepetition *rep
= static_cast<AST::MacroMatchRepetition *> (match.get ());
valid_current_match = match_repetition (parser, *rep);
}
break;
- case AST::MacroMatch::MacroMatchType::Matcher: {
+ case AST::MacroMatch::MacroMatchType::Matcher:
+ {
AST::MacroMatcher *m
= static_cast<AST::MacroMatcher *> (match.get ());
valid_current_match = match_matcher (parser, *m, true);
diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc
index 02e4e3b..ac36ed8 100644
--- a/gcc/rust/expand/rust-macro-substitute-ctx.cc
+++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc
@@ -273,7 +273,8 @@ SubstituteCtx::substitute_token (size_t token_idx)
// don't substitute, dollar sign is alone/metavar is unknown
return {std::vector<std::unique_ptr<AST::Token>> (), 0};
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// We need to parse up until the closing delimiter and expand this
// fragment->n times.
rust_debug ("expanding repetition");
diff --git a/gcc/rust/expand/rust-proc-macro.h b/gcc/rust/expand/rust-proc-macro.h
index 6ffaaf6..058c93a 100644
--- a/gcc/rust/expand/rust-proc-macro.h
+++ b/gcc/rust/expand/rust-proc-macro.h
@@ -82,11 +82,9 @@ public:
*
* @param The path to the shared object file to load.
*/
-const std::vector<ProcMacro::Procmacro>
-load_macros (std::string path);
+const std::vector<ProcMacro::Procmacro> load_macros (std::string path);
-std::string
-generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id);
+std::string generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id);
} // namespace Rust
diff --git a/gcc/rust/expand/rust-token-tree-desugar.cc b/gcc/rust/expand/rust-token-tree-desugar.cc
index 3b47180..aa20d50 100644
--- a/gcc/rust/expand/rust-token-tree-desugar.cc
+++ b/gcc/rust/expand/rust-token-tree-desugar.cc
@@ -68,5 +68,5 @@ TokenTreeDesugar::visit (Token &tts)
}
}
-}; // namespace AST
-}; // namespace Rust
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-token-tree-desugar.h b/gcc/rust/expand/rust-token-tree-desugar.h
index ccba53b..da9d732 100644
--- a/gcc/rust/expand/rust-token-tree-desugar.h
+++ b/gcc/rust/expand/rust-token-tree-desugar.h
@@ -49,7 +49,7 @@ private:
virtual void visit (Token &tts) override;
};
-}; // namespace AST
-}; // namespace Rust
+} // namespace AST
+} // namespace Rust
#endif //! RUST_TOKEN_TREE_DESUGAR_H
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index 2d9a445..b723f59 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -47,6 +47,27 @@ ASTLoweringBase::visit (AST::ErrorPropagationExpr &expr)
}
void
+ASTLoweringBase::visit (AST::TryExpr &expr)
+{
+ rust_fatal_error (expr.get_locus (), "missing desugar for try-blocks");
+ rust_unreachable ();
+}
+
+void
+ASTLoweringBase::visit (AST::ForLoopExpr &expr)
+{
+ rust_fatal_error (expr.get_locus (), "missing desugar for for-loops");
+ rust_unreachable ();
+}
+
+void
+ASTLoweringBase::visit (AST::WhileLetLoopExpr &expr)
+{
+ rust_fatal_error (expr.get_locus (), "missing desugar for while-let loops");
+ rust_unreachable ();
+}
+
+void
ASTLoweringBase::visit (AST::Token &)
{}
void
@@ -115,7 +136,7 @@ void
ASTLoweringBase::visit (AST::MetaItemLitExpr &)
{}
void
-ASTLoweringBase::visit (AST::MetaItemPathLit &)
+ASTLoweringBase::visit (AST::MetaItemPathExpr &)
{}
void
ASTLoweringBase::visit (AST::BorrowExpr &)
@@ -201,6 +222,12 @@ void
ASTLoweringBase::visit (AST::BlockExpr &)
{}
void
+ASTLoweringBase::visit (AST::AnonConst &)
+{}
+void
+ASTLoweringBase::visit (AST::ConstBlock &)
+{}
+void
ASTLoweringBase::visit (AST::ClosureExprInnerTyped &)
{}
void
@@ -245,12 +272,6 @@ void
ASTLoweringBase::visit (AST::WhileLoopExpr &)
{}
void
-ASTLoweringBase::visit (AST::WhileLetLoopExpr &)
-{}
-void
-ASTLoweringBase::visit (AST::ForLoopExpr &)
-{}
-void
ASTLoweringBase::visit (AST::IfExpr &)
{}
void
@@ -474,6 +495,12 @@ void
ASTLoweringBase::visit (AST::GroupedPattern &)
{}
void
+ASTLoweringBase::visit (AST::SlicePatternItemsNoRest &)
+{}
+void
+ASTLoweringBase::visit (AST::SlicePatternItemsHasRest &)
+{}
+void
ASTLoweringBase::visit (AST::SlicePattern &)
{}
void
@@ -551,6 +578,10 @@ void
ASTLoweringBase::visit (AST::FormatArgs &fmt)
{}
+void
+ASTLoweringBase::visit (AST::OffsetOf &offset_of)
+{}
+
HIR::Lifetime
ASTLoweringBase::lower_lifetime (AST::Lifetime &lifetime,
bool default_to_static_lifetime)
@@ -648,12 +679,14 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args)
{
switch (arg.get_kind ())
{
- case AST::GenericArg::Kind::Type: {
+ case AST::GenericArg::Kind::Type:
+ {
auto type = ASTLoweringType::translate (arg.get_type ());
type_args.emplace_back (std::unique_ptr<HIR::Type> (type));
break;
}
- case AST::GenericArg::Kind::Const: {
+ case AST::GenericArg::Kind::Const:
+ {
auto expr = ASTLoweringExpr::translate (arg.get_expression ());
const_args.emplace_back (
HIR::ConstGenericArg (std::unique_ptr<HIR::Expr> (expr),
@@ -887,7 +920,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound)
std::unique_ptr<HIR::RangePatternBound> hir_bound = nullptr;
switch (bound.get_bound_type ())
{
- case AST::RangePatternBound::RangePatternBoundType::LITERAL: {
+ case AST::RangePatternBound::RangePatternBoundType::LITERAL:
+ {
AST::RangePatternBoundLiteral &ref
= static_cast<AST::RangePatternBoundLiteral &> (bound);
@@ -898,7 +932,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound)
ref.get_has_minus ()));
}
break;
- case AST::RangePatternBound::RangePatternBoundType::PATH: {
+ case AST::RangePatternBound::RangePatternBoundType::PATH:
+ {
auto &ref = static_cast<AST::RangePatternBoundPath &> (bound);
HIR::PathInExpression *path
@@ -908,7 +943,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound)
new HIR::RangePatternBoundPath (*path));
}
break;
- case AST::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ case AST::RangePatternBound::RangePatternBoundType::QUALPATH:
+ {
auto &ref = static_cast<AST::RangePatternBoundQualPath &> (bound);
HIR::QualifiedPathInExpression *qualpath
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index 3116181..e86aacb 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -20,6 +20,8 @@
#define RUST_AST_LOWER_BASE
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
+#include "rust-expr.h"
#include "rust-system.h"
#include "rust-ast-full.h"
#include "rust-ast-visitor.h"
@@ -63,6 +65,9 @@ public:
// Special casing nodes that should never reach the HIR lowering stage
virtual void visit (AST::MacroInvocation &) override final;
virtual void visit (AST::ErrorPropagationExpr &) override final;
+ virtual void visit (AST::ForLoopExpr &) override final;
+ virtual void visit (AST::TryExpr &) override final;
+ virtual void visit (AST::WhileLetLoopExpr &) override final;
// visitor impl
// rust-ast.h
@@ -101,7 +106,7 @@ public:
virtual void visit (AST::AttrInputLiteral &attr_input) override;
virtual void visit (AST::AttrInputMacro &attr_input) override;
virtual void visit (AST::MetaItemLitExpr &meta_item) override;
- virtual void visit (AST::MetaItemPathLit &meta_item) override;
+ virtual void visit (AST::MetaItemPathExpr &meta_item) override;
virtual void visit (AST::BorrowExpr &expr) override;
virtual void visit (AST::DereferenceExpr &expr) override;
virtual void visit (AST::NegationExpr &expr) override;
@@ -131,6 +136,8 @@ public:
virtual void visit (AST::FieldAccessExpr &expr) override;
virtual void visit (AST::ClosureExprInner &expr) override;
virtual void visit (AST::BlockExpr &expr) override;
+ virtual void visit (AST::AnonConst &expr) override;
+ virtual void visit (AST::ConstBlock &expr) override;
virtual void visit (AST::ClosureExprInnerTyped &expr) override;
virtual void visit (AST::ContinueExpr &expr) override;
virtual void visit (AST::BreakExpr &expr) override;
@@ -145,8 +152,6 @@ public:
virtual void visit (AST::UnsafeBlockExpr &expr) override;
virtual void visit (AST::LoopExpr &expr) override;
virtual void visit (AST::WhileLoopExpr &expr) override;
- virtual void visit (AST::WhileLetLoopExpr &expr) override;
- virtual void visit (AST::ForLoopExpr &expr) override;
virtual void visit (AST::IfExpr &expr) override;
virtual void visit (AST::IfExprConseqElse &expr) override;
virtual void visit (AST::IfLetExpr &expr) override;
@@ -231,6 +236,8 @@ public:
virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override;
virtual void visit (AST::TuplePattern &pattern) override;
virtual void visit (AST::GroupedPattern &pattern) override;
+ virtual void visit (AST::SlicePatternItemsNoRest &items) override;
+ virtual void visit (AST::SlicePatternItemsHasRest &items) override;
virtual void visit (AST::SlicePattern &pattern) override;
virtual void visit (AST::AltPattern &pattern) override;
@@ -259,6 +266,7 @@ public:
virtual void visit (AST::SelfParam &param) override;
virtual void visit (AST::FormatArgs &fmt) override;
+ virtual void visit (AST::OffsetOf &offset_of) override;
protected:
ASTLoweringBase ()
diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h
index 93cd443..f10039b 100644
--- a/gcc/rust/hir/rust-ast-lower-block.h
+++ b/gcc/rust/hir/rust-ast-lower-block.h
@@ -213,8 +213,6 @@ public:
void visit (AST::WhileLoopExpr &expr) override;
- void visit (AST::ForLoopExpr &expr) override;
-
void visit (AST::MatchExpr &expr) override;
private:
diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc
index 07d0c835..4ed51d9 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.cc
+++ b/gcc/rust/hir/rust-ast-lower-expr.cc
@@ -24,7 +24,9 @@
#include "rust-ast-lower-pattern.h"
#include "rust-ast-lower-type.h"
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
#include "rust-diagnostics.h"
+#include "rust-hir-map.h"
#include "rust-system.h"
#include "tree/rust-hir-expr.h"
@@ -127,6 +129,50 @@ ASTLoweringExpr::visit (AST::BlockExpr &expr)
}
void
+ASTLoweringExpr::visit (AST::AnonConst &expr)
+{
+ auto &mappings = Analysis::Mappings::get ();
+ auto crate_num = mappings.get_current_crate ();
+ auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (),
+ mappings.get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ if (expr.is_deferred ())
+ {
+ translated = new HIR::AnonConst (std::move (mapping), expr.get_locus ());
+ }
+ else
+ {
+ auto inner_expr = ASTLoweringExpr::translate (expr.get_inner_expr ());
+
+ translated = new HIR::AnonConst (std::move (mapping),
+ std::unique_ptr<Expr> (inner_expr),
+ expr.get_locus ());
+ }
+}
+
+void
+ASTLoweringExpr::visit (AST::ConstBlock &expr)
+{
+ auto inner_expr = ASTLoweringExpr::translate (expr.get_const_expr ());
+
+ // we know this will always be an `AnonConst`, or we have an issue. Let's
+ // assert just to be sure.
+ rust_assert (inner_expr->get_expression_type () == Expr::ExprType::AnonConst);
+ auto anon_const = static_cast<AnonConst *> (inner_expr);
+
+ auto &mappings = Analysis::Mappings::get ();
+ auto crate_num = mappings.get_current_crate ();
+ auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (),
+ mappings.get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::ConstBlock (std::move (mapping), std::move (*anon_const),
+ expr.get_locus (), expr.get_outer_attrs ());
+}
+
+void
ASTLoweringExpr::visit (AST::UnsafeBlockExpr &expr)
{
translated = ASTLoweringBlock::translate (expr, &terminated);
@@ -589,12 +635,6 @@ ASTLoweringExpr::visit (AST::WhileLoopExpr &expr)
}
void
-ASTLoweringExpr::visit (AST::ForLoopExpr &expr)
-{
- rust_unreachable ();
-}
-
-void
ASTLoweringExpr::visit (AST::BreakExpr &expr)
{
tl::optional<HIR::Lifetime> break_label = tl::nullopt;
@@ -798,7 +838,7 @@ ASTLoweringExpr::visit (AST::ClosureExprInnerTyped &expr)
{
HIR::Type *closure_return_type = nullptr;
HIR::Expr *closure_expr
- = ASTLoweringExpr::translate (expr.get_definition_block ());
+ = ASTLoweringExpr::translate (expr.get_definition_expr ());
std::vector<HIR::ClosureParam> closure_params;
for (auto &param : expr.get_params ())
@@ -841,6 +881,7 @@ translate_operand_out (const AST::InlineAsmOperand &operand)
*out_value.expr.get ())));
return out;
}
+
HIR::InlineAsmOperand
translate_operand_inout (const AST::InlineAsmOperand &operand)
{
@@ -851,6 +892,7 @@ translate_operand_inout (const AST::InlineAsmOperand &operand)
*inout_value.expr.get ())));
return inout;
}
+
HIR::InlineAsmOperand
translate_operand_split_in_out (const AST::InlineAsmOperand &operand)
{
@@ -863,19 +905,21 @@ translate_operand_split_in_out (const AST::InlineAsmOperand &operand)
ASTLoweringExpr::translate (*split_in_out_value.out_expr.get ())));
return split_in_out;
}
+
HIR::InlineAsmOperand
translate_operand_const (const AST::InlineAsmOperand &operand)
{
auto const_value = operand.get_const ();
- struct HIR::AnonConst anon_const (const_value.anon_const.id,
- std::unique_ptr<Expr> (
- ASTLoweringExpr::translate (
- *const_value.anon_const.expr.get ())));
- struct HIR::InlineAsmOperand::Const cnst
- {
- anon_const
- };
- return cnst;
+
+ auto inner_expr = ASTLoweringExpr::translate (const_value.anon_const);
+
+ // Like `ConstBlock`, we know this should only be an `AnonConst` - let's
+ // assert to make sure and static cast
+ rust_assert (inner_expr->get_expression_type () == Expr::ExprType::AnonConst);
+
+ auto anon_const = static_cast<AnonConst *> (inner_expr);
+
+ return HIR::InlineAsmOperand::Const{*anon_const};
}
HIR::InlineAsmOperand
@@ -1006,5 +1050,20 @@ ASTLoweringExpr::visit (AST::FormatArgs &fmt)
"FormatArgs lowering is not implemented yet");
}
+void
+ASTLoweringExpr::visit (AST::OffsetOf &offset_of)
+{
+ auto type = std::unique_ptr<Type> (
+ ASTLoweringType::translate (offset_of.get_type ()));
+
+ auto crate_num = mappings.get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, offset_of.get_node_id (),
+ mappings.get_next_hir_id (crate_num),
+ mappings.get_next_localdef_id (crate_num));
+
+ translated = new HIR::OffsetOf (std::move (type), offset_of.get_field (),
+ mapping, offset_of.get_locus ());
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h
index adedeb3..4eed4ec 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -21,6 +21,7 @@
#include "rust-ast-lower-base.h"
#include "rust-ast.h"
+#include "rust-expr.h"
namespace Rust {
namespace HIR {
@@ -82,6 +83,8 @@ public:
void visit (AST::IfLetExpr &expr) override;
void visit (AST::IfLetExprConseqElse &expr) override;
void visit (AST::BlockExpr &expr) override;
+ void visit (AST::AnonConst &expr) override;
+ void visit (AST::ConstBlock &expr) override;
void visit (AST::UnsafeBlockExpr &expr) override;
void visit (AST::PathInExpression &expr) override;
void visit (AST::QualifiedPathInExpression &expr) override;
@@ -108,7 +111,6 @@ public:
void visit (AST::FieldAccessExpr &expr) override;
void visit (AST::LoopExpr &expr) override;
void visit (AST::WhileLoopExpr &expr) override;
- void visit (AST::ForLoopExpr &expr) override;
void visit (AST::BreakExpr &expr) override;
void visit (AST::ContinueExpr &expr) override;
void visit (AST::BorrowExpr &expr) override;
@@ -124,8 +126,9 @@ public:
void visit (AST::InlineAsm &expr) override;
void visit (AST::LlvmInlineAsm &expr) override;
- // Extra visitor for FormatArgs nodes
+ // Extra visitor for builtin macro nodes
void visit (AST::FormatArgs &fmt) override;
+ void visit (AST::OffsetOf &offset_of) override;
private:
ASTLoweringExpr ();
diff --git a/gcc/rust/hir/rust-ast-lower-extern.h b/gcc/rust/hir/rust-ast-lower-extern.h
index 0105e38..3dca1b6 100644
--- a/gcc/rust/hir/rust-ast-lower-extern.h
+++ b/gcc/rust/hir/rust-ast-lower-extern.h
@@ -99,7 +99,7 @@ public:
= static_cast<AST::IdentifierPattern &> (param.get_pattern ());
Identifier param_name = param_kind == AST::Pattern::Kind::Identifier
? param_ident.get_ident ()
- : std::string ("_");
+ : Identifier ("_", param.get_locus ());
HIR::Type *param_type = ASTLoweringType::translate (param.get_type ());
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.cc b/gcc/rust/hir/rust-ast-lower-implitem.cc
index d815a71..5db11cb 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.cc
+++ b/gcc/rust/hir/rust-ast-lower-implitem.cc
@@ -138,7 +138,8 @@ ASTLowerImplItem::visit (AST::Function &function)
std::unique_ptr<HIR::Type> return_type
= function.has_return_type () ? std::unique_ptr<HIR::Type> (
- ASTLoweringType::translate (function.get_return_type ()))
+ ASTLoweringType::translate (function.get_return_type (), false,
+ true /* impl trait is allowed here*/))
: nullptr;
Defaultness defaultness
@@ -274,7 +275,16 @@ ASTLowerTraitItem::visit (AST::Function &func)
auto hir_param
= HIR::FunctionParam (mapping, std::move (translated_pattern),
std::move (translated_type), param.get_locus ());
- function_params.push_back (hir_param);
+ function_params.push_back (std::move (hir_param));
+ }
+
+ if (func.has_self_param ())
+ {
+ // insert mappings for self
+ // TODO: Is this correct ? Looks fishy
+ mappings.insert_hir_self_param (&*self_param);
+ mappings.insert_location (self_param->get_mappings ().get_hirid (),
+ self_param->get_locus ());
}
HIR::TraitFunctionDecl decl (func.get_function_name (),
@@ -300,14 +310,6 @@ ASTLowerTraitItem::visit (AST::Function &func)
= new HIR::TraitItemFunc (mapping, std::move (decl), std::move (block_expr),
func.get_outer_attrs (), func.get_locus ());
translated = trait_item;
- if (func.has_self_param ())
- {
- // insert mappings for self
- // TODO: Is this correct ? Looks fishy
- mappings.insert_hir_self_param (&*self_param);
- mappings.insert_location (self_param->get_mappings ().get_hirid (),
- self_param->get_locus ());
- }
// add the mappings for the function params at the end
for (auto &param : trait_item->get_decl ().get_function_params ())
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc
index f4396b5..4e5a747 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -217,7 +217,7 @@ ASTLoweringItem::visit (AST::StructStruct &struct_decl)
field.get_outer_attrs ());
if (struct_field_name_exists (fields, translated_field))
- break;
+ continue;
fields.push_back (std::move (translated_field));
}
@@ -367,7 +367,9 @@ ASTLoweringItem::visit (AST::ConstantItem &constant)
HIR::Visibility vis = translate_visibility (constant.get_visibility ());
HIR::Type *type = ASTLoweringType::translate (constant.get_type (), true);
- HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ());
+ HIR::Expr *expr = nullptr;
+ if (constant.has_expr ())
+ expr = ASTLoweringExpr::translate (constant.get_expr ());
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, constant.get_node_id (),
@@ -411,7 +413,8 @@ ASTLoweringItem::visit (AST::Function &function)
std::unique_ptr<HIR::Type> return_type
= function.has_return_type () ? std::unique_ptr<HIR::Type> (
- ASTLoweringType::translate (function.get_return_type ()))
+ ASTLoweringType::translate (function.get_return_type (), false,
+ true /* impl trait is allowed here*/))
: nullptr;
std::vector<HIR::FunctionParam> function_params;
@@ -494,7 +497,8 @@ ASTLoweringItem::visit (AST::InherentImpl &impl_block)
{
switch (generic_param->get_kind ())
{
- case HIR::GenericParam::GenericKind::TYPE: {
+ case HIR::GenericParam::GenericKind::TYPE:
+ {
const HIR::TypeParam &t
= static_cast<const HIR::TypeParam &> (*generic_param);
@@ -651,7 +655,8 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block)
{
switch (generic_param->get_kind ())
{
- case HIR::GenericParam::GenericKind::TYPE: {
+ case HIR::GenericParam::GenericKind::TYPE:
+ {
const HIR::TypeParam &t
= static_cast<const HIR::TypeParam &> (*generic_param);
@@ -729,6 +734,25 @@ ASTLoweringItem::visit (AST::MacroRulesDefinition &def)
lower_macro_definition (def);
}
+void
+ASTLoweringItem::visit (AST::ExternCrate &extern_crate)
+{
+ if (extern_crate.references_self ())
+ return;
+
+ auto &mappings = Analysis::Mappings::get ();
+ CrateNum num
+ = mappings.lookup_crate_name (extern_crate.get_referenced_crate ())
+ .value ();
+ AST::Crate &crate = mappings.get_ast_crate (num);
+
+ auto saved_crate_num = mappings.get_current_crate ();
+ mappings.set_current_crate (num);
+ auto lowered = ASTLowering::Resolve (crate);
+ mappings.insert_hir_crate (std::move (lowered));
+ mappings.set_current_crate (saved_crate_num);
+}
+
HIR::SimplePath
ASTLoweringSimplePath::translate (const AST::SimplePath &path)
{
diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h
index 4e142ed..dc75057 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -45,6 +45,7 @@ public:
void visit (AST::TraitImpl &impl_block) override;
void visit (AST::ExternBlock &extern_block) override;
void visit (AST::MacroRulesDefinition &rules_def) override;
+ void visit (AST::ExternCrate &extern_crate) override;
private:
ASTLoweringItem () : translated (nullptr) {}
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc
index b7a4c56..8aabcd8 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -23,7 +23,9 @@
namespace Rust {
namespace HIR {
-ASTLoweringPattern::ASTLoweringPattern () : translated (nullptr) {}
+ASTLoweringPattern::ASTLoweringPattern ()
+ : translated (nullptr), is_let_top_level (false)
+{}
HIR::Pattern *
ASTLoweringPattern::translate (AST::Pattern &pattern, bool is_let_top_level)
@@ -49,13 +51,18 @@ ASTLoweringPattern::visit (AST::IdentifierPattern &pattern)
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- std::unique_ptr<Pattern> to_bind;
+ std::unique_ptr<Pattern> subpattern;
+ if (pattern.has_subpattern ())
+ {
+ subpattern = std::unique_ptr<Pattern> (
+ ASTLoweringPattern::translate (pattern.get_subpattern ()));
+ }
translated
= new HIR::IdentifierPattern (mapping, pattern.get_ident (),
pattern.get_locus (), pattern.get_is_ref (),
pattern.get_is_mut () ? Mutability::Mut
: Mutability::Imm,
- std::move (to_bind));
+ std::move (subpattern));
}
void
@@ -74,13 +81,15 @@ ASTLoweringPattern::visit (AST::TupleStructPattern &pattern)
auto &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case AST::TupleStructItems::RANGE: {
+ case AST::TupleStructItems::RANGE:
+ {
// TODO
rust_unreachable ();
}
break;
- case AST::TupleStructItems::NO_RANGE: {
+ case AST::TupleStructItems::NO_RANGE:
+ {
AST::TupleStructItemsNoRange &items_no_range
= static_cast<AST::TupleStructItemsNoRange &> (items);
@@ -120,7 +129,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
HIR::StructPatternField *f = nullptr;
switch (field->get_item_type ())
{
- case AST::StructPatternField::ItemType::TUPLE_PAT: {
+ case AST::StructPatternField::ItemType::TUPLE_PAT:
+ {
auto &tuple
= static_cast<AST::StructPatternFieldTuplePat &> (*field);
@@ -140,7 +150,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
}
break;
- case AST::StructPatternField::ItemType::IDENT_PAT: {
+ case AST::StructPatternField::ItemType::IDENT_PAT:
+ {
AST::StructPatternFieldIdentPat &ident
= static_cast<AST::StructPatternFieldIdentPat &> (*field);
@@ -160,7 +171,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
}
break;
- case AST::StructPatternField::ItemType::IDENT: {
+ case AST::StructPatternField::ItemType::IDENT:
+ {
AST::StructPatternFieldIdent &ident
= static_cast<AST::StructPatternFieldIdent &> (*field.get ());
@@ -213,7 +225,8 @@ ASTLoweringPattern::visit (AST::TuplePattern &pattern)
std::unique_ptr<HIR::TuplePatternItems> items;
switch (pattern.get_items ().get_pattern_type ())
{
- case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
+ case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE:
+ {
AST::TuplePatternItemsMultiple &ref
= static_cast<AST::TuplePatternItemsMultiple &> (
pattern.get_items ());
@@ -221,7 +234,8 @@ ASTLoweringPattern::visit (AST::TuplePattern &pattern)
}
break;
- case AST::TuplePatternItems::TuplePatternItemType::RANGED: {
+ case AST::TuplePatternItems::TuplePatternItemType::RANGED:
+ {
AST::TuplePatternItemsRanged &ref
= static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ());
items = lower_tuple_pattern_ranged (ref);
@@ -309,10 +323,27 @@ void
ASTLoweringPattern::visit (AST::SlicePattern &pattern)
{
std::vector<std::unique_ptr<HIR::Pattern>> items;
- for (auto &p : pattern.get_items ())
+
+ switch (pattern.get_items ().get_pattern_type ())
{
- HIR::Pattern *item = ASTLoweringPattern::translate (*p);
- items.push_back (std::unique_ptr<HIR::Pattern> (item));
+ case AST::SlicePatternItems::SlicePatternItemType::NO_REST:
+ {
+ AST::SlicePatternItemsNoRest &ref
+ = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ());
+ for (auto &p : ref.get_patterns ())
+ {
+ HIR::Pattern *item = ASTLoweringPattern::translate (*p);
+ items.push_back (std::unique_ptr<HIR::Pattern> (item));
+ }
+ }
+ break;
+ case AST::SlicePatternItems::SlicePatternItemType::HAS_REST:
+ {
+ rust_error_at (pattern.get_locus (),
+ "lowering of slice patterns with rest elements are not "
+ "supported yet");
+ }
+ break;
}
auto crate_num = mappings.get_current_crate ();
diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc
index a678f18..1841576 100644
--- a/gcc/rust/hir/rust-ast-lower-type.cc
+++ b/gcc/rust/hir/rust-ast-lower-type.cc
@@ -209,10 +209,17 @@ ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path)
path.get_locus ());
}
+ASTLoweringType::ASTLoweringType (bool default_to_static_lifetime,
+ bool impl_trait_allowed)
+ : ASTLoweringBase (), default_to_static_lifetime (default_to_static_lifetime),
+ impl_trait_allowed (impl_trait_allowed), translated (nullptr)
+{}
+
HIR::Type *
-ASTLoweringType::translate (AST::Type &type, bool default_to_static_lifetime)
+ASTLoweringType::translate (AST::Type &type, bool default_to_static_lifetime,
+ bool impl_trait_allowed)
{
- ASTLoweringType resolver (default_to_static_lifetime);
+ ASTLoweringType resolver (default_to_static_lifetime, impl_trait_allowed);
type.accept_vis (resolver);
rust_assert (resolver.translated != nullptr);
@@ -260,7 +267,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype)
HIR::Type *param_type
= ASTLoweringType::translate (param.get_type (),
- default_to_static_lifetime);
+ default_to_static_lifetime,
+ impl_trait_allowed);
HIR::MaybeNamedParam p (param.get_name (), kind,
std::unique_ptr<HIR::Type> (param_type),
@@ -272,7 +280,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype)
if (fntype.has_return_type ())
{
return_type = ASTLoweringType::translate (fntype.get_return_type (),
- default_to_static_lifetime);
+ default_to_static_lifetime,
+ impl_trait_allowed);
}
auto crate_num = mappings.get_current_crate ();
@@ -292,8 +301,8 @@ ASTLoweringType::visit (AST::TupleType &tuple)
std::vector<std::unique_ptr<HIR::Type>> elems;
for (auto &e : tuple.get_elems ())
{
- HIR::Type *t
- = ASTLoweringType::translate (*e, default_to_static_lifetime);
+ HIR::Type *t = ASTLoweringType::translate (*e, default_to_static_lifetime,
+ impl_trait_allowed);
elems.push_back (std::unique_ptr<HIR::Type> (t));
}
@@ -323,7 +332,8 @@ ASTLoweringType::visit (AST::ArrayType &type)
{
HIR::Type *translated_type
= ASTLoweringType::translate (type.get_elem_type (),
- default_to_static_lifetime);
+ default_to_static_lifetime,
+ impl_trait_allowed);
HIR::Expr *array_size = ASTLoweringExpr::translate (type.get_size_expr ());
auto crate_num = mappings.get_current_crate ();
@@ -343,9 +353,9 @@ ASTLoweringType::visit (AST::ReferenceType &type)
HIR::Lifetime lifetime
= lower_lifetime (type.get_lifetime (), default_to_static_lifetime);
- HIR::Type *base_type
- = ASTLoweringType::translate (type.get_base_type (),
- default_to_static_lifetime);
+ HIR::Type *base_type = ASTLoweringType::translate (type.get_base_type (),
+ default_to_static_lifetime,
+ impl_trait_allowed);
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -364,7 +374,8 @@ ASTLoweringType::visit (AST::RawPointerType &type)
{
HIR::Type *base_type
= ASTLoweringType::translate (type.get_type_pointed_to (),
- default_to_static_lifetime);
+ default_to_static_lifetime,
+ impl_trait_allowed);
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -384,9 +395,9 @@ ASTLoweringType::visit (AST::RawPointerType &type)
void
ASTLoweringType::visit (AST::SliceType &type)
{
- HIR::Type *base_type
- = ASTLoweringType::translate (type.get_elem_type (),
- default_to_static_lifetime);
+ HIR::Type *base_type = ASTLoweringType::translate (type.get_elem_type (),
+ default_to_static_lifetime,
+ impl_trait_allowed);
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -463,7 +474,8 @@ void
ASTLoweringType::visit (AST::ParenthesisedType &type)
{
auto *inner = ASTLoweringType::translate (*type.get_type_in_parens (),
- default_to_static_lifetime);
+ default_to_static_lifetime,
+ impl_trait_allowed);
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -480,6 +492,9 @@ ASTLoweringType::visit (AST::ParenthesisedType &type)
void
ASTLoweringType::visit (AST::ImplTraitType &type)
{
+ if (!impl_trait_allowed)
+ emit_impl_trait_error (type.get_locus ());
+
std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
for (auto &bound : type.get_type_param_bounds ())
{
@@ -499,9 +514,12 @@ ASTLoweringType::visit (AST::ImplTraitType &type)
void
ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type)
{
+ if (!impl_trait_allowed)
+ emit_impl_trait_error (type.get_locus ());
+
std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
- auto b = ASTLoweringTypeBounds::translate (type.get_trait_bound ());
+ auto b = ASTLoweringTypeBounds::translate (*type.get_trait_bound ().get ());
bounds.push_back (std::unique_ptr<HIR::TypeParamBound> (b));
auto crate_num = mappings.get_current_crate ();
@@ -513,6 +531,15 @@ ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type)
= new HIR::ImplTraitType (mapping, std::move (bounds), type.get_locus ());
}
+void
+ASTLoweringType::emit_impl_trait_error (location_t locus)
+{
+ rich_location r (line_table, locus);
+ rust_error_at (r, ErrorCode::E0562,
+ "%<impl Trait%> not allowed outside of function and inherent "
+ "method return types");
+}
+
HIR::GenericParam *
ASTLowerGenericParam::translate (AST::GenericParam &param)
{
@@ -593,7 +620,8 @@ ASTLowerGenericParam::visit (AST::TypeParam &param)
translated
= new HIR::TypeParam (mapping, param.get_type_representation (),
param.get_locus (), std::move (type_param_bounds),
- std::move (type), param.get_outer_attrs ());
+ std::move (type), param.get_outer_attrs (),
+ param.from_impl_trait ());
}
HIR::TypeParamBound *
diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h
index 4efaeee..50f543a 100644
--- a/gcc/rust/hir/rust-ast-lower-type.h
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -66,7 +66,8 @@ class ASTLoweringType : public ASTLoweringBase
public:
static HIR::Type *translate (AST::Type &type,
- bool default_to_static_lifetime = false);
+ bool default_to_static_lifetime = false,
+ bool impl_trait_allowed = false);
void visit (AST::BareFunctionType &fntype) override;
void visit (AST::TupleType &tuple) override;
@@ -81,19 +82,17 @@ public:
void visit (AST::TraitObjectTypeOneBound &type) override;
void visit (AST::TraitObjectType &type) override;
void visit (AST::ParenthesisedType &type) override;
-
void visit (AST::ImplTraitType &type) override;
void visit (AST::ImplTraitTypeOneBound &type) override;
+ void emit_impl_trait_error (location_t locus);
+
private:
- ASTLoweringType (bool default_to_static_lifetime)
- : ASTLoweringBase (),
- default_to_static_lifetime (default_to_static_lifetime),
- translated (nullptr)
- {}
+ ASTLoweringType (bool default_to_static_lifetime, bool impl_trait_allowed);
/** Used when compiling const and static items. */
bool default_to_static_lifetime;
+ bool impl_trait_allowed;
HIR::Type *translated;
};
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index 76bd135..e6e327f 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -423,12 +423,6 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr)
}
void
-ASTLoweringExprWithBlock::visit (AST::ForLoopExpr &expr)
-{
- rust_unreachable ();
-}
-
-void
ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr)
{
HIR::Expr *branch_value
diff --git a/gcc/rust/hir/rust-ast-lower.h b/gcc/rust/hir/rust-ast-lower.h
index cc74082..0787ddf 100644
--- a/gcc/rust/hir/rust-ast-lower.h
+++ b/gcc/rust/hir/rust-ast-lower.h
@@ -28,16 +28,14 @@ namespace HIR {
/* Checks whether the name of a field already exists. Returns true
and produces an error if so. */
-bool
-struct_field_name_exists (std::vector<HIR::StructField> &fields,
- HIR::StructField &new_field);
+bool struct_field_name_exists (std::vector<HIR::StructField> &fields,
+ HIR::StructField &new_field);
/**
* Lowers a Visibility from the AST into an HIR Visibility, desugaring it in
* the process
*/
-Visibility
-translate_visibility (const AST::Visibility &vis);
+Visibility translate_visibility (const AST::Visibility &vis);
/**
* Main base class used for lowering AST to HIR.
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index cb32f68..a0cdcb2 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -92,7 +92,7 @@ Dump::go (HIR::Crate &e)
end ("Crate");
}
-Dump::Dump (std::ostream &stream) : stream (stream) {}
+Dump::Dump (std::ostream &stream) : beg_of_line (false), stream (stream) {}
/**
* Writes TEXT with a final newline if ENDLINE is true.
@@ -1297,6 +1297,31 @@ Dump::visit (BlockExpr &e)
}
void
+Dump::visit (AnonConst &e)
+{
+ begin ("AnonConst");
+ do_expr (e);
+
+ if (e.is_deferred ())
+ put_field ("inner", "_");
+ else
+ visit_field ("inner", e.get_inner_expr ());
+
+ end ("AnonConst");
+}
+
+void
+Dump::visit (ConstBlock &e)
+{
+ begin ("ConstBlock");
+ do_expr (e);
+
+ visit_field ("inner", e.get_const_expr ());
+
+ end ("ConstBlock");
+}
+
+void
Dump::visit (ContinueExpr &e)
{
begin ("ContinueExpr");
@@ -1507,13 +1532,91 @@ Dump::visit (AsyncBlockExpr &e)
void
Dump::visit (InlineAsm &e)
-{}
+{
+ begin ("InlineAsm");
+ do_expr (e);
+ for (auto &temp : e.get_template_ ())
+ {
+ put_field ("template", temp.string);
+ }
+
+ for (auto &temp_str : e.get_template_strs ())
+ {
+ put_field ("template_str", temp_str.symbol);
+ }
+
+ for (auto &operand : e.get_operands ())
+ {
+ switch (operand.get_register_type ())
+ {
+ case HIR::InlineAsmOperand::RegisterType::In:
+ {
+ const auto &in = operand.get_in ();
+ visit_field ("in expr", *in.expr);
+ break;
+ }
+ case HIR::InlineAsmOperand::RegisterType::Out:
+ {
+ const auto &out = operand.get_out ();
+ visit_field ("out expr", *out.expr);
+ break;
+ }
+ case HIR::InlineAsmOperand::RegisterType::InOut:
+ {
+ const auto &inout = operand.get_in_out ();
+ visit_field ("inout expr", *inout.expr);
+ break;
+ }
+ case HIR::InlineAsmOperand::RegisterType::SplitInOut:
+ {
+ const auto &inout = operand.get_split_in_out ();
+ begin ("Split in out");
+ visit_field ("in expr", *inout.in_expr);
+ visit_field ("out expr", *inout.out_expr);
+ end ("Split in out");
+
+ break;
+ }
+ case HIR::InlineAsmOperand::RegisterType::Const:
+ {
+ auto &cnst = operand.get_const ();
+ visit_field ("const expr", cnst.anon_const.get_inner_expr ());
+ break;
+ }
+ case HIR::InlineAsmOperand::RegisterType::Sym:
+ {
+ auto &sym = operand.get_sym ();
+ visit_field ("sym expr", *sym.expr);
+ break;
+ }
+ case HIR::InlineAsmOperand::RegisterType::Label:
+ {
+ auto &label = operand.get_label ();
+ put_field ("label name", label.label_name);
+ do_expr (*label.expr);
+ break;
+ }
+ }
+ }
+ end ("InlineAsm");
+}
void
Dump::visit (LlvmInlineAsm &e)
{}
void
+Dump::visit (OffsetOf &e)
+{
+ begin ("OffsetOf");
+
+ put_field ("type", e.get_type ().as_string ());
+ put_field ("field", e.get_field ());
+
+ end ("OffsetOf");
+}
+
+void
Dump::visit (TypeParam &e)
{
begin ("TypeParam");
@@ -1602,7 +1705,8 @@ Dump::visit (UseTreeGlob &e)
case UseTreeGlob::PathType::GLOBAL:
glob = "::*";
break;
- case UseTreeGlob::PathType::PATH_PREFIXED: {
+ case UseTreeGlob::PathType::PATH_PREFIXED:
+ {
path = e.get_path ().as_string ();
glob = "::*";
break;
@@ -1630,7 +1734,8 @@ Dump::visit (UseTreeList &e)
case UseTreeList::PathType::GLOBAL:
path_type = "::*";
break;
- case UseTreeList::PathType::PATH_PREFIXED: {
+ case UseTreeList::PathType::PATH_PREFIXED:
+ {
path = e.get_path ().as_string ();
path_type = "::*";
break;
@@ -1902,7 +2007,8 @@ Dump::visit (ConstantItem &e)
do_vis_item (e);
put_field ("identifier", e.get_identifier ().as_string ());
visit_field ("type", e.get_type ());
- visit_field ("const_expr", e.get_expr ());
+ if (e.has_expr ())
+ visit_field ("const_expr", e.get_expr ());
end ("ConstantItem");
}
@@ -2091,10 +2197,10 @@ Dump::visit (IdentifierPattern &e)
put_field ("is_ref", std::to_string (e.get_is_ref ()));
put_field ("mut", std::to_string (e.is_mut ()));
- if (e.has_pattern_to_bind ())
- put_field ("to_bind", e.get_to_bind ().as_string ());
+ if (e.has_subpattern ())
+ visit_field ("subpattern", e.get_subpattern ());
else
- put_field ("to_bind", "none");
+ put_field ("subpattern", "none");
end ("IdentifierPattern");
}
@@ -2172,7 +2278,7 @@ Dump::visit (StructPatternFieldIdentPat &e)
auto oa = e.get_outer_attrs ();
do_outer_attrs (oa);
put_field ("ident", e.get_identifier ().as_string ());
- put_field ("ident_pattern", e.get_pattern ().as_string ());
+ visit_field ("ident_pattern", e.get_pattern ());
end ("StructPatternFieldIdentPat");
}
@@ -2290,7 +2396,7 @@ Dump::visit (LetStmt &e)
auto oa = e.get_outer_attrs ();
do_outer_attrs (oa);
- put_field ("variable_pattern", e.get_pattern ().as_string ());
+ visit_field ("variable_pattern", e.get_pattern ());
if (e.has_type ())
visit_field ("type", e.get_type ());
diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h
index 45b1708..3e6ae30 100644
--- a/gcc/rust/hir/rust-hir-dump.h
+++ b/gcc/rust/hir/rust-hir-dump.h
@@ -146,6 +146,8 @@ private:
virtual void visit (FieldAccessExpr &) override;
virtual void visit (ClosureExpr &) override;
virtual void visit (BlockExpr &) override;
+ virtual void visit (AnonConst &) override;
+ virtual void visit (ConstBlock &) override;
virtual void visit (ContinueExpr &) override;
virtual void visit (BreakExpr &) override;
virtual void visit (RangeFromToExpr &) override;
@@ -167,6 +169,7 @@ private:
virtual void visit (AsyncBlockExpr &) override;
virtual void visit (InlineAsm &) override;
virtual void visit (LlvmInlineAsm &) override;
+ virtual void visit (OffsetOf &) override;
virtual void visit (TypeParam &) override;
virtual void visit (ConstGenericParam &) override;
@@ -252,7 +255,6 @@ private:
} // namespace Rust
// In the global namespace to make it easier to call from debugger
-void
-debug (Rust::HIR::FullVisitable &v);
+void debug (Rust::HIR::FullVisitable &v);
#endif // !RUST_HIR_DUMP_H
diff --git a/gcc/rust/hir/tree/rust-hir-expr-abstract.h b/gcc/rust/hir/tree/rust-hir-expr-abstract.h
index 5bc5d89..371daa8 100644
--- a/gcc/rust/hir/tree/rust-hir-expr-abstract.h
+++ b/gcc/rust/hir/tree/rust-hir-expr-abstract.h
@@ -43,7 +43,7 @@ public:
WITHOUT_BLOCK,
};
- enum ExprType
+ enum class ExprType
{
Lit,
Operator,
@@ -58,6 +58,8 @@ public:
FieldAccess,
Closure,
Block,
+ AnonConst,
+ ConstBlock,
Continue,
Break,
Range,
@@ -72,6 +74,7 @@ public:
Path,
InlineAsm,
LlvmInlineAsm,
+ OffsetOf,
};
BaseKind get_hir_kind () override final { return Node::BaseKind::EXPR; }
diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc b/gcc/rust/hir/tree/rust-hir-expr.cc
index 266c79c..14786ad 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.cc
+++ b/gcc/rust/hir/tree/rust-hir-expr.cc
@@ -17,6 +17,8 @@
// <http://www.gnu.org/licenses/>.
#include "rust-hir-expr.h"
+#include "rust-hir-map.h"
+#include "optional.h"
#include "rust-operators.h"
#include "rust-hir-stmt.h"
@@ -790,6 +792,61 @@ BlockExpr::operator= (BlockExpr const &other)
return *this;
}
+AnonConst::AnonConst (Analysis::NodeMapping mappings,
+ std::unique_ptr<Expr> &&expr, location_t locus)
+ : ExprWithBlock (std::move (mappings), {}), locus (locus),
+ kind (Kind::Explicit), expr (std::move (expr))
+{
+ rust_assert (this->expr.value ());
+}
+
+AnonConst::AnonConst (Analysis::NodeMapping mappings, location_t locus)
+ : ExprWithBlock (std::move (mappings), {}), locus (locus),
+ kind (Kind::DeferredInference), expr (tl::nullopt)
+{}
+
+AnonConst::AnonConst (const AnonConst &other)
+ : ExprWithBlock (other), locus (other.locus), kind (other.kind)
+{
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
+}
+
+AnonConst
+AnonConst::operator= (const AnonConst &other)
+{
+ ExprWithBlock::operator= (other);
+
+ locus = other.locus;
+ kind = other.kind;
+
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
+
+ return *this;
+}
+
+ConstBlock::ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr,
+ location_t locus, AST::AttrVec outer_attrs)
+ : ExprWithBlock (std::move (mappings), std::move (outer_attrs)),
+ expr (std::move (expr)), locus (locus)
+{}
+
+ConstBlock::ConstBlock (const ConstBlock &other)
+ : ExprWithBlock (other), expr (other.expr), locus (other.locus)
+{}
+
+ConstBlock
+ConstBlock::operator= (const ConstBlock &other)
+{
+ ExprWithBlock::operator= (other);
+
+ expr = other.expr;
+ locus = other.locus;
+
+ return *this;
+}
+
ContinueExpr::ContinueExpr (Analysis::NodeMapping mappings, location_t locus,
tl::optional<Lifetime> label,
AST::AttrVec outer_attribs)
@@ -1277,59 +1334,42 @@ AsyncBlockExpr::operator= (AsyncBlockExpr const &other)
OperatorExprMeta::OperatorExprMeta (HIR::CompoundAssignmentExpr &expr)
: node_mappings (expr.get_mappings ()),
lvalue_mappings (expr.get_expr ().get_mappings ()),
- locus (expr.get_locus ())
+ rvalue_mappings (expr.get_rhs ().get_mappings ()), locus (expr.get_locus ())
{}
OperatorExprMeta::OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr)
: node_mappings (expr.get_mappings ()),
lvalue_mappings (expr.get_expr ().get_mappings ()),
- locus (expr.get_locus ())
+ rvalue_mappings (expr.get_rhs ().get_mappings ()), locus (expr.get_locus ())
{}
OperatorExprMeta::OperatorExprMeta (HIR::NegationExpr &expr)
: node_mappings (expr.get_mappings ()),
lvalue_mappings (expr.get_expr ().get_mappings ()),
+ rvalue_mappings (Analysis::NodeMapping::get_error ()),
locus (expr.get_locus ())
{}
OperatorExprMeta::OperatorExprMeta (HIR::DereferenceExpr &expr)
: node_mappings (expr.get_mappings ()),
lvalue_mappings (expr.get_expr ().get_mappings ()),
+ rvalue_mappings (Analysis::NodeMapping::get_error ()),
locus (expr.get_locus ())
{}
OperatorExprMeta::OperatorExprMeta (HIR::ArrayIndexExpr &expr)
: node_mappings (expr.get_mappings ()),
lvalue_mappings (expr.get_array_expr ().get_mappings ()),
+ rvalue_mappings (expr.get_index_expr ().get_mappings ()),
locus (expr.get_locus ())
{}
OperatorExprMeta::OperatorExprMeta (HIR::ComparisonExpr &expr)
: node_mappings (expr.get_mappings ()),
lvalue_mappings (expr.get_expr ().get_mappings ()),
- locus (expr.get_locus ())
+ rvalue_mappings (expr.get_rhs ().get_mappings ()), locus (expr.get_locus ())
{}
-AnonConst::AnonConst (NodeId id, std::unique_ptr<Expr> expr)
- : id (id), expr (std::move (expr))
-{
- rust_assert (this->expr != nullptr);
-}
-
-AnonConst::AnonConst (const AnonConst &other)
-{
- id = other.id;
- expr = other.expr->clone_expr ();
-}
-
-AnonConst
-AnonConst::operator= (const AnonConst &other)
-{
- id = other.id;
- expr = other.expr->clone_expr ();
- return *this;
-}
-
InlineAsmOperand::In::In (
const tl::optional<struct AST::InlineAsmRegOrRegClass> &reg,
std::unique_ptr<Expr> expr)
@@ -1476,7 +1516,7 @@ InlineAsm::InlineAsm (location_t locus, bool is_global_asm,
std::vector<AST::TupleTemplateStr> template_strs,
std::vector<HIR::InlineAsmOperand> operands,
std::vector<AST::TupleClobber> clobber_abi,
- std::set<AST::InlineAsmOption> options,
+ std::set<AST::InlineAsm::Option> options,
Analysis::NodeMapping mappings,
AST::AttrVec outer_attribs)
: ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
@@ -1486,5 +1526,41 @@ InlineAsm::InlineAsm (location_t locus, bool is_global_asm,
clobber_abi (std::move (clobber_abi)), options (std::move (options))
{}
+OffsetOf &
+OffsetOf::operator= (const OffsetOf &other)
+{
+ ExprWithoutBlock::operator= (other);
+
+ type = other.type->clone_type ();
+ field = other.field;
+ loc = other.loc;
+
+ return *this;
+}
+
+ExprWithoutBlock *
+OffsetOf::clone_expr_without_block_impl () const
+{
+ return new OffsetOf (*this);
+}
+
+std::string
+OffsetOf::as_string () const
+{
+ return "OffsetOf(" + type->as_string () + ", " + field.as_string () + ")";
+}
+
+void
+OffsetOf::accept_vis (HIRExpressionVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+OffsetOf::accept_vis (HIRFullVisitor &vis)
+{
+ vis.visit (*this);
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index 375f474..61e3590 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -19,12 +19,15 @@
#ifndef RUST_HIR_EXPR_H
#define RUST_HIR_EXPR_H
+#include "rust-ast.h"
#include "rust-hir-expr-abstract.h"
#include "rust-hir-literal.h"
#include "rust-common.h"
#include "rust-hir-bound.h"
#include "rust-hir-attrs.h"
#include "rust-expr.h"
+#include "rust-hir-map.h"
+#include "rust-mapping-common.h"
namespace Rust {
namespace HIR {
@@ -1800,6 +1803,92 @@ protected:
}
};
+class AnonConst : public ExprWithBlock
+{
+public:
+ enum class Kind
+ {
+ Explicit,
+ DeferredInference
+ };
+
+ AnonConst (Analysis::NodeMapping mappings, std::unique_ptr<Expr> &&expr,
+ location_t locus = UNKNOWN_LOCATION);
+ AnonConst (Analysis::NodeMapping mappings,
+ location_t locus = UNKNOWN_LOCATION);
+ AnonConst (const AnonConst &other);
+ AnonConst operator= (const AnonConst &other);
+
+ std::string as_string () const override;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::AnonConst;
+ }
+
+ location_t get_locus () const override { return locus; }
+
+ Expr &get_inner_expr ()
+ {
+ rust_assert (kind == Kind::Explicit);
+ return *expr.value ();
+ }
+
+ const Expr &get_inner_expr () const
+ {
+ rust_assert (kind == Kind::Explicit);
+ return *expr.value ();
+ }
+
+ bool is_deferred () const { return kind == Kind::DeferredInference; }
+
+private:
+ location_t locus;
+ Kind kind;
+ tl::optional<std::unique_ptr<Expr>> expr;
+
+ AnonConst *clone_expr_with_block_impl () const override
+ {
+ return new AnonConst (*this);
+ }
+};
+
+class ConstBlock : public ExprWithBlock
+{
+public:
+ ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr,
+ location_t locus = UNKNOWN_LOCATION,
+ AST::AttrVec outer_attrs = {});
+ ConstBlock (const ConstBlock &other);
+ ConstBlock operator= (const ConstBlock &other);
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::string as_string () const override;
+
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::ConstBlock;
+ }
+
+ location_t get_locus () const override { return locus; }
+ AnonConst &get_const_expr () { return expr; }
+ const AnonConst &get_const_expr () const { return expr; }
+
+private:
+ AnonConst expr;
+ location_t locus;
+
+ ConstBlock *clone_expr_with_block_impl () const override
+ {
+ return new ConstBlock (*this);
+ }
+};
+
// HIR node representing continue expression within loops
class ContinueExpr : public ExprWithoutBlock
{
@@ -2631,6 +2720,8 @@ public:
Expr &get_guard_expr () { return *guard_expr; }
location_t get_locus () const { return locus; }
+
+ AST::AttrVec &get_outer_attrs () { return outer_attrs; }
};
/* A "match case" - a correlated match arm and resulting expression. Not
@@ -2823,6 +2914,22 @@ public:
OperatorExprMeta (HIR::ComparisonExpr &expr);
+ OperatorExprMeta (const OperatorExprMeta &other)
+ : node_mappings (other.node_mappings),
+ lvalue_mappings (other.lvalue_mappings),
+ rvalue_mappings (other.rvalue_mappings), locus (other.locus)
+ {}
+
+ OperatorExprMeta &operator= (const OperatorExprMeta &other)
+ {
+ node_mappings = other.node_mappings;
+ lvalue_mappings = other.lvalue_mappings;
+ rvalue_mappings = other.rvalue_mappings;
+ locus = other.locus;
+
+ return *this;
+ }
+
const Analysis::NodeMapping &get_mappings () const { return node_mappings; }
const Analysis::NodeMapping &get_lvalue_mappings () const
@@ -2830,11 +2937,22 @@ public:
return lvalue_mappings;
}
+ const Analysis::NodeMapping &get_rvalue_mappings () const
+ {
+ return rvalue_mappings;
+ }
+
+ bool has_rvalue_mappings () const
+ {
+ return rvalue_mappings.get_hirid () != UNKNOWN_HIRID;
+ }
+
location_t get_locus () const { return locus; }
private:
- const Analysis::NodeMapping node_mappings;
- const Analysis::NodeMapping lvalue_mappings;
+ Analysis::NodeMapping node_mappings;
+ Analysis::NodeMapping lvalue_mappings;
+ Analysis::NodeMapping rvalue_mappings;
location_t locus;
};
@@ -2892,18 +3010,6 @@ class InlineAsmRegClass
std::string placeholder;
};
-struct AnonConst
-{
- NodeId id;
- std::unique_ptr<Expr> expr;
-
- AnonConst (NodeId id, std::unique_ptr<Expr> expr);
-
- AnonConst (const AnonConst &other);
-
- AnonConst operator= (const AnonConst &other);
-};
-
class InlineAsmOperand
{
public:
@@ -2992,8 +3098,9 @@ public:
Label operator= (const struct Label &other);
};
-private:
using RegisterType = AST::InlineAsmOperand::RegisterType;
+
+private:
AST::InlineAsmOperand::RegisterType register_type;
tl::optional<struct In> in;
@@ -3037,13 +3144,24 @@ public:
RegisterType get_register_type () const { return register_type; }
// Potentially unsafe without get_register_type() check
- struct In get_in () const { return in.value (); }
- struct Out get_out () const { return out.value (); }
- struct InOut get_in_out () const { return in_out.value (); }
- struct SplitInOut get_split_in_out () const { return split_in_out.value (); }
- struct Const get_const () const { return cnst.value (); }
- struct Sym get_sym () const { return sym.value (); }
- struct Label get_label () const { return label.value (); }
+ const struct In &get_in () const { return in.value (); }
+ const struct Out &get_out () const { return out.value (); }
+ const struct InOut &get_in_out () const { return in_out.value (); }
+ const struct SplitInOut &get_split_in_out () const
+ {
+ return split_in_out.value ();
+ }
+ const struct Const &get_const () const { return cnst.value (); }
+ const struct Sym &get_sym () const { return sym.value (); }
+ const struct Label &get_label () const { return label.value (); }
+
+ struct In &get_in () { return in.value (); }
+ struct Out &get_out () { return out.value (); }
+ struct InOut &get_in_out () { return in_out.value (); }
+ struct SplitInOut &get_split_in_out () { return split_in_out.value (); }
+ struct Const &get_const () { return cnst.value (); }
+ struct Sym &get_sym () { return sym.value (); }
+ struct Label &get_label () { return label.value (); }
};
// Inline Assembly Node
@@ -3059,7 +3177,7 @@ public:
std::vector<AST::TupleTemplateStr> template_strs;
std::vector<HIR::InlineAsmOperand> operands;
std::vector<AST::TupleClobber> clobber_abi;
- std::set<AST::InlineAsmOption> options;
+ std::set<AST::InlineAsm::Option> options;
std::vector<location_t> line_spans;
@@ -3090,11 +3208,11 @@ public:
return template_strs;
}
- std::vector<HIR::InlineAsmOperand> get_operands () { return operands; }
+ std::vector<HIR::InlineAsmOperand> &get_operands () { return operands; }
std::vector<AST::TupleClobber> get_clobber_abi () { return clobber_abi; }
- std::set<AST::InlineAsmOption> get_options () { return options; }
+ std::set<AST::InlineAsm::Option> get_options () { return options; }
bool is_simple_asm ()
{
@@ -3113,11 +3231,47 @@ public:
std::vector<AST::TupleTemplateStr> template_strs,
std::vector<HIR::InlineAsmOperand> operands,
std::vector<AST::TupleClobber> clobber_abi,
- std::set<AST::InlineAsmOption> options,
+ std::set<AST::InlineAsm::Option> options,
Analysis::NodeMapping mappings,
AST::AttrVec outer_attribs = AST::AttrVec ());
};
+class OffsetOf : public ExprWithoutBlock
+{
+public:
+ OffsetOf (std::unique_ptr<Type> &&type, Identifier field,
+ Analysis::NodeMapping mappings, location_t loc)
+ : ExprWithoutBlock (mappings), type (std::move (type)), field (field),
+ loc (loc)
+ {}
+
+ OffsetOf (const OffsetOf &other)
+ : ExprWithoutBlock (other), type (other.type->clone_type ()),
+ field (other.field), loc (other.loc)
+ {}
+
+ OffsetOf &operator= (const OffsetOf &other);
+
+ ExprWithoutBlock *clone_expr_without_block_impl () const override;
+ std::string as_string () const override;
+
+ void accept_vis (HIRExpressionVisitor &vis) override;
+ void accept_vis (HIRFullVisitor &vis) override;
+
+ ExprType get_expression_type () const override { return ExprType::OffsetOf; }
+
+ location_t get_locus () const override { return loc; }
+
+ Type &get_type () { return *type; }
+ const Type &get_type () const { return *type; }
+ const Identifier &get_field () const { return field; }
+
+private:
+ std::unique_ptr<Type> type;
+ Identifier field;
+ location_t loc;
+};
+
struct LlvmOperand
{
std::string constraint;
diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h
index 1e313ec..57b3a4d 100644
--- a/gcc/rust/hir/tree/rust-hir-full-decls.h
+++ b/gcc/rust/hir/tree/rust-hir-full-decls.h
@@ -95,6 +95,8 @@ class FieldAccessExpr;
struct ClosureParam;
class ClosureExpr;
class BlockExpr;
+class AnonConst;
+class ConstBlock;
class ContinueExpr;
class BreakExpr;
class RangeExpr;
@@ -123,10 +125,10 @@ class AwaitExpr;
class AsyncBlockExpr;
class InlineAsmReg;
class InlineAsmRegClass;
-struct AnonConst;
class InlineAsmOperand;
class InlineAsm;
class LlvmInlineAsm;
+class OffsetOf;
// rust-stmt.h
class EmptyStmt;
diff --git a/gcc/rust/hir/tree/rust-hir-generic-param.h b/gcc/rust/hir/tree/rust-hir-generic-param.h
index 960de56..340b5c6 100644
--- a/gcc/rust/hir/tree/rust-hir-generic-param.h
+++ b/gcc/rust/hir/tree/rust-hir-generic-param.h
@@ -150,7 +150,7 @@ public:
location_t get_locus () const override final { return locus; };
- bool has_default_expression () { return default_expression != nullptr; }
+ bool has_default_expression () const { return default_expression != nullptr; }
std::string get_name () { return name; }
Type &get_type ()
@@ -160,6 +160,8 @@ public:
}
Expr &get_default_expression () { return *default_expression; }
+ const Expr &get_default_expression () const { return *default_expression; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/hir/tree/rust-hir-item.cc b/gcc/rust/hir/tree/rust-hir-item.cc
index 160f710..1406e7a 100644
--- a/gcc/rust/hir/tree/rust-hir-item.cc
+++ b/gcc/rust/hir/tree/rust-hir-item.cc
@@ -26,16 +26,18 @@ TypeParam::TypeParam (
Analysis::NodeMapping mappings, Identifier type_representation,
location_t locus,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
- tl::optional<std::unique_ptr<Type>> type, AST::AttrVec outer_attrs)
+ tl::optional<std::unique_ptr<Type>> type, AST::AttrVec outer_attrs,
+ bool was_impl_trait)
: GenericParam (mappings), outer_attrs (std::move (outer_attrs)),
type_representation (std::move (type_representation)),
type_param_bounds (std::move (type_param_bounds)), type (std::move (type)),
- locus (locus)
+ locus (locus), was_impl_trait (was_impl_trait)
{}
TypeParam::TypeParam (TypeParam const &other)
: GenericParam (other.mappings), outer_attrs (other.outer_attrs),
- type_representation (other.type_representation), locus (other.locus)
+ type_representation (other.type_representation), locus (other.locus),
+ was_impl_trait (other.was_impl_trait)
{
// guard to prevent null pointer dereference
if (other.has_type ())
@@ -55,6 +57,7 @@ TypeParam::operator= (TypeParam const &other)
outer_attrs = other.outer_attrs;
locus = other.locus;
mappings = other.mappings;
+ was_impl_trait = other.was_impl_trait;
// guard to prevent null pointer dereference
if (other.has_type ())
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 37f599c..d9df602 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -95,17 +95,11 @@ protected:
class TypeParam : public GenericParam
{
AST::AttrVec outer_attrs;
-
Identifier type_representation;
-
- // bool has_type_param_bounds;
- // TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
- type_param_bounds; // inlined form
-
+ std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
tl::optional<std::unique_ptr<Type>> type;
-
location_t locus;
+ bool was_impl_trait;
public:
// Returns whether the type of the type param has been specified.
@@ -121,9 +115,9 @@ public:
TypeParam (Analysis::NodeMapping mappings, Identifier type_representation,
location_t locus = UNDEF_LOCATION,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds
- = std::vector<std::unique_ptr<TypeParamBound>> (),
+ = {},
tl::optional<std::unique_ptr<Type>> type = tl::nullopt,
- AST::AttrVec outer_attrs = std::vector<AST::Attribute> ());
+ AST::AttrVec outer_attrs = {}, bool was_impl_trait = false);
// Copy constructor uses clone
TypeParam (TypeParam const &other);
@@ -154,6 +148,8 @@ public:
std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ();
+ bool from_impl_trait () const { return was_impl_trait; }
+
protected:
// Clone function implementation as (not pure) virtual method
TypeParam *clone_generic_param_impl () const override
@@ -213,6 +209,8 @@ public:
std::string as_string () const override;
+ location_t get_locus () const { return locus; }
+
void accept_vis (HIRFullVisitor &vis) override;
Lifetime &get_lifetime () { return lifetime; }
@@ -406,6 +404,8 @@ public:
const Lifetime &get_lifetime () const { return lifetime.value (); }
+ Lifetime &get_lifetime () { return lifetime.value (); }
+
std::string as_string () const;
location_t get_locus () const { return locus; }
@@ -1801,6 +1801,8 @@ public:
return *type;
}
+ bool has_expr () const { return const_expr != nullptr; }
+
Expr &get_expr () { return *const_expr; }
Identifier get_identifier () const { return identifier; }
diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h
index 3ce2662..4f296d8 100644
--- a/gcc/rust/hir/tree/rust-hir-path.h
+++ b/gcc/rust/hir/tree/rust-hir-path.h
@@ -41,11 +41,15 @@ public:
: segment_name (std::move (segment_name))
{}
- /* TODO: insert check in constructor for this? Or is this a semantic error
- * best handled then? */
+ PathIdentSegment (const PathIdentSegment &other)
+ : segment_name (other.segment_name)
+ {}
- /* TODO: does this require visitor? pretty sure this isn't polymorphic, but
- * not entirely sure */
+ PathIdentSegment &operator= (PathIdentSegment const &other)
+ {
+ segment_name = other.segment_name;
+ return *this;
+ }
// Creates an error PathIdentSegment.
static PathIdentSegment create_error () { return PathIdentSegment (""); }
@@ -128,6 +132,8 @@ public:
std::unique_ptr<Expr> &get_expression () { return expression; }
+ location_t get_locus () const { return locus; }
+
private:
std::unique_ptr<Expr> expression;
location_t locus;
@@ -146,7 +152,7 @@ public:
bool has_generic_args () const
{
return !(lifetime_args.empty () && type_args.empty ()
- && binding_args.empty ());
+ && binding_args.empty () && const_args.empty ());
}
GenericArgs (std::vector<Lifetime> lifetime_args,
diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h
index 5cc5c95..9c636ca 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -80,7 +80,7 @@ class IdentifierPattern : public Pattern
Identifier variable_ident;
bool is_ref;
Mutability mut;
- std::unique_ptr<Pattern> to_bind;
+ std::unique_ptr<Pattern> subpattern;
location_t locus;
Analysis::NodeMapping mappings;
@@ -88,15 +88,15 @@ public:
std::string as_string () const override;
// Returns whether the IdentifierPattern has a pattern to bind.
- bool has_pattern_to_bind () const { return to_bind != nullptr; }
+ bool has_subpattern () const { return subpattern != nullptr; }
// Constructor
IdentifierPattern (Analysis::NodeMapping mappings, Identifier ident,
location_t locus, bool is_ref = false,
Mutability mut = Mutability::Imm,
- std::unique_ptr<Pattern> to_bind = nullptr)
+ std::unique_ptr<Pattern> subpattern = nullptr)
: variable_ident (std::move (ident)), is_ref (is_ref), mut (mut),
- to_bind (std::move (to_bind)), locus (locus), mappings (mappings)
+ subpattern (std::move (subpattern)), locus (locus), mappings (mappings)
{}
// Copy constructor with clone
@@ -105,8 +105,8 @@ public:
mut (other.mut), locus (other.locus), mappings (other.mappings)
{
// fix to get prevent null pointer dereference
- if (other.to_bind != nullptr)
- to_bind = other.to_bind->clone_pattern ();
+ if (other.subpattern != nullptr)
+ subpattern = other.subpattern->clone_pattern ();
}
// Overload assignment operator to use clone
@@ -119,8 +119,8 @@ public:
mappings = other.mappings;
// fix to get prevent null pointer dereference
- if (other.to_bind != nullptr)
- to_bind = other.to_bind->clone_pattern ();
+ if (other.subpattern != nullptr)
+ subpattern = other.subpattern->clone_pattern ();
return *this;
}
@@ -133,7 +133,7 @@ public:
bool is_mut () const { return mut == Mutability::Mut; }
bool get_is_ref () const { return is_ref; }
- Pattern &get_to_bind () { return *to_bind; }
+ Pattern &get_subpattern () { return *subpattern; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRPatternVisitor &vis) override;
diff --git a/gcc/rust/hir/tree/rust-hir-visibility.h b/gcc/rust/hir/tree/rust-hir-visibility.h
index a750d88..9dd6ff2 100644
--- a/gcc/rust/hir/tree/rust-hir-visibility.h
+++ b/gcc/rust/hir/tree/rust-hir-visibility.h
@@ -73,6 +73,8 @@ public:
}
std::string as_string () const;
+
+ location_t get_locus () const { return locus; }
};
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.cc b/gcc/rust/hir/tree/rust-hir-visitor.cc
new file mode 100644
index 0000000..58c1e1a
--- /dev/null
+++ b/gcc/rust/hir/tree/rust-hir-visitor.cc
@@ -0,0 +1,1187 @@
+// Copyright (C) 2021-2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-expr.h"
+#include "rust-hir-full-decls.h"
+#include "rust-hir-visitor.h"
+#include "rust-hir-full.h"
+#include "rust-system.h"
+
+namespace Rust {
+namespace HIR {
+
+void
+DefaultHIRVisitor::walk (Lifetime &)
+{}
+
+void
+DefaultHIRVisitor::walk (LifetimeParam &lifetime_param)
+{
+ visit_outer_attrs (lifetime_param);
+ lifetime_param.get_lifetime ().accept_vis (*this);
+ for (Lifetime &lifetime_bound : lifetime_param.get_lifetime_bounds ())
+ lifetime_bound.accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_generic_args (GenericArgs &generic_args)
+{
+ for (auto &lifetime : generic_args.get_lifetime_args ())
+ lifetime.accept_vis (*this);
+ for (auto &type : generic_args.get_type_args ())
+ type->accept_vis (*this);
+ for (auto &binding : generic_args.get_binding_args ())
+ binding.get_type ().accept_vis (*this);
+ for (auto &const_arg : generic_args.get_const_args ())
+ const_arg.get_expression ()->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (PathInExpression &path_in_expr)
+{
+ visit_outer_attrs (path_in_expr);
+ if (!path_in_expr.is_lang_item ())
+ for (auto &segment : path_in_expr.get_segments ())
+ visit_path_expr_segment (segment);
+}
+
+void
+DefaultHIRVisitor::walk (TypePathSegment &)
+{}
+
+void
+DefaultHIRVisitor::walk (TypePathSegmentFunction &segment_function)
+{
+ TypePathFunction &function_path = segment_function.get_function_path ();
+ if (function_path.has_inputs ())
+ for (auto &param : function_path.get_params ())
+ param->accept_vis (*this);
+ if (function_path.has_return_type ())
+ function_path.get_return_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TypePathSegmentGeneric &segment_generic)
+{
+ if (segment_generic.has_generic_args ())
+ visit_generic_args (segment_generic.get_generic_args ());
+}
+
+void
+DefaultHIRVisitor::walk (TypePath &type_path)
+{
+ for (auto &segment : type_path.get_segments ())
+ segment->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_qualified_path_type (QualifiedPathType &path)
+{
+ path.get_type ().accept_vis (*this);
+ if (path.has_as_clause ())
+ path.get_trait ().accept_vis (*this);
+}
+
+// TODO: Implement visit_path_expr_segment
+void
+DefaultHIRVisitor::visit_path_expr_segment (PathExprSegment &segment)
+{
+ if (segment.has_generic_args ())
+ visit_generic_args (segment.get_generic_args ());
+}
+
+void
+DefaultHIRVisitor::walk (QualifiedPathInExpression &path_in_expr)
+{
+ visit_outer_attrs (path_in_expr);
+ visit_qualified_path_type (path_in_expr.get_path_type ());
+ for (auto &segment : path_in_expr.get_segments ())
+ visit_path_expr_segment (segment);
+}
+
+void
+DefaultHIRVisitor::walk (QualifiedPathInType &path_in_type)
+{
+ visit_qualified_path_type (path_in_type.get_path_type ());
+ path_in_type.get_associated_segment ().accept_vis (*this);
+ for (auto &segment : path_in_type.get_segments ())
+ segment->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (LiteralExpr &expr)
+{
+ visit_outer_attrs (expr);
+}
+
+void
+DefaultHIRVisitor::walk (BorrowExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (DereferenceExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ErrorPropagationExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (NegationExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ArithmeticOrLogicalExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_lhs ().accept_vis (*this);
+ expr.get_rhs ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ComparisonExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_lhs ().accept_vis (*this);
+ expr.get_rhs ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (LazyBooleanExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_lhs ().accept_vis (*this);
+ expr.get_rhs ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TypeCastExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_expr ().accept_vis (*this);
+ expr.get_type_to_convert_to ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (AssignmentExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_lhs ().accept_vis (*this);
+ expr.get_rhs ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (CompoundAssignmentExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_lhs ().accept_vis (*this);
+ expr.get_rhs ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (GroupedExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ expr.get_expr_in_parens ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ArrayElemsValues &elems)
+{
+ for (auto &elem : elems.get_values ())
+ elem->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ArrayElemsCopied &elems)
+{
+ elems.get_elem_to_copy ().accept_vis (*this);
+ elems.get_num_copies_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ArrayExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ expr.get_internal_elements ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ArrayIndexExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_array_expr ().accept_vis (*this);
+ expr.get_index_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ for (auto &elem : expr.get_tuple_elems ())
+ elem->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleIndexExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_tuple_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructExprStruct &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ expr.get_struct_name ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructExprFieldIdentifier &)
+{}
+
+void
+DefaultHIRVisitor::walk (StructExprFieldIdentifierValue &field)
+{
+ field.get_value ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructExprFieldIndexValue &field)
+{
+ field.get_value ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructExprStructFields &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ expr.get_struct_name ().accept_vis (*this);
+ if (expr.has_struct_base ())
+ {
+ StructBase &base = expr.get_struct_base ();
+ base.get_base ().accept_vis (*this);
+ }
+ for (auto &field : expr.get_fields ())
+ field->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructExprStructBase &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ expr.get_struct_name ().accept_vis (*this);
+ StructBase &base = expr.get_struct_base ();
+ base.get_base ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (CallExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_fnexpr ().accept_vis (*this);
+ for (auto &arg : expr.get_arguments ())
+ arg->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (MethodCallExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_receiver ().accept_vis (*this);
+ visit_path_expr_segment (expr.get_method_name ());
+ for (auto &arg : expr.get_arguments ())
+ arg->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (FieldAccessExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_receiver_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_closure_param (ClosureParam &param)
+{
+ visit_outer_attrs (param);
+ param.get_pattern ().accept_vis (*this);
+ if (param.has_type_given ())
+ {
+ param.get_type ().accept_vis (*this);
+ }
+}
+
+void
+DefaultHIRVisitor::walk (ClosureExpr &expr)
+{
+ visit_outer_attrs (expr);
+ for (auto &param : expr.get_params ())
+ visit_closure_param (param);
+ if (expr.has_return_type ())
+ expr.get_return_type ().accept_vis (*this);
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (BlockExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ for (auto &stmt : expr.get_statements ())
+ stmt->accept_vis (*this);
+ if (expr.has_expr ())
+ expr.get_final_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (AnonConst &expr)
+{
+ if (!expr.is_deferred ())
+ expr.get_inner_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ConstBlock &expr)
+{
+ expr.get_const_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ContinueExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_label ())
+ expr.get_label ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (BreakExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_label ())
+ expr.get_label ().accept_vis (*this);
+
+ if (expr.has_break_expr ())
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangeFromToExpr &expr)
+{
+ expr.get_from_expr ().accept_vis (*this);
+ expr.get_to_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangeFromExpr &expr)
+{
+ expr.get_from_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangeToExpr &expr)
+{
+ expr.get_to_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangeFullExpr &)
+{}
+
+void
+DefaultHIRVisitor::walk (RangeFromToInclExpr &expr)
+{
+ expr.get_from_expr ().accept_vis (*this);
+ expr.get_to_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangeToInclExpr &expr)
+{
+ expr.get_to_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ReturnExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_return_expr ())
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (UnsafeBlockExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_block_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_loop_label (LoopLabel &label)
+{
+ label.get_lifetime ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (LoopExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_loop_label ())
+ visit_loop_label (expr.get_loop_label ());
+ expr.get_loop_block ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (WhileLoopExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_loop_label ())
+ visit_loop_label (expr.get_loop_label ());
+ expr.get_predicate_expr ().accept_vis (*this);
+ expr.get_loop_block ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (WhileLetLoopExpr &expr)
+{
+ visit_outer_attrs (expr);
+ for (auto &pattern : expr.get_patterns ())
+ pattern->accept_vis (*this);
+ if (expr.has_loop_label ())
+ visit_loop_label (expr.get_loop_label ());
+ expr.get_cond ().accept_vis (*this);
+ expr.get_loop_block ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (IfExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_if_condition ().accept_vis (*this);
+ expr.get_if_block ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (IfExprConseqElse &expr)
+{
+ expr.IfExpr::accept_vis (*this);
+ expr.get_else_block ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_match_arm (MatchArm &arm)
+{
+ // visit_outer_attrs (arm);
+ for (auto &pattern : arm.get_patterns ())
+ pattern->accept_vis (*this);
+ if (arm.has_match_arm_guard ())
+ arm.get_guard_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_match_case (MatchCase &arm)
+{
+ visit_match_arm (arm.get_arm ());
+ arm.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (MatchExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ expr.get_scrutinee_expr ().accept_vis (*this);
+ for (auto &arm : expr.get_match_cases ())
+ visit_match_case (arm);
+}
+
+void
+DefaultHIRVisitor::walk (AwaitExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_awaited_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (AsyncBlockExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_block_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (InlineAsm &expr)
+{
+ visit_outer_attrs (expr);
+ auto &operands = expr.get_operands ();
+ using RegisterType = AST::InlineAsmOperand::RegisterType;
+ for (auto &operand : operands)
+ {
+ switch (operand.get_register_type ())
+ {
+ case RegisterType::In:
+ {
+ operand.get_in ().expr->accept_vis (*this);
+ break;
+ }
+ case RegisterType::Out:
+ {
+ operand.get_out ().expr->accept_vis (*this);
+ break;
+ }
+ case RegisterType::InOut:
+ {
+ operand.get_in_out ().expr->accept_vis (*this);
+ break;
+ }
+ case RegisterType::SplitInOut:
+ {
+ operand.get_split_in_out ().in_expr->accept_vis (*this);
+ operand.get_split_in_out ().out_expr->accept_vis (*this);
+ break;
+ }
+ case RegisterType::Const:
+ {
+ operand.get_const ().anon_const.get_inner_expr ().accept_vis (
+ *this);
+ break;
+ }
+ case RegisterType::Sym:
+ {
+ operand.get_sym ().expr->accept_vis (*this);
+ break;
+ }
+ case RegisterType::Label:
+ {
+ operand.get_label ().expr->accept_vis (*this);
+ break;
+ }
+ }
+ }
+}
+
+void
+DefaultHIRVisitor::walk (LlvmInlineAsm &expr)
+{
+ for (auto &output : expr.outputs)
+ output.expr->accept_vis (*this);
+ for (auto &input : expr.inputs)
+ input.expr->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (OffsetOf &expr)
+{
+ expr.get_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TypeParam &param)
+{
+ visit_outer_attrs (param);
+ for (auto &bounds : param.get_type_param_bounds ())
+ bounds->accept_vis (*this);
+ if (param.has_type ())
+ param.get_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ConstGenericParam &const_param)
+{
+ visit_outer_attrs (const_param);
+ const_param.get_type ().accept_vis (*this);
+ if (const_param.has_default_expression ())
+ const_param.get_default_expression ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (LifetimeWhereClauseItem &item)
+{
+ item.get_lifetime ().accept_vis (*this);
+ for (auto &bound : item.get_lifetime_bounds ())
+ bound.accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TypeBoundWhereClauseItem &item)
+{
+ for (auto &lifetime : item.get_for_lifetimes ())
+ lifetime.accept_vis (*this);
+ item.get_bound_type ().accept_vis (*this);
+ for (auto &param : item.get_type_param_bounds ())
+ param->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (Module &module)
+{
+ visit_outer_attrs (module);
+ visit_inner_attrs (module);
+ for (auto &item : module.get_items ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ExternCrate &crate)
+{
+ visit_outer_attrs (crate);
+}
+
+void
+DefaultHIRVisitor::walk (UseTreeGlob &)
+{}
+
+void
+DefaultHIRVisitor::walk (UseTreeList &)
+{}
+
+void
+DefaultHIRVisitor::walk (UseTreeRebind &)
+{}
+
+void
+DefaultHIRVisitor::walk (UseDeclaration &)
+{}
+
+void
+DefaultHIRVisitor::visit_function_param (FunctionParam &param)
+{
+ param.get_param_name ().accept_vis (*this);
+ param.get_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (Function &function)
+{
+ visit_outer_attrs (function);
+ for (auto &generic : function.get_generic_params ())
+ generic->accept_vis (*this);
+ for (auto &param : function.get_function_params ())
+ visit_function_param (param);
+ if (function.has_return_type ())
+ function.get_return_type ().accept_vis (*this);
+ if (function.has_where_clause ())
+ visit_where_clause (function.get_where_clause ());
+ function.get_definition ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TypeAlias &type_alias)
+{
+ visit_outer_attrs (type_alias);
+ for (auto &generic : type_alias.get_generic_params ())
+ generic->accept_vis (*this);
+ if (type_alias.has_where_clause ())
+ visit_where_clause (type_alias.get_where_clause ());
+ type_alias.get_type_aliased ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_struct_field (StructField &field)
+{
+ field.get_field_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructStruct &struct_item)
+{
+ visit_outer_attrs (struct_item);
+ for (auto &generic : struct_item.get_generic_params ())
+ generic->accept_vis (*this);
+ if (struct_item.has_where_clause ())
+ visit_where_clause (struct_item.get_where_clause ());
+ for (auto &field : struct_item.get_fields ())
+ visit_struct_field (field);
+}
+
+void
+DefaultHIRVisitor::walk (TupleStruct &tuple_struct)
+{
+ visit_outer_attrs (tuple_struct);
+ for (auto &generic : tuple_struct.get_generic_params ())
+ generic->accept_vis (*this);
+ if (tuple_struct.has_where_clause ())
+ visit_where_clause (tuple_struct.get_where_clause ());
+ for (auto &field : tuple_struct.get_fields ())
+ field.get_field_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (EnumItem &item)
+{
+ visit_outer_attrs (item);
+}
+
+void
+DefaultHIRVisitor::walk (EnumItemTuple &item_tuple)
+{
+ item_tuple.EnumItem::accept_vis (*this);
+ for (auto &field : item_tuple.get_tuple_fields ())
+ field.get_field_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (EnumItemStruct &item_struct)
+{
+ item_struct.EnumItem::accept_vis (*this);
+ for (auto &field : item_struct.get_struct_fields ())
+ field.get_field_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (EnumItemDiscriminant &item)
+{
+ item.EnumItem::accept_vis (*this);
+ item.get_discriminant_expression ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (Enum &enum_item)
+{
+ visit_outer_attrs (enum_item);
+ for (auto &generic : enum_item.get_generic_params ())
+ generic->accept_vis (*this);
+ if (enum_item.has_where_clause ())
+ visit_where_clause (enum_item.get_where_clause ());
+ for (auto &item : enum_item.get_variants ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (Union &union_item)
+{
+ visit_outer_attrs (union_item);
+ for (auto &generic : union_item.get_generic_params ())
+ generic->accept_vis (*this);
+ if (union_item.has_where_clause ())
+ visit_where_clause (union_item.get_where_clause ());
+ for (auto &variant : union_item.get_variants ())
+ visit_struct_field (variant);
+}
+
+void
+DefaultHIRVisitor::walk (ConstantItem &const_item)
+{
+ visit_outer_attrs (const_item);
+ const_item.get_type ().accept_vis (*this);
+ const_item.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StaticItem &static_item)
+{
+ visit_outer_attrs (static_item);
+ static_item.get_type ().accept_vis (*this);
+ static_item.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_self_param (SelfParam &self_param)
+{
+ if (self_param.has_lifetime ())
+ {
+ Lifetime lifetime = self_param.get_lifetime ();
+ lifetime.accept_vis (*this);
+ }
+ if (self_param.has_type ())
+ self_param.get_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TraitItemFunc &item)
+{
+ visit_outer_attrs (item);
+ TraitFunctionDecl &decl = item.get_decl ();
+ for (auto &generic : decl.get_generic_params ())
+ generic->accept_vis (*this);
+ if (decl.get_self ().has_value ())
+ visit_self_param (decl.get_self ().value ());
+ for (auto &param : decl.get_function_params ())
+ visit_function_param (param);
+ if (decl.has_return_type ())
+ decl.get_return_type ().accept_vis (*this);
+ if (decl.has_where_clause ())
+ visit_where_clause (decl.get_where_clause ());
+ if (item.has_definition ())
+ item.get_block_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TraitItemConst &item)
+{
+ visit_outer_attrs (item);
+ item.get_type ().accept_vis (*this);
+ if (item.has_expr ())
+ item.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TraitItemType &item)
+{
+ visit_outer_attrs (item);
+ for (auto &bound : item.get_type_param_bounds ())
+ bound->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_where_clause (const WhereClause &where_clause)
+{
+ for (auto &item : where_clause.get_items ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_where_clause (WhereClause &where_clause)
+{
+ for (auto &item : where_clause.get_items ())
+ {
+ item->accept_vis (*this);
+ }
+}
+
+void
+DefaultHIRVisitor::walk (WhereClauseItem &node)
+{}
+
+void
+DefaultHIRVisitor::walk (Trait &trait)
+{
+ visit_outer_attrs (trait);
+ for (auto &generic : trait.get_generic_params ())
+ generic->accept_vis (*this);
+ if (trait.has_where_clause ())
+ visit_where_clause (trait.get_where_clause ());
+ for (auto &bound : trait.get_type_param_bounds ())
+ bound->accept_vis (*this);
+ for (auto &item : trait.get_trait_items ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ImplBlock &impl)
+{
+ visit_outer_attrs (impl);
+ for (auto &generic : impl.get_generic_params ())
+ generic->accept_vis (*this);
+ if (impl.has_trait_ref ())
+ impl.get_trait_ref ().accept_vis (*this);
+ impl.get_type ().accept_vis (*this);
+ if (impl.has_where_clause ())
+ visit_where_clause (impl.get_where_clause ());
+ visit_inner_attrs (impl);
+ for (auto &item : impl.get_impl_items ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ExternalStaticItem &item)
+{
+ visit_outer_attrs (item);
+ item.get_item_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_named_function_param (NamedFunctionParam &param)
+{
+ param.get_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ExternalFunctionItem &item)
+{
+ visit_outer_attrs (item);
+ for (auto &generic : item.get_generic_params ())
+ generic->accept_vis (*this);
+ for (auto &param : item.get_function_params ())
+ visit_named_function_param (param);
+ if (item.has_return_type ())
+ item.get_return_type ().accept_vis (*this);
+ if (item.has_where_clause ())
+ visit_where_clause (item.get_where_clause ());
+}
+
+void
+DefaultHIRVisitor::walk (ExternalTypeItem &item)
+{
+ visit_outer_attrs (item);
+}
+
+void
+DefaultHIRVisitor::walk (ExternBlock &block)
+{
+ visit_outer_attrs (block);
+ visit_inner_attrs (block);
+ for (auto &item : block.get_extern_items ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (LiteralPattern &)
+{}
+
+void
+DefaultHIRVisitor::walk (IdentifierPattern &pattern)
+{
+ if (pattern.has_subpattern ())
+ pattern.get_subpattern ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (WildcardPattern &)
+{}
+
+void
+DefaultHIRVisitor::walk (RangePatternBoundLiteral &)
+{}
+
+void
+DefaultHIRVisitor::walk (RangePatternBoundPath &bound)
+{
+ bound.get_path ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangePatternBoundQualPath &bound)
+{
+ bound.get_qualified_path ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangePattern &pattern)
+{
+ pattern.get_lower_bound ().accept_vis (*this);
+ pattern.get_upper_bound ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ReferencePattern &pattern)
+{
+ pattern.get_referenced_pattern ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructPatternFieldTuplePat &field)
+{
+ visit_outer_attrs (field);
+ field.get_tuple_pattern ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructPatternFieldIdentPat &field)
+{
+ visit_outer_attrs (field);
+ field.get_pattern ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructPatternFieldIdent &field)
+{
+ visit_outer_attrs (field);
+}
+
+void
+DefaultHIRVisitor::walk (StructPattern &pattern)
+{
+ pattern.get_path ().accept_vis (*this);
+ StructPatternElements &elements = pattern.get_struct_pattern_elems ();
+ for (auto &field : elements.get_struct_pattern_fields ())
+ field->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleStructItemsNoRange &tuple_items)
+{
+ for (auto &item : tuple_items.get_patterns ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleStructItemsRange &tuple_items)
+{
+ for (auto &lower : tuple_items.get_lower_patterns ())
+ lower->accept_vis (*this);
+ for (auto &upper : tuple_items.get_upper_patterns ())
+ upper->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleStructPattern &pattern)
+{
+ pattern.get_path ().accept_vis (*this);
+ pattern.get_items ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TuplePatternItemsMultiple &tuple_items)
+{
+ for (auto &pattern : tuple_items.get_patterns ())
+ pattern->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TuplePatternItemsRanged &tuple_items)
+{
+ for (auto &lower : tuple_items.get_lower_patterns ())
+ lower->accept_vis (*this);
+ for (auto &upper : tuple_items.get_upper_patterns ())
+ upper->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TuplePattern &pattern)
+{
+ pattern.get_items ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (SlicePattern &pattern)
+{
+ for (auto &item : pattern.get_items ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (AltPattern &pattern)
+{
+ for (auto &item : pattern.get_alts ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (EmptyStmt &stmt)
+{}
+
+void
+DefaultHIRVisitor::walk (LetStmt &stmt)
+{
+ visit_outer_attrs (stmt);
+ stmt.get_pattern ().accept_vis (*this);
+ if (stmt.has_type ())
+ stmt.get_type ().accept_vis (*this);
+ if (stmt.has_init_expr ())
+ stmt.get_init_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ExprStmt &stmt)
+{
+ stmt.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TraitBound &bound)
+{
+ for (auto &lifetime : bound.get_for_lifetimes ())
+ lifetime.accept_vis (*this);
+ bound.get_path ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ImplTraitType &type)
+{
+ for (auto &bound : type.get_type_param_bounds ())
+ bound->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TraitObjectType &type)
+{
+ for (auto &bound : type.get_type_param_bounds ())
+ bound->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ParenthesisedType &type)
+{
+ type.get_type_in_parens ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleType &type)
+{
+ for (auto &elem : type.get_elems ())
+ elem->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (NeverType &type)
+{}
+
+void
+DefaultHIRVisitor::walk (RawPointerType &type)
+{
+ type.get_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ReferenceType &type)
+{
+ if (type.has_lifetime ())
+ type.get_lifetime ().accept_vis (*this);
+ type.get_base_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ArrayType &type)
+{
+ type.get_element_type ().accept_vis (*this);
+ type.get_size_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (SliceType &type)
+{
+ type.get_element_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (InferredType &type)
+{}
+
+void
+DefaultHIRVisitor::walk (BareFunctionType &type)
+{
+ for (auto &lifetime : type.get_for_lifetimes ())
+ lifetime.accept_vis (*this);
+ for (auto &param : type.get_function_params ())
+ param.get_type ().accept_vis (*this);
+ if (type.has_return_type ())
+ type.get_return_type ().accept_vis (*this);
+}
+
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h
index 283cc34..7996260 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.h
+++ b/gcc/rust/hir/tree/rust-hir-visitor.h
@@ -20,6 +20,7 @@
#define RUST_HIR_VISITOR_H
#include "rust-hir-full-decls.h"
+#include "rust-ast.h"
namespace Rust {
namespace HIR {
@@ -64,6 +65,8 @@ public:
virtual void visit (MethodCallExpr &expr) = 0;
virtual void visit (FieldAccessExpr &expr) = 0;
virtual void visit (BlockExpr &expr) = 0;
+ virtual void visit (AnonConst &expr) = 0;
+ virtual void visit (ConstBlock &expr) = 0;
virtual void visit (ClosureExpr &expr) = 0;
virtual void visit (ContinueExpr &expr) = 0;
virtual void visit (BreakExpr &expr) = 0;
@@ -85,6 +88,7 @@ public:
virtual void visit (AsyncBlockExpr &expr) = 0;
virtual void visit (InlineAsm &expr) = 0;
virtual void visit (LlvmInlineAsm &expr) = 0;
+ virtual void visit (OffsetOf &expr) = 0;
virtual void visit (TypeParam &param) = 0;
virtual void visit (ConstGenericParam &param) = 0;
virtual void visit (LifetimeWhereClauseItem &item) = 0;
@@ -153,6 +157,312 @@ public:
virtual void visit (BareFunctionType &type) = 0;
};
+class DefaultHIRVisitor : public HIRFullVisitor
+{
+public:
+ virtual void visit_where_clause (WhereClause &);
+ virtual void visit_where_clause (const WhereClause &);
+ virtual void visit_named_function_param (NamedFunctionParam &param);
+ virtual void visit_function_param (FunctionParam &param);
+ virtual void visit_self_param (SelfParam &param);
+ virtual void visit_match_arm (MatchArm &arm);
+ virtual void visit_match_case (MatchCase &);
+ virtual void visit_struct_field (StructField &field);
+ virtual void visit_generic_args (GenericArgs &args);
+ virtual void visit_qualified_path_type (QualifiedPathType &);
+ virtual void visit_path_expr_segment (PathExprSegment &segment);
+ virtual void visit_closure_param (ClosureParam &param);
+ virtual void visit_loop_label (LoopLabel &);
+
+ virtual void visit_attribute (AST::Attribute &attr)
+ {
+ visit_attribute (static_cast<const AST::Attribute &> (attr));
+ }
+ virtual void visit_attribute (const AST::Attribute &attr) {}
+ template <typename T> void visit_outer_attrs (T &node)
+ {
+ for (auto &attr : node.get_outer_attrs ())
+ visit_attribute (attr);
+ }
+ template <typename T> void visit_inner_attrs (T &node)
+ {
+ for (auto &attr : node.get_inner_attrs ())
+ visit_attribute (attr);
+ }
+
+ virtual void visit (WhereClauseItem &node) { walk (node); }
+
+ virtual void visit (Lifetime &node) override { walk (node); }
+ virtual void visit (LifetimeParam &node) override { walk (node); }
+ virtual void visit (PathInExpression &node) override { walk (node); }
+ virtual void visit (TypePathSegment &node) override { walk (node); }
+ virtual void visit (TypePathSegmentGeneric &node) override { walk (node); }
+ virtual void visit (TypePathSegmentFunction &node) override { walk (node); }
+ virtual void visit (TypePath &node) override { walk (node); }
+ virtual void visit (QualifiedPathInExpression &node) override { walk (node); }
+ virtual void visit (QualifiedPathInType &node) override { walk (node); }
+ virtual void visit (LiteralExpr &node) override { walk (node); }
+ virtual void visit (BorrowExpr &node) override { walk (node); }
+ virtual void visit (DereferenceExpr &node) override { walk (node); }
+ virtual void visit (ErrorPropagationExpr &node) override { walk (node); }
+ virtual void visit (NegationExpr &node) override { walk (node); }
+ virtual void visit (ArithmeticOrLogicalExpr &node) override { walk (node); }
+ virtual void visit (ComparisonExpr &node) override { walk (node); }
+ virtual void visit (LazyBooleanExpr &node) override { walk (node); }
+ virtual void visit (TypeCastExpr &node) override { walk (node); }
+ virtual void visit (AssignmentExpr &node) override { walk (node); }
+ virtual void visit (CompoundAssignmentExpr &node) override { walk (node); }
+ virtual void visit (GroupedExpr &node) override { walk (node); }
+ virtual void visit (ArrayElemsValues &node) override { walk (node); }
+ virtual void visit (ArrayElemsCopied &node) override { walk (node); }
+ virtual void visit (ArrayExpr &node) override { walk (node); }
+ virtual void visit (ArrayIndexExpr &node) override { walk (node); }
+ virtual void visit (TupleExpr &node) override { walk (node); }
+ virtual void visit (TupleIndexExpr &node) override { walk (node); }
+ virtual void visit (StructExprStruct &node) override { walk (node); }
+ virtual void visit (StructExprFieldIdentifier &node) override { walk (node); }
+ virtual void visit (StructExprFieldIdentifierValue &node) override
+ {
+ walk (node);
+ }
+ virtual void visit (StructExprFieldIndexValue &node) override { walk (node); }
+ virtual void visit (StructExprStructFields &node) override { walk (node); }
+ virtual void visit (StructExprStructBase &node) override { walk (node); }
+ virtual void visit (CallExpr &node) override { walk (node); }
+ virtual void visit (MethodCallExpr &node) override { walk (node); }
+ virtual void visit (FieldAccessExpr &node) override { walk (node); }
+ virtual void visit (ClosureExpr &node) override { walk (node); }
+ virtual void visit (BlockExpr &node) override { walk (node); }
+ virtual void visit (AnonConst &node) override { walk (node); }
+ virtual void visit (ConstBlock &node) override { walk (node); }
+ virtual void visit (ContinueExpr &node) override { walk (node); }
+ virtual void visit (BreakExpr &node) override { walk (node); }
+ virtual void visit (RangeFromToExpr &node) override { walk (node); }
+ virtual void visit (RangeFromExpr &node) override { walk (node); }
+ virtual void visit (RangeToExpr &node) override { walk (node); }
+ virtual void visit (RangeFullExpr &node) override { walk (node); }
+ virtual void visit (RangeFromToInclExpr &node) override { walk (node); }
+ virtual void visit (RangeToInclExpr &node) override { walk (node); }
+ virtual void visit (ReturnExpr &node) override { walk (node); }
+ virtual void visit (UnsafeBlockExpr &node) override { walk (node); }
+ virtual void visit (LoopExpr &node) override { walk (node); }
+ virtual void visit (WhileLoopExpr &node) override { walk (node); }
+ virtual void visit (WhileLetLoopExpr &node) override { walk (node); }
+ virtual void visit (IfExpr &node) override { walk (node); }
+ virtual void visit (IfExprConseqElse &node) override { walk (node); }
+ virtual void visit (MatchExpr &node) override { walk (node); }
+ virtual void visit (AwaitExpr &node) override { walk (node); }
+ virtual void visit (AsyncBlockExpr &node) override { walk (node); }
+ virtual void visit (InlineAsm &node) override { walk (node); }
+ virtual void visit (LlvmInlineAsm &node) override { walk (node); }
+ virtual void visit (OffsetOf &node) override { walk (node); }
+ virtual void visit (TypeParam &node) override { walk (node); }
+ virtual void visit (ConstGenericParam &node) override { walk (node); }
+ virtual void visit (LifetimeWhereClauseItem &node) override { walk (node); }
+ virtual void visit (TypeBoundWhereClauseItem &node) override { walk (node); }
+ virtual void visit (Module &node) override { walk (node); }
+ virtual void visit (ExternCrate &node) override { walk (node); }
+ virtual void visit (UseTreeGlob &node) override { walk (node); }
+ virtual void visit (UseTreeList &node) override { walk (node); }
+ virtual void visit (UseTreeRebind &node) override { walk (node); }
+ virtual void visit (UseDeclaration &node) override { walk (node); }
+ virtual void visit (Function &node) override { walk (node); }
+ virtual void visit (TypeAlias &node) override { walk (node); }
+ virtual void visit (StructStruct &node) override { walk (node); }
+ virtual void visit (TupleStruct &node) override { walk (node); }
+ virtual void visit (EnumItem &node) override { walk (node); }
+ virtual void visit (EnumItemTuple &node) override { walk (node); }
+ virtual void visit (EnumItemStruct &node) override { walk (node); }
+ virtual void visit (EnumItemDiscriminant &node) override { walk (node); }
+ virtual void visit (Enum &node) override { walk (node); }
+ virtual void visit (Union &node) override { walk (node); }
+ virtual void visit (ConstantItem &node) override { walk (node); }
+ virtual void visit (StaticItem &node) override { walk (node); }
+ virtual void visit (TraitItemFunc &node) override { walk (node); }
+ virtual void visit (TraitItemConst &node) override { walk (node); }
+ virtual void visit (TraitItemType &node) override { walk (node); }
+ virtual void visit (Trait &node) override { walk (node); }
+ virtual void visit (ImplBlock &node) override { walk (node); }
+ virtual void visit (ExternalStaticItem &node) override { walk (node); }
+ virtual void visit (ExternalFunctionItem &node) override { walk (node); }
+ virtual void visit (ExternalTypeItem &node) override { walk (node); }
+ virtual void visit (ExternBlock &node) override { walk (node); }
+ virtual void visit (LiteralPattern &node) override { walk (node); }
+ virtual void visit (IdentifierPattern &node) override { walk (node); }
+ virtual void visit (WildcardPattern &node) override { walk (node); }
+ virtual void visit (RangePatternBoundLiteral &node) override { walk (node); }
+ virtual void visit (RangePatternBoundPath &node) override { walk (node); }
+ virtual void visit (RangePatternBoundQualPath &node) override { walk (node); }
+ virtual void visit (RangePattern &node) override { walk (node); }
+ virtual void visit (ReferencePattern &node) override { walk (node); }
+ virtual void visit (StructPatternFieldTuplePat &node) override
+ {
+ walk (node);
+ }
+ virtual void visit (StructPatternFieldIdentPat &node) override
+ {
+ walk (node);
+ }
+ virtual void visit (StructPatternFieldIdent &node) override { walk (node); }
+ virtual void visit (StructPattern &node) override { walk (node); }
+ virtual void visit (TupleStructItemsNoRange &node) override { walk (node); }
+ virtual void visit (TupleStructItemsRange &node) override { walk (node); }
+ virtual void visit (TupleStructPattern &node) override { walk (node); }
+ virtual void visit (TuplePatternItemsMultiple &node) override { walk (node); }
+ virtual void visit (TuplePatternItemsRanged &node) override { walk (node); }
+ virtual void visit (TuplePattern &node) override { walk (node); }
+ virtual void visit (SlicePattern &node) override { walk (node); }
+ virtual void visit (AltPattern &node) override { walk (node); }
+ virtual void visit (EmptyStmt &node) override { walk (node); }
+ virtual void visit (LetStmt &node) override { walk (node); }
+ virtual void visit (ExprStmt &node) override { walk (node); }
+ virtual void visit (TraitBound &node) override { walk (node); }
+ virtual void visit (ImplTraitType &node) override { walk (node); }
+ virtual void visit (TraitObjectType &node) override { walk (node); }
+ virtual void visit (ParenthesisedType &node) override { walk (node); }
+ virtual void visit (TupleType &node) override { walk (node); }
+ virtual void visit (NeverType &node) override { walk (node); }
+ virtual void visit (RawPointerType &node) override { walk (node); }
+ virtual void visit (ReferenceType &node) override { walk (node); }
+ virtual void visit (ArrayType &node) override { walk (node); }
+ virtual void visit (SliceType &node) override { walk (node); }
+ virtual void visit (InferredType &node) override { walk (node); }
+ virtual void visit (BareFunctionType &node) override { walk (node); }
+
+protected:
+ virtual void walk (WhereClauseItem &) final;
+
+ virtual void walk (Lifetime &) final;
+ virtual void walk (LifetimeParam &) final;
+ virtual void walk (PathInExpression &) final;
+ virtual void walk (TypePathSegment &) final;
+ virtual void walk (TypePathSegmentGeneric &) final;
+ virtual void walk (TypePathSegmentFunction &) final;
+ virtual void walk (TypePath &) final;
+ virtual void walk (QualifiedPathInExpression &) final;
+ virtual void walk (QualifiedPathInType &) final;
+
+ virtual void walk (LiteralExpr &) final;
+ virtual void walk (BorrowExpr &) final;
+ virtual void walk (DereferenceExpr &) final;
+ virtual void walk (ErrorPropagationExpr &) final;
+ virtual void walk (NegationExpr &) final;
+ virtual void walk (ArithmeticOrLogicalExpr &) final;
+ virtual void walk (ComparisonExpr &) final;
+ virtual void walk (LazyBooleanExpr &) final;
+ virtual void walk (TypeCastExpr &) final;
+ virtual void walk (AssignmentExpr &) final;
+ virtual void walk (CompoundAssignmentExpr &) final;
+ virtual void walk (GroupedExpr &) final;
+
+ virtual void walk (ArrayElemsValues &) final;
+ virtual void walk (ArrayElemsCopied &) final;
+ virtual void walk (ArrayExpr &) final;
+ virtual void walk (ArrayIndexExpr &) final;
+ virtual void walk (TupleExpr &) final;
+ virtual void walk (TupleIndexExpr &) final;
+ virtual void walk (StructExprStruct &) final;
+ virtual void walk (StructExprFieldIdentifier &) final;
+ virtual void walk (StructExprFieldIdentifierValue &) final;
+ virtual void walk (StructExprFieldIndexValue &) final;
+ virtual void walk (StructExprStructFields &) final;
+ virtual void walk (StructExprStructBase &) final;
+ virtual void walk (CallExpr &) final;
+ virtual void walk (MethodCallExpr &) final;
+ virtual void walk (FieldAccessExpr &) final;
+ virtual void walk (ClosureExpr &) final;
+ virtual void walk (BlockExpr &) final;
+ virtual void walk (AnonConst &) final;
+ virtual void walk (ConstBlock &) final;
+ virtual void walk (ContinueExpr &) final;
+ virtual void walk (BreakExpr &) final;
+ virtual void walk (RangeFromToExpr &) final;
+ virtual void walk (RangeFromExpr &) final;
+ virtual void walk (RangeToExpr &) final;
+ virtual void walk (RangeFullExpr &) final;
+ virtual void walk (RangeFromToInclExpr &) final;
+ virtual void walk (RangeToInclExpr &) final;
+ virtual void walk (ReturnExpr &) final;
+ virtual void walk (UnsafeBlockExpr &) final;
+ virtual void walk (LoopExpr &) final;
+ virtual void walk (WhileLoopExpr &) final;
+ virtual void walk (WhileLetLoopExpr &) final;
+ virtual void walk (IfExpr &) final;
+ virtual void walk (IfExprConseqElse &) final;
+ virtual void walk (MatchExpr &) final;
+ virtual void walk (AwaitExpr &) final;
+ virtual void walk (AsyncBlockExpr &) final;
+ virtual void walk (InlineAsm &) final;
+ virtual void walk (LlvmInlineAsm &) final;
+ virtual void walk (OffsetOf &) final;
+ virtual void walk (TypeParam &) final;
+ virtual void walk (ConstGenericParam &) final;
+ virtual void walk (LifetimeWhereClauseItem &) final;
+ virtual void walk (TypeBoundWhereClauseItem &) final;
+ virtual void walk (Module &) final;
+ virtual void walk (ExternCrate &) final;
+ virtual void walk (UseTreeGlob &) final;
+ virtual void walk (UseTreeList &) final;
+ virtual void walk (UseTreeRebind &) final;
+ virtual void walk (UseDeclaration &) final;
+ virtual void walk (Function &) final;
+ virtual void walk (TypeAlias &) final;
+ virtual void walk (StructStruct &) final;
+ virtual void walk (TupleStruct &) final;
+ virtual void walk (EnumItem &) final;
+ virtual void walk (EnumItemTuple &) final;
+ virtual void walk (EnumItemStruct &) final;
+ virtual void walk (EnumItemDiscriminant &) final;
+ virtual void walk (Enum &) final;
+ virtual void walk (Union &) final;
+ virtual void walk (ConstantItem &) final;
+ virtual void walk (StaticItem &) final;
+ virtual void walk (TraitItemFunc &) final;
+ virtual void walk (TraitItemConst &) final;
+ virtual void walk (TraitItemType &) final;
+ virtual void walk (Trait &) final;
+ virtual void walk (ImplBlock &) final;
+ virtual void walk (ExternalStaticItem &) final;
+ virtual void walk (ExternalFunctionItem &) final;
+ virtual void walk (ExternalTypeItem &) final;
+ virtual void walk (ExternBlock &) final;
+ virtual void walk (LiteralPattern &) final;
+ virtual void walk (IdentifierPattern &) final;
+ virtual void walk (WildcardPattern &) final;
+ virtual void walk (RangePatternBoundLiteral &) final;
+ virtual void walk (RangePatternBoundPath &) final;
+ virtual void walk (RangePatternBoundQualPath &) final;
+ virtual void walk (RangePattern &) final;
+ virtual void walk (ReferencePattern &) final;
+ virtual void walk (StructPatternFieldTuplePat &) final;
+ virtual void walk (StructPatternFieldIdentPat &) final;
+ virtual void walk (StructPatternFieldIdent &) final;
+ virtual void walk (StructPattern &) final;
+ virtual void walk (TupleStructItemsNoRange &) final;
+ virtual void walk (TupleStructItemsRange &) final;
+ virtual void walk (TupleStructPattern &) final;
+ virtual void walk (TuplePatternItemsMultiple &) final;
+ virtual void walk (TuplePatternItemsRanged &) final;
+ virtual void walk (TuplePattern &) final;
+ virtual void walk (SlicePattern &) final;
+ virtual void walk (AltPattern &) final;
+ virtual void walk (EmptyStmt &) final;
+ virtual void walk (LetStmt &) final;
+ virtual void walk (ExprStmt &) final;
+ virtual void walk (TraitBound &) final;
+ virtual void walk (ImplTraitType &) final;
+ virtual void walk (TraitObjectType &) final;
+ virtual void walk (ParenthesisedType &) final;
+ virtual void walk (TupleType &) final;
+ virtual void walk (NeverType &) final;
+ virtual void walk (RawPointerType &) final;
+ virtual void walk (ReferenceType &) final;
+ virtual void walk (ArrayType &) final;
+ virtual void walk (SliceType &) final;
+ virtual void walk (InferredType &) final;
+ virtual void walk (BareFunctionType &) final;
+};
+
class HIRFullVisitorBase : public HIRFullVisitor
{
public:
@@ -201,6 +511,8 @@ public:
virtual void visit (FieldAccessExpr &) override {}
virtual void visit (ClosureExpr &) override {}
virtual void visit (BlockExpr &) override {}
+ virtual void visit (AnonConst &) override {}
+ virtual void visit (ConstBlock &) override {}
virtual void visit (ContinueExpr &) override {}
virtual void visit (BreakExpr &) override {}
virtual void visit (RangeFromToExpr &) override {}
@@ -222,6 +534,7 @@ public:
virtual void visit (AsyncBlockExpr &) override {}
virtual void visit (InlineAsm &) override {}
virtual void visit (LlvmInlineAsm &) override {}
+ virtual void visit (OffsetOf &) override {}
virtual void visit (TypeParam &) override {}
virtual void visit (ConstGenericParam &) override {}
@@ -427,6 +740,8 @@ public:
virtual void visit (MethodCallExpr &expr) = 0;
virtual void visit (FieldAccessExpr &expr) = 0;
virtual void visit (BlockExpr &expr) = 0;
+ virtual void visit (AnonConst &expr) = 0;
+ virtual void visit (ConstBlock &expr) = 0;
virtual void visit (ContinueExpr &expr) = 0;
virtual void visit (BreakExpr &expr) = 0;
virtual void visit (RangeFromToExpr &expr) = 0;
@@ -443,6 +758,7 @@ public:
virtual void visit (IfExpr &expr) = 0;
virtual void visit (IfExprConseqElse &expr) = 0;
virtual void visit (InlineAsm &expr) = 0;
+ virtual void visit (OffsetOf &expr) = 0;
virtual void visit (LlvmInlineAsm &expr) = 0;
virtual void visit (MatchExpr &expr) = 0;
virtual void visit (AwaitExpr &expr) = 0;
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index 093d8d5..a802e8c 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -577,7 +577,8 @@ UseTreeGlob::as_string () const
return "*";
case GLOBAL:
return "::*";
- case PATH_PREFIXED: {
+ case PATH_PREFIXED:
+ {
std::string path_str = path.as_string ();
return path_str + "::*";
}
@@ -600,7 +601,8 @@ UseTreeList::as_string () const
case GLOBAL:
path_str = "::{";
break;
- case PATH_PREFIXED: {
+ case PATH_PREFIXED:
+ {
path_str = path.as_string () + "::{";
break;
}
@@ -1048,6 +1050,36 @@ BlockExpr::as_string () const
}
std::string
+AnonConst::as_string () const
+{
+ std::string istr = indent_spaces (enter);
+ std::string str = istr + "AnonConst:\n" + istr;
+
+ if (expr.has_value ())
+ str += get_inner_expr ().as_string ();
+ else
+ str += "_";
+
+ str += "\n" + indent_spaces (out);
+
+ return str;
+}
+
+std::string
+ConstBlock::as_string () const
+{
+ std::string istr = indent_spaces (enter);
+
+ std::string str = istr + "ConstBlock:\n" + istr;
+
+ str += get_const_expr ().as_string ();
+
+ str += "\n" + indent_spaces (out);
+
+ return str;
+}
+
+std::string
TypeAlias::as_string () const
{
std::string str = VisItem::as_string ();
@@ -2579,9 +2611,9 @@ IdentifierPattern::as_string () const
str += variable_ident.as_string ();
- if (has_pattern_to_bind ())
+ if (has_subpattern ())
{
- str += " @ " + to_bind->as_string ();
+ str += " @ " + subpattern->as_string ();
}
return str;
@@ -4055,6 +4087,18 @@ BlockExpr::accept_vis (HIRFullVisitor &vis)
}
void
+AnonConst::accept_vis (HIRFullVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstBlock::accept_vis (HIRFullVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
ContinueExpr::accept_vis (HIRFullVisitor &vis)
{
vis.visit (*this);
@@ -5027,6 +5071,18 @@ BlockExpr::accept_vis (HIRExpressionVisitor &vis)
}
void
+AnonConst::accept_vis (HIRExpressionVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstBlock::accept_vis (HIRExpressionVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
Function::accept_vis (HIRStmtVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt
index 9cdbce2..d9824f1 100644
--- a/gcc/rust/lang.opt
+++ b/gcc/rust/lang.opt
@@ -205,7 +205,7 @@ EnumValue
Enum(frust_compile_until) String(end) Value(13)
frust-name-resolution-2.0
-Rust Var(flag_name_resolution_2_0)
+Rust Var(flag_name_resolution_2_0) Init(1)
Use the temporary and experimental name resolution pipeline instead of the stable one
frust-borrowcheck
@@ -229,4 +229,8 @@ frust-overflow-checks
Rust Var(flag_overflow_checks) Init(1)
Enable the overflow checks in code generation
+frust-assume-builtin-offset-of
+Rust Var(flag_assume_builtin_offset_of)
+Define a built-in offset_of macro in the compiler and assume it is present
+
; This comment is to ensure we retain the blank line above.
diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index b143e70..76ff15c 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -1317,7 +1317,8 @@ Lexer::parse_escape (char opening_char)
switch (current_char.value)
{
- case 'x': {
+ case 'x':
+ {
auto hex_escape_pair = parse_partial_hex_escape ();
long hexLong = hex_escape_pair.first;
additional_length_offset += hex_escape_pair.second;
@@ -1400,7 +1401,8 @@ Lexer::parse_utf8_escape ()
switch (current_char.value)
{
- case 'x': {
+ case 'x':
+ {
auto hex_escape_pair = parse_partial_hex_escape ();
long hexLong = hex_escape_pair.first;
additional_length_offset += hex_escape_pair.second;
@@ -1438,7 +1440,8 @@ Lexer::parse_utf8_escape ()
case '"':
output_char = '"';
break;
- case 'u': {
+ case 'u':
+ {
auto unicode_escape_pair = parse_partial_unicode_escape ();
output_char = unicode_escape_pair.first;
additional_length_offset += unicode_escape_pair.second;
@@ -1894,6 +1897,11 @@ Lexer::parse_raw_byte_string (location_t loc)
break;
}
}
+ else if (current_char.is_eof ())
+ {
+ rust_error_at (string_begin_locus, "unended raw byte string literal");
+ return Token::make (END_OF_FILE, get_current_location ());
+ }
else if (current_char.value > 127)
{
rust_error_at (get_current_location (),
@@ -1901,11 +1909,6 @@ Lexer::parse_raw_byte_string (location_t loc)
current_char.as_string ().c_str ());
current_char = 0;
}
- else if (current_char.is_eof ())
- {
- rust_error_at (string_begin_locus, "unended raw byte string literal");
- return Token::make (END_OF_FILE, get_current_location ());
- }
length++;
current_column++;
diff --git a/gcc/rust/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h
index 10293e0..383ffac 100644
--- a/gcc/rust/lex/rust-lex.h
+++ b/gcc/rust/lex/rust-lex.h
@@ -263,8 +263,7 @@ private:
#if CHECKING_P
namespace selftest {
-void
-rust_input_source_test ();
+void rust_input_source_test ();
} // namespace selftest
diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc
index 8493889..c396e10 100644
--- a/gcc/rust/lex/rust-token.cc
+++ b/gcc/rust/lex/rust-token.cc
@@ -20,6 +20,7 @@
#include "rust-token.h"
#include "rust-diagnostics.h"
#include "rust-unicode.h"
+#include "rust-ast.h"
namespace Rust {
// Hackily defined way to get token description for enum value using x-macros
@@ -88,7 +89,8 @@ token_id_keyword_string (TokenId id)
switch (id)
{
#define RS_TOKEN_KEYWORD_2015(id, str_ptr) \
- case id: { \
+ case id: \
+ { \
static const std::string str (str_ptr); \
return str; \
} \
@@ -234,6 +236,13 @@ escape_special_chars (const std::string &source, Context ctx)
} // namespace
+TokenPtr
+Token::make_identifier (const Identifier &ident)
+{
+ std::string str = ident;
+ return make_identifier (ident.get_locus (), std::move (str));
+}
+
std::string
Token::as_string () const
{
diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index c683ecd..2021aec 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -24,6 +24,10 @@
#include "rust-unicode.h"
namespace Rust {
+
+// used by Rust::Token::make_identifier
+class Identifier;
+
// "Primitive core types" in Rust - the different int and float types, as well
// as some others
enum PrimitiveCoreType
@@ -221,25 +225,20 @@ typedef std::shared_ptr<Token> TokenPtr;
typedef std::shared_ptr<const Token> const_TokenPtr;
// Hackily defined way to get token description for enum value using x-macros
-const char *
-get_token_description (TokenId id);
+const char *get_token_description (TokenId id);
/* Hackily defined way to get token description as a string for enum value using
* x-macros */
-const char *
-token_id_to_str (TokenId id);
+const char *token_id_to_str (TokenId id);
/* checks if a token is a keyword */
-bool
-token_id_is_keyword (TokenId id);
+bool token_id_is_keyword (TokenId id);
/* gets the string associated with a keyword */
-const std::string &
-token_id_keyword_string (TokenId id);
+const std::string &token_id_keyword_string (TokenId id);
// Get type hint description as a string.
-const char *
-get_type_hint_string (PrimitiveCoreType type);
+const char *get_type_hint_string (PrimitiveCoreType type);
/* Normalize string if a token is a identifier */
-std::string
-nfc_normalize_token_string (location_t loc, TokenId id, const std::string &str);
+std::string nfc_normalize_token_string (location_t loc, TokenId id,
+ const std::string &str);
// Represents a single token. Create using factory static methods.
class Token
@@ -329,6 +328,8 @@ public:
return TokenPtr (new Token (IDENTIFIER, locus, std::move (str)));
}
+ static TokenPtr make_identifier (const Identifier &ident);
+
// Makes and returns a new TokenPtr of type INT_LITERAL.
static TokenPtr make_int (location_t locus, std::string &&str,
PrimitiveCoreType type_hint = CORETYPE_UNKNOWN)
diff --git a/gcc/rust/metadata/rust-export-metadata.cc b/gcc/rust/metadata/rust-export-metadata.cc
index 771bec6..1829a85 100644
--- a/gcc/rust/metadata/rust-export-metadata.cc
+++ b/gcc/rust/metadata/rust-export-metadata.cc
@@ -263,8 +263,7 @@ PublicInterface::write_to_path (const std::string &path) const
FILE *nfd = fopen (path.c_str (), "wb");
if (nfd == NULL)
{
- rust_error_at (UNDEF_LOCATION,
- "failed to open file %qs for writing: %s",
+ rust_error_at (UNDEF_LOCATION, "failed to open file %qs for writing: %s",
path.c_str (), xstrerror (errno));
return;
}
diff --git a/gcc/rust/metadata/rust-import-archive.cc b/gcc/rust/metadata/rust-import-archive.cc
index cf24607..f64de4e 100644
--- a/gcc/rust/metadata/rust-import-archive.cc
+++ b/gcc/rust/metadata/rust-import-archive.cc
@@ -683,7 +683,7 @@ public:
const Header &operator* () const { return this->header_; }
- const Header *operator-> () const { return &this->header_; }
+ const Header *operator->() const { return &this->header_; }
Archive_iterator &operator++ ()
{
diff --git a/gcc/rust/metadata/rust-imports.h b/gcc/rust/metadata/rust-imports.h
index a497c67..65a2af1 100644
--- a/gcc/rust/metadata/rust-imports.h
+++ b/gcc/rust/metadata/rust-imports.h
@@ -11,8 +11,7 @@
namespace Rust {
-extern void
-add_search_path (const std::string &path);
+extern void add_search_path (const std::string &path);
class Import
{
diff --git a/gcc/rust/parse/rust-cfg-parser.h b/gcc/rust/parse/rust-cfg-parser.h
index 0d64016..61db240 100644
--- a/gcc/rust/parse/rust-cfg-parser.h
+++ b/gcc/rust/parse/rust-cfg-parser.h
@@ -36,15 +36,14 @@ namespace Rust {
*
* @return false if the given input was invalid, true otherwise
*/
-bool
-parse_cfg_option (std::string &input, std::string &key, std::string &value);
+bool parse_cfg_option (std::string &input, std::string &key,
+ std::string &value);
} // namespace Rust
#if CHECKING_P
namespace selftest {
-extern void
-rust_cfg_parser_test (void);
+extern void rust_cfg_parser_test (void);
} // namespace selftest
#endif // CHECKING_P
diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/parse/rust-parse-impl-lexer.cc
index 2703438..fec91e8 100644
--- a/gcc/rust/ast/rust-macro.cc
+++ b/gcc/rust/parse/rust-parse-impl-lexer.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
+// Copyright (C) 2025 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -16,10 +16,10 @@
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-#include "rust-macro.h"
+#include "rust-parse-impl.h"
namespace Rust {
-namespace AST {
-} // namespace AST
+template class Parser<Lexer>;
+
} // namespace Rust
diff --git a/gcc/rust/parse/rust-parse-impl-macro.cc b/gcc/rust/parse/rust-parse-impl-macro.cc
new file mode 100644
index 0000000..e632887
--- /dev/null
+++ b/gcc/rust/parse/rust-parse-impl-macro.cc
@@ -0,0 +1,26 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-parse-impl.h"
+#include "rust-macro-invoc-lexer.h"
+
+namespace Rust {
+
+template class Parser<MacroInvocLexer>;
+
+} // namespace Rust
diff --git a/gcc/rust/parse/rust-parse-impl-proc-macro.cc b/gcc/rust/parse/rust-parse-impl-proc-macro.cc
new file mode 100644
index 0000000..edc484f
--- /dev/null
+++ b/gcc/rust/parse/rust-parse-impl-proc-macro.cc
@@ -0,0 +1,34 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-parse-impl.h"
+#include "rust-proc-macro-invoc-lexer.h"
+
+namespace Rust {
+
+template std::unique_ptr<AST::Item>
+Parser<ProcMacroInvocLexer>::parse_item (bool);
+
+template std::unique_ptr<AST::Stmt>
+ Parser<ProcMacroInvocLexer>::parse_stmt (ParseRestrictions);
+
+// instantiate entire class (or just more functions) if necessary
+
+// template class Parser<ProcMacroInvocLexer>;
+
+} // namespace Rust
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 9dda231..14bccbd 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -19,13 +19,17 @@
/* Template implementation for Rust::Parser. Previously in rust-parse.cc (before
* Parser was template). Separated from rust-parse.h for readability. */
-/* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h
+/* DO NOT INCLUDE ANYWHERE - this is automatically included
+ * by rust-parse-impl-*.cc
* This is also the reason why there are no include guards. */
+#include "expected.h"
+#include "rust-ast.h"
#include "rust-common.h"
#include "rust-expr.h"
#include "rust-item.h"
#include "rust-common.h"
+#include "rust-parse.h"
#include "rust-token.h"
#define INCLUDE_ALGORITHM
#include "rust-diagnostics.h"
@@ -227,19 +231,22 @@ Parser<ManagedTokenSource>::skip_generics_right_angle ()
// this is good - skip token
lexer.skip_token ();
return true;
- case RIGHT_SHIFT: {
+ case RIGHT_SHIFT:
+ {
// new implementation that should be better
lexer.split_current_token (RIGHT_ANGLE, RIGHT_ANGLE);
lexer.skip_token ();
return true;
}
- case GREATER_OR_EQUAL: {
+ case GREATER_OR_EQUAL:
+ {
// new implementation that should be better
lexer.split_current_token (RIGHT_ANGLE, EQUAL);
lexer.skip_token ();
return true;
}
- case RIGHT_SHIFT_EQ: {
+ case RIGHT_SHIFT_EQ:
+ {
// new implementation that should be better
lexer.split_current_token (RIGHT_ANGLE, GREATER_OR_EQUAL);
lexer.skip_token ();
@@ -651,10 +658,7 @@ Parser<ManagedTokenSource>::parse_simple_path ()
// Parse all other simple path segments
while (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION)
{
- // Skip scope resolution operator
- lexer.skip_token ();
-
- AST::SimplePathSegment new_segment = parse_simple_path_segment ();
+ AST::SimplePathSegment new_segment = parse_simple_path_segment (1);
// Return path as currently constructed if segment in error state.
if (new_segment.is_error ())
@@ -682,35 +686,36 @@ Parser<ManagedTokenSource>::parse_simple_path ()
}
/* Parses a single SimplePathSegment (does not handle the scope resolution
- * operators) */
+ * operators)
+ * Starts parsing at an offset of base_peek */
template <typename ManagedTokenSource>
AST::SimplePathSegment
-Parser<ManagedTokenSource>::parse_simple_path_segment ()
+Parser<ManagedTokenSource>::parse_simple_path_segment (int base_peek)
{
using namespace Values;
- const_TokenPtr t = lexer.peek_token ();
+ const_TokenPtr t = lexer.peek_token (base_peek);
switch (t->get_id ())
{
case IDENTIFIER:
- lexer.skip_token ();
+ lexer.skip_token (base_peek);
return AST::SimplePathSegment (t->get_str (), t->get_locus ());
case SUPER:
- lexer.skip_token ();
+ lexer.skip_token (base_peek);
return AST::SimplePathSegment (Keywords::SUPER, t->get_locus ());
case SELF:
- lexer.skip_token ();
+ lexer.skip_token (base_peek);
return AST::SimplePathSegment (Keywords::SELF, t->get_locus ());
case CRATE:
- lexer.skip_token ();
+ lexer.skip_token (base_peek);
return AST::SimplePathSegment (Keywords::CRATE, t->get_locus ());
case DOLLAR_SIGN:
- if (lexer.peek_token (1)->get_id () == CRATE)
+ if (lexer.peek_token (base_peek + 1)->get_id () == CRATE)
{
- lexer.skip_token (1);
+ lexer.skip_token (base_peek + 1);
return AST::SimplePathSegment ("$crate", t->get_locus ());
}
@@ -790,7 +795,8 @@ Parser<ManagedTokenSource>::parse_attr_input ()
{
case LEFT_PAREN:
case LEFT_SQUARE:
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// must be a delimited token tree, so parse that
std::unique_ptr<AST::AttrInput> input_tree (
new AST::DelimTokenTree (parse_delim_token_tree ()));
@@ -799,7 +805,8 @@ Parser<ManagedTokenSource>::parse_attr_input ()
return input_tree;
}
- case EQUAL: {
+ case EQUAL:
+ {
// = LiteralExpr
lexer.skip_token ();
@@ -877,7 +884,10 @@ Parser<ManagedTokenSource>::parse_attr_input ()
return attr_input_lit;
}
break;
+ case RIGHT_PAREN:
case RIGHT_SQUARE:
+ case RIGHT_CURLY:
+ case END_OF_FILE:
// means AttrInput is missing, which is allowed
return nullptr;
default:
@@ -2117,7 +2127,8 @@ Parser<ManagedTokenSource>::parse_macro_match ()
{
case LEFT_PAREN:
case LEFT_SQUARE:
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// must be macro matcher as delimited
AST::MacroMatcher matcher = parse_macro_matcher ();
if (matcher.is_error ())
@@ -2131,7 +2142,8 @@ Parser<ManagedTokenSource>::parse_macro_match ()
return std::unique_ptr<AST::MacroMatcher> (
new AST::MacroMatcher (std::move (matcher)));
}
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
// have to do more lookahead to determine if fragment or repetition
const_TokenPtr t2 = lexer.peek_token (1);
switch (t2->get_id ())
@@ -2402,7 +2414,8 @@ Parser<ManagedTokenSource>::parse_visibility ()
skip_token (RIGHT_PAREN);
return AST::Visibility::create_super (path_loc, vis_loc);
- case IN: {
+ case IN:
+ {
lexer.skip_token ();
// parse the "in" path as well
@@ -2466,7 +2479,8 @@ Parser<ManagedTokenSource>::parse_module (AST::Visibility vis,
new AST::Module (std::move (name), std::move (vis),
std::move (outer_attrs), locus, safety,
lexer.get_filename (), inline_module_stack));
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
lexer.skip_token ();
// parse inner attributes
@@ -2730,7 +2744,8 @@ Parser<ManagedTokenSource>::parse_use_tree ()
return std::unique_ptr<AST::UseTreeGlob> (
new AST::UseTreeGlob (AST::UseTreeGlob::NO_PATH,
AST::SimplePath::create_empty (), locus));
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// nested tree UseTree type
lexer.skip_token ();
@@ -2794,58 +2809,12 @@ Parser<ManagedTokenSource>::parse_use_tree ()
}
else
{
- /* Due to aforementioned implementation issues, the trailing :: token is
- * consumed by the path, so it can not be used as a disambiguator.
- * NOPE, not true anymore - TODO what are the consequences of this? */
-
const_TokenPtr t = lexer.peek_token ();
+
switch (t->get_id ())
{
- case ASTERISK:
- // glob UseTree type
- lexer.skip_token ();
-
- return std::unique_ptr<AST::UseTreeGlob> (
- new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED,
- std::move (path), locus));
- case LEFT_CURLY: {
- // nested tree UseTree type
- lexer.skip_token ();
-
- std::vector<std::unique_ptr<AST::UseTree>> use_trees;
-
- // TODO: think of better control structure
- const_TokenPtr t = lexer.peek_token ();
- while (t->get_id () != RIGHT_CURLY)
- {
- std::unique_ptr<AST::UseTree> use_tree = parse_use_tree ();
- if (use_tree == nullptr)
- {
- break;
- }
-
- use_trees.push_back (std::move (use_tree));
-
- if (lexer.peek_token ()->get_id () != COMMA)
- break;
-
- lexer.skip_token ();
- t = lexer.peek_token ();
- }
-
- // skip end curly delimiter
- if (!skip_token (RIGHT_CURLY))
- {
- // skip after somewhere?
- return nullptr;
- }
-
- return std::unique_ptr<AST::UseTreeList> (
- new AST::UseTreeList (AST::UseTreeList::PATH_PREFIXED,
- std::move (path), std::move (use_trees),
- locus));
- }
- case AS: {
+ case AS:
+ {
// rebind UseTree type
lexer.skip_token ();
@@ -2884,16 +2853,72 @@ Parser<ManagedTokenSource>::parse_use_tree ()
// don't skip semicolon - handled in parse_use_tree
// lexer.skip_token();
-
- return std::unique_ptr<AST::UseTreeRebind> (
- new AST::UseTreeRebind (AST::UseTreeRebind::NONE, std::move (path),
- locus));
case COMMA:
case RIGHT_CURLY:
// this may occur in recursive calls - assume it is ok and ignore it
return std::unique_ptr<AST::UseTreeRebind> (
new AST::UseTreeRebind (AST::UseTreeRebind::NONE, std::move (path),
locus));
+ case SCOPE_RESOLUTION:
+ // keep going
+ break;
+ default:
+ add_error (Error (t->get_locus (),
+ "unexpected token %qs in use tree with valid path",
+ t->get_token_description ()));
+ return nullptr;
+ }
+
+ skip_token ();
+ t = lexer.peek_token ();
+
+ switch (t->get_id ())
+ {
+ case ASTERISK:
+ // glob UseTree type
+ lexer.skip_token ();
+
+ return std::unique_ptr<AST::UseTreeGlob> (
+ new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED,
+ std::move (path), locus));
+ case LEFT_CURLY:
+ {
+ // nested tree UseTree type
+ lexer.skip_token ();
+
+ std::vector<std::unique_ptr<AST::UseTree>> use_trees;
+
+ // TODO: think of better control structure
+ const_TokenPtr t = lexer.peek_token ();
+ while (t->get_id () != RIGHT_CURLY)
+ {
+ std::unique_ptr<AST::UseTree> use_tree = parse_use_tree ();
+ if (use_tree == nullptr)
+ {
+ break;
+ }
+
+ use_trees.push_back (std::move (use_tree));
+
+ if (lexer.peek_token ()->get_id () != COMMA)
+ break;
+
+ lexer.skip_token ();
+ t = lexer.peek_token ();
+ }
+
+ // skip end curly delimiter
+ if (!skip_token (RIGHT_CURLY))
+ {
+ // skip after somewhere?
+ return nullptr;
+ }
+
+ return std::unique_ptr<AST::UseTreeList> (
+ new AST::UseTreeList (AST::UseTreeList::PATH_PREFIXED,
+ std::move (path), std::move (use_trees),
+ locus));
+ }
default:
add_error (Error (t->get_locus (),
"unexpected token %qs in use tree with valid path",
@@ -3100,7 +3125,8 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
switch (token->get_id ())
{
- case LIFETIME: {
+ case LIFETIME:
+ {
auto lifetime = parse_lifetime (false);
if (!lifetime)
{
@@ -3126,7 +3152,8 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
std::move (outer_attrs), token->get_locus ()));
break;
}
- case IDENTIFIER: {
+ case IDENTIFIER:
+ {
auto type_ident = token->get_str ();
lexer.skip_token ();
@@ -3161,7 +3188,8 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
std::move (outer_attrs)));
break;
}
- case CONST: {
+ case CONST:
+ {
lexer.skip_token ();
auto name_token = expect_token (IDENTIFIER);
@@ -3345,7 +3373,8 @@ Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token)
/* Parses lifetime generic parameters (objects). Will also consume any
* trailing comma. No extra checks for end token.
- * TODO: is this best solution? implements most of the same algorithm. */
+ * TODO: is this best solution? implements most of the same algorithm.
+ * TODO: seems to be unused, remove? */
template <typename ManagedTokenSource>
std::vector<AST::LifetimeParam>
Parser<ManagedTokenSource>::parse_lifetime_params_objs ()
@@ -3363,7 +3392,7 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs ()
break;
}
- lifetime_params.push_back (std::move (lifetime_param));
+ lifetime_params.push_back (std::move (lifetime_param.value ()));
if (lexer.peek_token ()->get_id () != COMMA)
break;
@@ -4356,7 +4385,8 @@ Parser<ManagedTokenSource>::parse_struct (AST::Visibility vis,
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// struct with body
// skip curly bracket
@@ -4759,7 +4789,8 @@ Parser<ManagedTokenSource>::parse_enum_item ()
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// tuple enum item
lexer.skip_token ();
@@ -4780,7 +4811,8 @@ Parser<ManagedTokenSource>::parse_enum_item ()
std::move (item_name), std::move (vis), std::move (tuple_fields),
std::move (outer_attrs), item_name_tok->get_locus ()));
}
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// struct enum item
lexer.skip_token ();
@@ -4797,7 +4829,8 @@ Parser<ManagedTokenSource>::parse_enum_item ()
std::move (item_name), std::move (vis), std::move (struct_fields),
std::move (outer_attrs), item_name_tok->get_locus ()));
}
- case EQUAL: {
+ case EQUAL:
+ {
// discriminant enum item
lexer.skip_token ();
@@ -5450,7 +5483,8 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item ()
case SUPER:
case SELF:
case CRATE:
- case PUB: {
+ case PUB:
+ {
// visibility, so not a macro invocation semi - must be constant,
// function, or method
AST::Visibility vis = parse_visibility ();
@@ -5581,7 +5615,8 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
// param
auto initial_param = parse_self_param ();
- if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+ if (!initial_param.has_value ()
+ && initial_param.error () != ParseSelfError::NOT_SELF)
return nullptr;
/* FIXME: ensure that self param doesn't accidently consume tokens for a
@@ -5780,7 +5815,8 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
// param
auto initial_param = parse_self_param ();
- if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+ if (!initial_param.has_value ()
+ && initial_param.error () != ParseSelfError::NOT_SELF)
return nullptr;
// FIXME: ensure that self param doesn't accidently consume tokens for a
@@ -5964,7 +6000,8 @@ Parser<ManagedTokenSource>::parse_external_item ()
{
case IDENTIFIER:
return parse_macro_invocation_semi (outer_attrs);
- case STATIC_KW: {
+ case STATIC_KW:
+ {
// parse extern static item
lexer.skip_token ();
@@ -6261,7 +6298,8 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
switch (tok->get_id ())
{
- case IDENTIFIER: {
+ case IDENTIFIER:
+ {
// This is a bit of a weird situation: With an identifier token, we
// could either have a valid type or a macro (FIXME: anything else?). So
// we need one bit of lookahead to differentiate if this is really
@@ -6309,9 +6347,10 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
case FALSE_LITERAL:
expr = parse_literal_expr ();
break;
- // FIXME: Because of this, error reporting is garbage for const generic
- // parameter's default values
- default: {
+ // FIXME: Because of this, error reporting is garbage for const generic
+ // parameter's default values
+ default:
+ {
auto type = parse_type ();
// FIXME: Find a better way to do this?
if (type)
@@ -6510,7 +6549,8 @@ Parser<ManagedTokenSource>::parse_type_path_segment ()
switch (t->get_id ())
{
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// parse generic args
AST::GenericArgs generic_args = parse_path_generic_args ();
@@ -6519,7 +6559,8 @@ Parser<ManagedTokenSource>::parse_type_path_segment ()
has_separating_scope_resolution,
std::move (generic_args), locus));
}
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// parse type path function
AST::TypePathFunction type_path_function
= parse_type_path_function (locus);
@@ -7068,16 +7109,14 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs,
case SELF:
case SELF_ALIAS:
case DOLLAR_SIGN:
- case SCOPE_RESOLUTION: {
+ case SCOPE_RESOLUTION:
+ {
AST::PathInExpression path = parse_path_in_expression ();
std::unique_ptr<AST::Expr> null_denotation;
if (lexer.peek_token ()->get_id () == EXCLAM)
{
- // Bind a reference to avoid -Wredundant-move on post-P1825R0
- // compilers. Change to non-reference type and remove the moves
- // below once C++20 is required to build gcc.
- std::unique_ptr<AST::MacroInvocation> &&invoc
+ std::unique_ptr<AST::MacroInvocation> invoc
= parse_macro_invocation_partial (std::move (path),
std::move (outer_attrs));
@@ -7085,7 +7124,7 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs,
{
invoc->add_semicolon ();
// Macro invocation with semicolon.
- return std::move (invoc);
+ return invoc;
}
TokenId after_macro = lexer.peek_token ()->get_id ();
@@ -7093,14 +7132,14 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs,
if (restrictions.allow_close_after_expr_stmt
&& (after_macro == RIGHT_PAREN || after_macro == RIGHT_CURLY
|| after_macro == RIGHT_SQUARE))
- return std::move (invoc);
+ return invoc;
if (invoc->get_invoc_data ().get_delim_tok_tree ().get_delim_type ()
== AST::CURLY
&& after_macro != DOT && after_macro != QUESTION_MARK)
{
rust_debug ("braced macro statement");
- return std::move (invoc);
+ return invoc;
}
null_denotation = std::move (invoc);
@@ -7238,6 +7277,51 @@ Parser<ManagedTokenSource>::parse_block_expr (
std::move (label), locus, end_locus));
}
+/* Parse an anonymous const expression. This can be a regular const expression
+ * or an underscore for deferred const inference */
+template <typename ManagedTokenSource>
+tl::expected<AST::AnonConst, AnonConstError>
+Parser<ManagedTokenSource>::parse_anon_const ()
+{
+ auto current = lexer.peek_token ();
+ auto locus = current->get_locus ();
+
+ // Special case deferred inference constants
+ if (maybe_skip_token (UNDERSCORE))
+ return AST::AnonConst (locus);
+
+ auto expr = parse_expr ();
+
+ if (!expr)
+ return tl::make_unexpected (AnonConstError::InvalidSizeExpr);
+
+ return AST::AnonConst (std::move (expr), locus);
+}
+
+/* Parse a "const block", a block preceded by the `const` keyword whose
+ * statements can be const evaluated and used in constant contexts */
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::ConstBlock>
+Parser<ManagedTokenSource>::parse_const_block_expr (AST::AttrVec outer_attrs,
+ location_t locus)
+{
+ auto block = parse_block_expr ();
+
+ if (!block)
+ {
+ add_error (Error (locus, "failed to parse inner block in const block"));
+ skip_after_end_block ();
+
+ return nullptr;
+ }
+
+ auto block_locus = block->get_locus ();
+
+ return std::make_unique<AST::ConstBlock> (AST::AnonConst (std::move (block),
+ block_locus),
+ locus, std::move (outer_attrs));
+}
+
/* Parses a "grouped" expression (expression in parentheses), used to control
* precedence. */
template <typename ManagedTokenSource>
@@ -7518,6 +7602,34 @@ Parser<ManagedTokenSource>::parse_return_expr (AST::AttrVec outer_attrs,
locus));
}
+// Parses a try expression.
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::TryExpr>
+Parser<ManagedTokenSource>::parse_try_expr (AST::AttrVec outer_attrs,
+ location_t pratt_parsed_loc)
+{
+ location_t locus = pratt_parsed_loc;
+ if (locus == UNKNOWN_LOCATION)
+ {
+ locus = lexer.peek_token ()->get_locus ();
+ skip_token (TRY);
+ }
+
+ std::unique_ptr<AST::BlockExpr> block_expr = parse_block_expr ();
+
+ if (!block_expr)
+ {
+ Error error (lexer.peek_token ()->get_locus (),
+ "failed to parse try block expression");
+ add_error (std::move (error));
+
+ return nullptr;
+ }
+
+ return std::unique_ptr<AST::TryExpr> (
+ new AST::TryExpr (std::move (block_expr), std::move (outer_attrs), locus));
+}
+
/* Parses a break expression (including any label to break to AND any return
* expression). */
template <typename ManagedTokenSource>
@@ -7675,7 +7787,8 @@ Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs,
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// double selection - else
// parse else block expr (required)
std::unique_ptr<AST::BlockExpr> else_body = parse_block_expr ();
@@ -7696,7 +7809,8 @@ Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs,
std::move (else_body),
std::move (outer_attrs), locus));
}
- case IF: {
+ case IF:
+ {
// multiple selection - else if or else if let
// branch on whether next token is 'let' or not
if (lexer.peek_token (1)->get_id () == LET)
@@ -7857,7 +7971,8 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs,
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// double selection - else
// parse else block expr (required)
std::unique_ptr<AST::BlockExpr> else_body = parse_block_expr ();
@@ -7879,7 +7994,8 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs,
std::move (else_body),
std::move (outer_attrs), locus));
}
- case IF: {
+ case IF:
+ {
// multiple selection - else if or else if let
// branch on whether next token is 'let' or not
if (lexer.peek_token (1)->get_id () == LET)
@@ -8931,7 +9047,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
// slice type or array type - requires further disambiguation
return parse_slice_or_array_type ();
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path in type
AST::QualifiedPathInType path = parse_qualified_path_in_type ();
if (path.is_error ())
@@ -8960,7 +9077,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
case LOGICAL_AND:
// reference type
return parse_reference_type ();
- case LIFETIME: {
+ case LIFETIME:
+ {
/* probably a lifetime bound, so probably type param bounds in
* TraitObjectType */
std::vector<std::unique_ptr<AST::TypeParamBound>> bounds
@@ -8976,7 +9094,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
case SELF_ALIAS:
case CRATE:
case DOLLAR_SIGN:
- case SCOPE_RESOLUTION: {
+ case SCOPE_RESOLUTION:
+ {
// macro invocation or type path - requires further disambiguation.
/* for parsing path component of each rule, perhaps parse it as a
* typepath and attempt conversion to simplepath if a trailing '!' is
@@ -9006,7 +9125,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
t = lexer.peek_token ();
switch (t->get_id ())
{
- case EXCLAM: {
+ case EXCLAM:
+ {
// macro invocation
// convert to simple path
AST::SimplePath macro_path = path.as_simple_path ();
@@ -9032,7 +9152,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
std::move (tok_tree)),
{}, locus);
}
- case PLUS: {
+ case PLUS:
+ {
// type param bounds
std::vector<std::unique_ptr<AST::TypeParamBound>> bounds;
@@ -9117,14 +9238,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
t = lexer.peek_token ();
if (t->get_id () != PLUS)
{
- // convert trait bound to value object
- AST::TraitBound value_bound (*initial_bound);
-
- // DEBUG: removed as unique ptr, so should auto-delete
- // delete initial_bound;
-
return std::unique_ptr<AST::ImplTraitTypeOneBound> (
- new AST::ImplTraitTypeOneBound (std::move (value_bound),
+ new AST::ImplTraitTypeOneBound (std::move (initial_bound),
locus));
}
@@ -9152,7 +9267,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
new AST::ImplTraitType (std::move (bounds), locus));
}
case DYN:
- case QUESTION_MARK: {
+ case QUESTION_MARK:
+ {
// either TraitObjectType or TraitObjectTypeOneBound
bool has_dyn = false;
if (t->get_id () == DYN)
@@ -9405,7 +9521,8 @@ Parser<ManagedTokenSource>::parse_for_prefixed_type ()
case SELF:
case SELF_ALIAS:
case CRATE:
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
// path, so trait type
// parse type path to finish parsing trait bound
@@ -9751,13 +9868,15 @@ Parser<ManagedTokenSource>::parse_slice_or_array_type ()
return std::unique_ptr<AST::SliceType> (
new AST::SliceType (std::move (inner_type), locus));
- case SEMICOLON: {
+ case SEMICOLON:
+ {
// array type
lexer.skip_token ();
// parse required array size expression
- std::unique_ptr<AST::Expr> size = parse_expr ();
- if (size == nullptr)
+ auto size = parse_anon_const ();
+
+ if (!size)
{
Error error (lexer.peek_token ()->get_locus (),
"failed to parse size expression in array type");
@@ -9772,7 +9891,8 @@ Parser<ManagedTokenSource>::parse_slice_or_array_type ()
}
return std::unique_ptr<AST::ArrayType> (
- new AST::ArrayType (std::move (inner_type), std::move (size), locus));
+ new AST::ArrayType (std::move (inner_type), std::move (*size),
+ locus));
}
default:
// error
@@ -9802,7 +9922,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
// slice type or array type - requires further disambiguation
return parse_slice_or_array_type ();
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path in type
AST::QualifiedPathInType path = parse_qualified_path_in_type ();
if (path.is_error ())
@@ -9843,7 +9964,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
case SELF_ALIAS:
case CRATE:
case DOLLAR_SIGN:
- case SCOPE_RESOLUTION: {
+ case SCOPE_RESOLUTION:
+ {
// macro invocation or type path - requires further disambiguation.
/* for parsing path component of each rule, perhaps parse it as a
* typepath and attempt conversion to simplepath if a trailing '!' is
@@ -9871,7 +9993,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
t = lexer.peek_token ();
switch (t->get_id ())
{
- case EXCLAM: {
+ case EXCLAM:
+ {
// macro invocation
// convert to simple path
AST::SimplePath macro_path = path.as_simple_path ();
@@ -9955,14 +10078,12 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
return nullptr;
}
- // convert trait bound to value object
- AST::TraitBound value_bound (*initial_bound);
-
return std::unique_ptr<AST::ImplTraitTypeOneBound> (
- new AST::ImplTraitTypeOneBound (std::move (value_bound), locus));
+ new AST::ImplTraitTypeOneBound (std::move (initial_bound), locus));
}
case DYN:
- case QUESTION_MARK: {
+ case QUESTION_MARK:
+ {
// either TraitObjectTypeOneBound
bool has_dyn = false;
if (t->get_id () == DYN)
@@ -10303,7 +10424,8 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound ()
case SELF_ALIAS:
case CRATE:
case SCOPE_RESOLUTION:
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
// path in expression
AST::PathInExpression path = parse_path_in_expression ();
if (path.is_error ())
@@ -10319,7 +10441,8 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound ()
new AST::RangePatternBoundPath (std::move (path)));
}
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path in expression
AST::QualifiedPathInExpression path
= parse_qualified_path_in_expression ();
@@ -10464,7 +10587,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
// slice pattern
return parse_slice_pattern ();
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path in expression or qualified range pattern bound
AST::QualifiedPathInExpression path
= parse_qualified_path_in_expression ();
@@ -10500,7 +10624,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
case SELF_ALIAS:
case CRATE:
case SCOPE_RESOLUTION:
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
// path in expression or range pattern bound
AST::PathInExpression path = parse_path_in_expression ();
@@ -10509,7 +10634,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
{
case DOT_DOT_EQ:
case DOT_DOT:
- case ELLIPSIS: {
+ case ELLIPSIS:
+ {
// qualified range pattern bound, so parse rest of range pattern
AST::RangeKind kind = AST::tokenid_to_rangekind (next->get_id ());
lexer.skip_token ();
@@ -10527,7 +10653,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
case EXCLAM:
return parse_macro_invocation_partial (std::move (path),
AST::AttrVec ());
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// tuple struct
lexer.skip_token ();
@@ -10552,7 +10679,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
new AST::TupleStructPattern (std::move (path),
std::move (items)));
}
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// struct
lexer.skip_token ();
@@ -10722,7 +10850,8 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern ()
return std::unique_ptr<AST::GroupedPattern> (
new AST::GroupedPattern (std::move (initial_pattern), paren_locus));
- case COMMA: {
+ case COMMA:
+ {
// tuple pattern
lexer.skip_token ();
@@ -10835,27 +10964,47 @@ Parser<ManagedTokenSource>::parse_slice_pattern ()
{
location_t square_locus = lexer.peek_token ()->get_locus ();
std::vector<std::unique_ptr<AST::Pattern>> patterns;
+ tl::optional<std::vector<std::unique_ptr<AST::Pattern>>> upper_patterns
+ = tl::nullopt;
+
+ // lambda function to determine which vector to push new patterns into
+ auto get_pattern_ref
+ = [&] () -> std::vector<std::unique_ptr<AST::Pattern>> & {
+ return upper_patterns.has_value () ? upper_patterns.value () : patterns;
+ };
+
skip_token (LEFT_SQUARE);
if (lexer.peek_token ()->get_id () == RIGHT_SQUARE)
{
skip_token (RIGHT_SQUARE);
+ std::unique_ptr<AST::SlicePatternItemsNoRest> items (
+ new AST::SlicePatternItemsNoRest (std::move (patterns)));
return std::unique_ptr<AST::SlicePattern> (
- new AST::SlicePattern (std::move (patterns), square_locus));
+ new AST::SlicePattern (std::move (items), square_locus));
}
// parse initial pattern (required)
- std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern ();
- if (initial_pattern == nullptr)
+ if (lexer.peek_token ()->get_id () == DOT_DOT)
{
- Error error (lexer.peek_token ()->get_locus (),
- "failed to parse initial pattern in slice pattern");
- add_error (std::move (error));
-
- return nullptr;
+ lexer.skip_token ();
+ upper_patterns = std::vector<std::unique_ptr<AST::Pattern>> ();
}
+ else
+ {
+ // Not a rest pattern `..`, parse normally
+ std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern ();
+ if (initial_pattern == nullptr)
+ {
+ Error error (lexer.peek_token ()->get_locus (),
+ "failed to parse initial pattern in slice pattern");
+ add_error (std::move (error));
- patterns.push_back (std::move (initial_pattern));
+ return nullptr;
+ }
+
+ patterns.push_back (std::move (initial_pattern));
+ }
const_TokenPtr t = lexer.peek_token ();
while (t->get_id () == COMMA)
@@ -10866,6 +11015,23 @@ Parser<ManagedTokenSource>::parse_slice_pattern ()
if (lexer.peek_token ()->get_id () == RIGHT_SQUARE)
break;
+ if (lexer.peek_token ()->get_id () == DOT_DOT)
+ {
+ if (upper_patterns.has_value ())
+ {
+ // DOT_DOT has been parsed before
+ Error error (lexer.peek_token ()->get_locus (), "%s",
+ "`..` can only be used once per slice pattern");
+ add_error (std::move (error));
+
+ return nullptr;
+ }
+ upper_patterns = std::vector<std::unique_ptr<AST::Pattern>> ();
+ lexer.skip_token ();
+ t = lexer.peek_token ();
+ continue;
+ }
+
// parse pattern (required)
std::unique_ptr<AST::Pattern> pattern = parse_pattern ();
if (pattern == nullptr)
@@ -10876,7 +11042,7 @@ Parser<ManagedTokenSource>::parse_slice_pattern ()
return nullptr;
}
- patterns.push_back (std::move (pattern));
+ get_pattern_ref ().push_back (std::move (pattern));
t = lexer.peek_token ();
}
@@ -10886,8 +11052,21 @@ Parser<ManagedTokenSource>::parse_slice_pattern ()
return nullptr;
}
+ if (upper_patterns.has_value ())
+ {
+ // Slice pattern with rest
+ std::unique_ptr<AST::SlicePatternItemsHasRest> items (
+ new AST::SlicePatternItemsHasRest (
+ std::move (patterns), std::move (upper_patterns.value ())));
+ return std::unique_ptr<AST::SlicePattern> (
+ new AST::SlicePattern (std::move (items), square_locus));
+ }
+
+ // Rest-less slice pattern
+ std::unique_ptr<AST::SlicePatternItemsNoRest> items (
+ new AST::SlicePatternItemsNoRest (std::move (patterns)));
return std::unique_ptr<AST::SlicePattern> (
- new AST::SlicePattern (std::move (patterns), square_locus));
+ new AST::SlicePattern (std::move (items), square_locus));
}
/* Parses an identifier pattern (pattern that binds a value matched to a
@@ -10979,7 +11158,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
{
case EXCLAM:
return parse_macro_invocation_partial (std::move (path), AST::AttrVec ());
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// tuple struct
lexer.skip_token ();
@@ -11012,7 +11192,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
return std::unique_ptr<AST::TupleStructPattern> (
new AST::TupleStructPattern (std::move (path), std::move (items)));
}
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// struct
lexer.skip_token ();
@@ -11033,7 +11214,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
}
case DOT_DOT_EQ:
case DOT_DOT:
- case ELLIPSIS: {
+ case ELLIPSIS:
+ {
// range
AST::RangeKind kind
= AST::tokenid_to_rangekind (lexer.peek_token ()->get_id ());
@@ -11050,7 +11232,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
std::move (upper_bound), kind,
t->get_locus ()));
}
- case PATTERN_BIND: {
+ case PATTERN_BIND:
+ {
// only allow on single-segment paths
if (path.is_single_segment ())
{
@@ -11188,7 +11371,8 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items ()
case RIGHT_PAREN:
return std::unique_ptr<AST::TupleStructItemsNoRange> (
new AST::TupleStructItemsNoRange (std::move (lower_patterns)));
- case DOT_DOT: {
+ case DOT_DOT:
+ {
// has an upper range that must be parsed separately
lexer.skip_token ();
@@ -11308,7 +11492,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case INT_LITERAL: {
+ case INT_LITERAL:
+ {
// tuple index
std::string index_str = t->get_str ();
int index = atoi (index_str.c_str ());
@@ -11342,7 +11527,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
// branch on next token
switch (lexer.peek_token (1)->get_id ())
{
- case COLON: {
+ case COLON:
+ {
// identifier-pattern
Identifier ident{t};
lexer.skip_token ();
@@ -11367,7 +11553,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
t->get_locus ()));
}
case COMMA:
- case RIGHT_CURLY: {
+ case RIGHT_CURLY:
+ {
// identifier only
Identifier ident = {t};
lexer.skip_token ();
@@ -11386,7 +11573,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
return nullptr;
}
case REF:
- case MUT: {
+ case MUT:
+ {
// only identifier
bool has_ref = false;
if (t->get_id () == REF)
@@ -11458,7 +11646,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
t = lexer.peek_token ();
switch (t->get_id ())
{
- case LET: {
+ case LET:
+ {
// let statement
std::unique_ptr<AST::LetStmt> stmt (
parse_let_stmt (std::move (outer_attrs)));
@@ -11476,42 +11665,48 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
case STATIC_KW:
case AUTO:
case TRAIT:
- case IMPL: {
+ case IMPL:
+ {
std::unique_ptr<AST::VisItem> item (
parse_vis_item (std::move (outer_attrs)));
return ExprOrStmt (std::move (item));
}
- /* TODO: implement union keyword but not really because of
- * context-dependence crappy hack way to parse a union written below to
- * separate it from the good code. */
- // case UNION:
- case UNSAFE: { // maybe - unsafe traits are a thing
+ /* TODO: implement union keyword but not really because of
+ * context-dependence crappy hack way to parse a union written below to
+ * separate it from the good code. */
+ // case UNION:
+ case UNSAFE:
+ { // maybe - unsafe traits are a thing
/* if any of these (should be all possible VisItem prefixes), parse a
* VisItem - can't parse item because would require reparsing outer
* attributes */
const_TokenPtr t2 = lexer.peek_token (1);
switch (t2->get_id ())
{
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// unsafe block: parse as expression
expr = parse_expr (std::move (outer_attrs), restrictions);
break;
}
case AUTO:
- case TRAIT: {
+ case TRAIT:
+ {
// unsafe trait
std::unique_ptr<AST::VisItem> item (
parse_vis_item (std::move (outer_attrs)));
return ExprOrStmt (std::move (item));
}
case EXTERN_KW:
- case FN_KW: {
+ case FN_KW:
+ {
// unsafe function
std::unique_ptr<AST::VisItem> item (
parse_vis_item (std::move (outer_attrs)));
return ExprOrStmt (std::move (item));
}
- case IMPL: {
+ case IMPL:
+ {
// unsafe trait impl
std::unique_ptr<AST::VisItem> item (
parse_vis_item (std::move (outer_attrs)));
@@ -11556,7 +11751,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
case SELF_ALIAS:
case CRATE:
case SCOPE_RESOLUTION:
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
AST::PathInExpression path = parse_path_in_expression ();
std::unique_ptr<AST::Expr> null_denotation;
@@ -11680,7 +11876,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_field ()
std::move (outer_attrs),
t->get_locus ()));
}
- case INT_LITERAL: {
+ case INT_LITERAL:
+ {
// parse tuple index field
int index = atoi (t->get_str ().c_str ());
lexer.skip_token ();
@@ -11725,11 +11922,12 @@ Parser<ManagedTokenSource>::parse_struct_expr_field ()
}
// "Unexpected token" panic mode - flags gcc error at unexpected token
+// TODO: seems to be unused, remove?
template <typename ManagedTokenSource>
void
Parser<ManagedTokenSource>::unexpected_token (const_TokenPtr t)
{
- Error error (t->get_locus (), "unexpected token %qs\n",
+ Error error (t->get_locus (), "unexpected token %qs",
t->get_token_description ());
add_error (std::move (error));
}
@@ -11920,7 +12118,7 @@ Parser<ManagedTokenSource>::skip_after_end_attribute ()
{
const_TokenPtr t = lexer.peek_token ();
- while (t->get_id () != RIGHT_SQUARE)
+ while (t->get_id () != RIGHT_SQUARE && t->get_id () != END_OF_FILE)
{
lexer.skip_token ();
t = lexer.peek_token ();
@@ -12050,7 +12248,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
case SELF_ALIAS:
case DOLLAR_SIGN:
case CRATE:
- case SUPER: {
+ case SUPER:
+ {
// DEBUG
rust_debug ("beginning null denotation identifier handling");
@@ -12061,7 +12260,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
return null_denotation_path (std::move (path), std::move (outer_attrs),
restrictions);
}
- case SCOPE_RESOLUTION: {
+ case SCOPE_RESOLUTION:
+ {
// TODO: fix: this is for global paths, i.e. std::string::whatever
Error error (tok->get_locus (),
"found null denotation scope resolution operator, and "
@@ -12103,7 +12303,8 @@ Parser<ManagedTokenSource>::null_denotation_path (
// macro
return parse_macro_invocation_partial (std::move (path),
std::move (outer_attrs));
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
bool not_a_block = lexer.peek_token (1)->get_id () == IDENTIFIER
&& (lexer.peek_token (2)->get_id () == COMMA
|| (lexer.peek_token (2)->get_id () == COLON
@@ -12179,7 +12380,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
{
// FIXME: Handle in null_denotation_path?
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path
// HACK: add outer attrs to path
AST::QualifiedPathInExpression path
@@ -12237,23 +12439,24 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
return parse_grouped_or_tuple_expr (std::move (outer_attrs),
tok->get_locus ());
- /*case PLUS: { // unary plus operator
- // invoke parse_expr recursively with appropriate priority, etc. for
- below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS);
+ /*case PLUS: { // unary plus operator
+ // invoke parse_expr recursively with appropriate priority, etc. for
+ below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS);
- if (expr == nullptr)
- return nullptr;
- // can only apply to integer and float expressions
- if (expr->get_type() != integer_type_node || expr->get_type() !=
- float_type_node) { rust_error_at(tok->get_locus(), "operand of unary
- plus must be int or float but it is %s", print_type(expr->get_type()));
- return nullptr;
- }
+ if (expr == nullptr)
+ return nullptr;
+ // can only apply to integer and float expressions
+ if (expr->get_type() != integer_type_node || expr->get_type() !=
+ float_type_node) { rust_error_at(tok->get_locus(), "operand of unary
+ plus must be int or float but it is %s", print_type(expr->get_type()));
+ return nullptr;
+ }
- return Tree(expr, tok->get_locus());
- }*/
- // Rust has no unary plus operator
- case MINUS: { // unary minus
+ return Tree(expr, tok->get_locus());
+ }*/
+ // Rust has no unary plus operator
+ case MINUS:
+ { // unary minus
ParseRestrictions entered_from_unary;
entered_from_unary.entered_from_unary = true;
if (!restrictions.can_be_struct_expr)
@@ -12280,7 +12483,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
new AST::NegationExpr (std::move (expr), NegationOperator::NEGATE,
std::move (outer_attrs), tok->get_locus ()));
}
- case EXCLAM: { // logical or bitwise not
+ case EXCLAM:
+ { // logical or bitwise not
ParseRestrictions entered_from_unary;
entered_from_unary.entered_from_unary = true;
if (!restrictions.can_be_struct_expr)
@@ -12305,7 +12509,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
new AST::NegationExpr (std::move (expr), NegationOperator::NOT,
std::move (outer_attrs), tok->get_locus ()));
}
- case ASTERISK: {
+ case ASTERISK:
+ {
/* pointer dereference only - HACK: as struct expressions should
* always be value expressions, cannot be dereferenced */
ParseRestrictions entered_from_unary;
@@ -12318,7 +12523,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
new AST::DereferenceExpr (std::move (expr), std::move (outer_attrs),
tok->get_locus ()));
}
- case AMP: {
+ case AMP:
+ {
// (single) "borrow" expression - shared (mutable) or immutable
std::unique_ptr<AST::Expr> expr = nullptr;
Mutability mutability = Mutability::Imm;
@@ -12375,7 +12581,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
new AST::BorrowExpr (std::move (expr), mutability, raw_borrow, false,
std::move (outer_attrs), tok->get_locus ()));
}
- case LOGICAL_AND: {
+ case LOGICAL_AND:
+ {
// (double) "borrow" expression - shared (mutable) or immutable
std::unique_ptr<AST::Expr> expr = nullptr;
Mutability mutability = Mutability::Imm;
@@ -12414,6 +12621,9 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
case RETURN_KW:
// FIXME: is this really a null denotation expression?
return parse_return_expr (std::move (outer_attrs), tok->get_locus ());
+ case TRY:
+ // FIXME: is this really a null denotation expression?
+ return parse_try_expr (std::move (outer_attrs), tok->get_locus ());
case BREAK:
// FIXME: is this really a null denotation expression?
return parse_break_expr (std::move (outer_attrs), tok->get_locus ());
@@ -12469,6 +12679,9 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
"use of %qs is not allowed on the right-side of an assignment",
tok->get_token_description ()));
return nullptr;
+ case CONST:
+ return parse_const_block_expr (std::move (outer_attrs),
+ tok->get_locus ());
default:
if (!restrictions.expr_can_be_null)
add_error (Error (tok->get_locus (),
@@ -12491,8 +12704,9 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok,
// Token passed in has already been skipped, so peek gives "next" token
switch (tok->get_id ())
{
- // FIXME: allow for outer attributes to be applied
- case QUESTION_MARK: {
+ // FIXME: allow for outer attributes to be applied
+ case QUESTION_MARK:
+ {
location_t left_locus = left->get_locus ();
// error propagation expression - unary postfix
return std::unique_ptr<AST::ErrorPropagationExpr> (
@@ -12746,7 +12960,8 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok,
"function - this should probably be handled elsewhere"));
return nullptr;
- case DOT: {
+ case DOT:
+ {
/* field expression or method call - relies on parentheses after next
* identifier or await if token after is "await" (unary postfix) or
* tuple index if token after is a decimal int literal */
@@ -14062,7 +14277,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_struct_partial (
* algorithm should work too. As such, AST type not happening. */
case IDENTIFIER:
case HASH:
- case INT_LITERAL: {
+ case INT_LITERAL:
+ {
// struct with struct expr fields
// parse struct expr fields
@@ -14359,7 +14575,8 @@ Parser<ManagedTokenSource>::parse_closure_expr_pratt (const_TokenPtr tok,
case OR:
// no parameters, don't skip token
break;
- case PIPE: {
+ case PIPE:
+ {
// actually may have parameters
// don't skip token
const_TokenPtr t = lexer.peek_token ();
diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc
index 43d15aa..860fd11 100644
--- a/gcc/rust/parse/rust-parse.cc
+++ b/gcc/rust/parse/rust-parse.cc
@@ -42,8 +42,7 @@ extract_module_path (const AST::AttrVec &inner_attrs,
{
rust_error_at (
path_attr.get_locus (),
- // Split the format string so that -Wformat-diag does not complain...
- "path attributes must contain a filename: '%s'", "#![path = \"file\"]");
+ "path attributes must contain a filename: %<#[path = \"file\"]%>");
return name;
}
@@ -67,8 +66,7 @@ extract_module_path (const AST::AttrVec &inner_attrs,
{
rust_error_at (
path_attr.get_locus (),
- // Split the format string so that -Wformat-diag does not complain...
- "path attributes must contain a filename: '%s'", "#[path = \"file\"]");
+ "path attributes must contain a filename: %<#[path = \"file\"]%>");
return name;
}
@@ -80,6 +78,15 @@ extract_module_path (const AST::AttrVec &inner_attrs,
// a character that is not an equal sign or whitespace
auto filename_begin = path_value.find_first_not_of ("=\t ");
+ // If the path consists of only whitespace, then we have an error
+ if (filename_begin == std::string::npos)
+ {
+ rust_error_at (
+ path_attr.get_locus (),
+ "path attributes must contain a filename: %<#[path = \"file\"]%>");
+ return name;
+ }
+
auto path = path_value.substr (filename_begin);
// On windows, the path might mix '/' and '\' separators. Replace the
@@ -144,10 +151,9 @@ peculiar_fragment_match_compatible_fragment (
= contains (fragment_follow_set[last_spec.get_kind ()], spec.get_kind ());
if (!is_valid)
- rust_error_at (
- match_locus,
- "fragment specifier %qs is not allowed after %qs fragments",
- spec.as_string ().c_str (), last_spec.as_string ().c_str ());
+ rust_error_at (match_locus,
+ "fragment specifier %qs is not allowed after %qs fragments",
+ spec.as_string ().c_str (), last_spec.as_string ().c_str ());
return is_valid;
}
@@ -244,7 +250,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match,
// the error.
switch (match.get_macro_match_type ())
{
- case AST::MacroMatch::Tok: {
+ case AST::MacroMatch::Tok:
+ {
auto tok = static_cast<const AST::Token *> (&match);
if (contains (allowed_toks, tok->get_id ()))
return true;
@@ -254,7 +261,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match,
break;
}
break;
- case AST::MacroMatch::Repetition: {
+ case AST::MacroMatch::Repetition:
+ {
auto repetition
= static_cast<const AST::MacroMatchRepetition *> (&match);
auto &matches = repetition->get_matches ();
@@ -263,7 +271,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match,
return peculiar_fragment_match_compatible (last_match, *first_frag);
break;
}
- case AST::MacroMatch::Matcher: {
+ case AST::MacroMatch::Matcher:
+ {
auto matcher = static_cast<const AST::MacroMatcher *> (&match);
auto first_token = matcher->get_delim_type ();
TokenId delim_id;
@@ -289,7 +298,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match,
error_locus = matcher->get_match_locus ();
break;
}
- case AST::MacroMatch::Fragment: {
+ case AST::MacroMatch::Fragment:
+ {
auto last_spec = last_match.get_frag_spec ();
auto fragment = static_cast<const AST::MacroMatchFragment *> (&match);
if (last_spec.has_follow_set_fragment_restrictions ())
@@ -328,10 +338,11 @@ is_match_compatible (const AST::MacroMatch &last_match,
switch (last_match.get_macro_match_type ())
{
- // This is our main stop condition: When we are finally looking at the
- // last match (or its actual last component), and it is a fragment, it
- // may contain some follow up restrictions.
- case AST::MacroMatch::Fragment: {
+ // This is our main stop condition: When we are finally looking at the
+ // last match (or its actual last component), and it is a fragment, it
+ // may contain some follow up restrictions.
+ case AST::MacroMatch::Fragment:
+ {
auto fragment
= static_cast<const AST::MacroMatchFragment *> (&last_match);
if (fragment->get_frag_spec ().has_follow_set_restrictions ())
@@ -339,7 +350,8 @@ is_match_compatible (const AST::MacroMatch &last_match,
else
return true;
}
- case AST::MacroMatch::Repetition: {
+ case AST::MacroMatch::Repetition:
+ {
// A repetition on the left hand side means we want to make sure the
// last match of the repetition is compatible with the new match
auto repetition
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 827d91d..8253885 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -17,6 +17,7 @@ along with GCC; see the file COPYING3. If not see
#ifndef RUST_PARSE_H
#define RUST_PARSE_H
+#include "rust-ast.h"
#include "rust-item.h"
#include "rust-lex.h"
#include "rust-ast-full.h"
@@ -33,12 +34,19 @@ class ParseLifetimeParamError
class ParseLifetimeError
{
};
+
+enum class AnonConstError
+{
+ InvalidSizeExpr,
+};
+
enum class ParseLoopLabelError
{
NOT_LOOP_LABEL,
MISSING_COLON,
};
-enum ParseSelfError
+
+enum class ParseSelfError
{
SELF_PTR,
PARSING,
@@ -165,6 +173,12 @@ public:
tl::optional<AST::LoopLabel> = tl::nullopt,
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
+ tl::expected<AST::AnonConst, AnonConstError> parse_anon_const ();
+
+ std::unique_ptr<AST::ConstBlock>
+ parse_const_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
+ location_t loc = UNKNOWN_LOCATION);
+
bool is_macro_rules_def (const_TokenPtr t);
std::unique_ptr<AST::Item> parse_item (bool called_from_statement);
std::unique_ptr<AST::Pattern> parse_pattern ();
@@ -222,7 +236,7 @@ private:
// Path-related
AST::SimplePath parse_simple_path ();
- AST::SimplePathSegment parse_simple_path_segment ();
+ AST::SimplePathSegment parse_simple_path_segment (int base_peek = 0);
AST::TypePath parse_type_path ();
std::unique_ptr<AST::TypePathSegment> parse_type_path_segment ();
AST::PathIdentSegment parse_path_ident_segment ();
@@ -644,6 +658,9 @@ private:
std::unique_ptr<AST::ReturnExpr>
parse_return_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
+ std::unique_ptr<AST::TryExpr>
+ parse_try_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
+ location_t pratt_parsed_loc = UNKNOWN_LOCATION);
std::unique_ptr<AST::BreakExpr>
parse_break_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
@@ -762,11 +779,15 @@ private:
}
~InlineModuleStackScope () { parser.inline_module_stack.pop_back (); }
};
+
+ // don't want to make things *only* AttributeParser uses public
+ // TODO: fold more of AttributeParser into Parser?
+ friend class ::Rust::AST::AttributeParser;
};
-std::string
-extract_module_path (const AST::AttrVec &inner_attrs,
- const AST::AttrVec &outer_attrs, const std::string &name);
+std::string extract_module_path (const AST::AttrVec &inner_attrs,
+ const AST::AttrVec &outer_attrs,
+ const std::string &name);
/**
* Check if a MacroMatch is allowed to follow the last parsed MacroMatch.
@@ -776,12 +797,8 @@ extract_module_path (const AST::AttrVec &inner_attrs,
*
* @return true if the follow-up is valid, false otherwise
*/
-bool
-is_match_compatible (const AST::MacroMatch &last_match,
- const AST::MacroMatch &current_match);
+bool is_match_compatible (const AST::MacroMatch &last_match,
+ const AST::MacroMatch &current_match);
} // namespace Rust
-// as now template, include implementations of all methods
-#include "rust-parse-impl.h"
-
#endif // RUST_PARSE_H
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc
index b781ce33..3c7b425 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-base.cc
@@ -116,7 +116,7 @@ ResolverBase::visit (AST::MetaItemLitExpr &)
{}
void
-ResolverBase::visit (AST::MetaItemPathLit &)
+ResolverBase::visit (AST::MetaItemPathExpr &)
{}
void
@@ -232,6 +232,14 @@ ResolverBase::visit (AST::BlockExpr &)
{}
void
+ResolverBase::visit (AST::AnonConst &)
+{}
+
+void
+ResolverBase::visit (AST::ConstBlock &)
+{}
+
+void
ResolverBase::visit (AST::ClosureExprInnerTyped &)
{}
@@ -276,6 +284,10 @@ ResolverBase::visit (AST::ReturnExpr &)
{}
void
+ResolverBase::visit (AST::TryExpr &)
+{}
+
+void
ResolverBase::visit (AST::UnsafeBlockExpr &)
{}
@@ -572,6 +584,14 @@ ResolverBase::visit (AST::GroupedPattern &)
{}
void
+ResolverBase::visit (AST::SlicePatternItemsNoRest &)
+{}
+
+void
+ResolverBase::visit (AST::SlicePatternItemsHasRest &)
+{}
+
+void
ResolverBase::visit (AST::SlicePattern &)
{}
@@ -663,5 +683,9 @@ void
ResolverBase::visit (AST::FormatArgs &fmt)
{}
+void
+ResolverBase::visit (AST::OffsetOf &offset_of)
+{}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h
index 5bb9e4f..89c5c35 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.h
+++ b/gcc/rust/resolve/rust-ast-resolve-base.h
@@ -21,6 +21,8 @@
#include "rust-ast-visitor.h"
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
+#include "rust-expr.h"
#include "rust-name-resolver.h"
#include "rust-diagnostics.h"
#include "rust-location.h"
@@ -56,7 +58,7 @@ public:
void visit (AST::AttrInputLiteral &);
void visit (AST::AttrInputMacro &);
void visit (AST::MetaItemLitExpr &);
- void visit (AST::MetaItemPathLit &);
+ void visit (AST::MetaItemPathExpr &);
void visit (AST::BorrowExpr &);
void visit (AST::DereferenceExpr &);
void visit (AST::ErrorPropagationExpr &);
@@ -85,6 +87,8 @@ public:
void visit (AST::FieldAccessExpr &);
void visit (AST::ClosureExprInner &);
void visit (AST::BlockExpr &);
+ void visit (AST::AnonConst &);
+ void visit (AST::ConstBlock &);
void visit (AST::ClosureExprInnerTyped &);
void visit (AST::ContinueExpr &);
void visit (AST::BreakExpr &);
@@ -96,6 +100,7 @@ public:
void visit (AST::RangeToInclExpr &);
void visit (AST::BoxExpr &);
void visit (AST::ReturnExpr &);
+ void visit (AST::TryExpr &);
void visit (AST::UnsafeBlockExpr &);
void visit (AST::LoopExpr &);
void visit (AST::WhileLoopExpr &);
@@ -181,6 +186,8 @@ public:
void visit (AST::TuplePatternItemsRanged &);
void visit (AST::TuplePattern &);
void visit (AST::GroupedPattern &);
+ void visit (AST::SlicePatternItemsNoRest &);
+ void visit (AST::SlicePatternItemsHasRest &);
void visit (AST::SlicePattern &);
void visit (AST::AltPattern &);
@@ -207,6 +214,7 @@ public:
void visit (AST::SelfParam &param);
void visit (AST::FormatArgs &fmt);
+ void visit (AST::OffsetOf &offset_of);
protected:
ResolverBase ()
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc
index 5524e18..a410193 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc
@@ -315,6 +315,18 @@ ResolveExpr::visit (AST::BlockExpr &expr)
}
void
+ResolveExpr::visit (AST::AnonConst &expr)
+{
+ ResolveExpr::go (expr.get_inner_expr (), prefix, canonical_prefix);
+}
+
+void
+ResolveExpr::visit (AST::ConstBlock &expr)
+{
+ ResolveExpr::go (expr.get_const_expr (), prefix, canonical_prefix);
+}
+
+void
translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
{
@@ -324,38 +336,46 @@ translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix,
{
switch (operand.get_register_type ())
{
- case RegisterType::In: {
+ case RegisterType::In:
+ {
auto in = operand.get_in ();
ResolveExpr::go (*in.expr, prefix, canonical_prefix);
break;
}
- case RegisterType::Out: {
+ case RegisterType::Out:
+ {
auto out = operand.get_out ();
ResolveExpr::go (*out.expr, prefix, canonical_prefix);
break;
}
- case RegisterType::InOut: {
+ case RegisterType::InOut:
+ {
auto in_out = operand.get_in_out ();
ResolveExpr::go (*in_out.expr, prefix, canonical_prefix);
break;
}
- case RegisterType::SplitInOut: {
+ case RegisterType::SplitInOut:
+ {
auto split_in_out = operand.get_split_in_out ();
ResolveExpr::go (*split_in_out.in_expr, prefix, canonical_prefix);
ResolveExpr::go (*split_in_out.out_expr, prefix, canonical_prefix);
break;
}
- case RegisterType::Const: {
+ case RegisterType::Const:
+ {
auto anon_const = operand.get_const ().anon_const;
- ResolveExpr::go (*anon_const.expr, prefix, canonical_prefix);
+ ResolveExpr::go (anon_const.get_inner_expr (), prefix,
+ canonical_prefix);
break;
}
- case RegisterType::Sym: {
+ case RegisterType::Sym:
+ {
auto sym = operand.get_sym ();
ResolveExpr::go (*sym.expr, prefix, canonical_prefix);
break;
}
- case RegisterType::Label: {
+ case RegisterType::Label:
+ {
auto label = operand.get_label ();
ResolveExpr::go (*label.expr, prefix, canonical_prefix);
break;
@@ -766,7 +786,7 @@ ResolveExpr::visit (AST::ClosureExprInnerTyped &expr)
resolver->push_closure_context (expr.get_node_id ());
- ResolveExpr::go (expr.get_definition_block (), prefix, canonical_prefix);
+ ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix);
resolver->pop_closure_context ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index b296d66..aad1605 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -56,6 +56,8 @@ public:
void visit (AST::IfLetExpr &expr) override;
void visit (AST::IfLetExprConseqElse &expr) override;
void visit (AST::BlockExpr &expr) override;
+ void visit (AST::AnonConst &expr) override;
+ void visit (AST::ConstBlock &expr) override;
void visit (AST::InlineAsm &expr) override;
void visit (AST::LlvmInlineAsm &expr) override;
void visit (AST::UnsafeBlockExpr &expr) override;
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc
index 30f6d43..1d5ebed 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -453,7 +453,8 @@ ResolveItem::visit (AST::ConstantItem &constant)
resolve_visibility (constant.get_visibility ());
ResolveType::go (constant.get_type ());
- ResolveExpr::go (constant.get_expr (), path, cpath);
+ if (constant.has_expr ())
+ ResolveExpr::go (constant.get_expr (), path, cpath);
}
void
@@ -608,10 +609,7 @@ ResolveItem::visit (AST::InherentImpl &impl_block)
}
else
{
- std::string seg_buf = "<impl " + self_cpath.get () + ">";
- CanonicalPath seg
- = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf);
- cpath = canonical_prefix.append (seg);
+ cpath = canonical_prefix.append (impl_type_seg);
}
// done setup paths
@@ -732,13 +730,7 @@ ResolveItem::visit (AST::TraitImpl &impl_block)
}
else
{
- std::string projection_str = canonical_projection.get ();
- std::string seg_buf
- = "<impl " + projection_str.substr (1, projection_str.size () - 2)
- + ">";
- CanonicalPath seg
- = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf);
- cpath = canonical_prefix.append (seg);
+ cpath = canonical_prefix.append (canonical_projection);
}
// DONE setup canonical-path
@@ -838,29 +830,32 @@ ResolveItem::resolve_extern_item (AST::ExternalItem &item)
ResolveExternItem::go (item, prefix, canonical_prefix);
}
-static void
-flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports);
-static void
-flatten_rebind (const AST::UseTreeRebind &glob, std::vector<Import> &imports);
-static void
-flatten_list (const AST::UseTreeList &glob, std::vector<Import> &imports);
+static void flatten_glob (const AST::UseTreeGlob &glob,
+ std::vector<Import> &imports);
+static void flatten_rebind (const AST::UseTreeRebind &glob,
+ std::vector<Import> &imports);
+static void flatten_list (const AST::UseTreeList &glob,
+ std::vector<Import> &imports);
static void
flatten (const AST::UseTree *tree, std::vector<Import> &imports)
{
switch (tree->get_kind ())
{
- case AST::UseTree::Glob: {
+ case AST::UseTree::Glob:
+ {
auto glob = static_cast<const AST::UseTreeGlob *> (tree);
flatten_glob (*glob, imports);
break;
}
- case AST::UseTree::Rebind: {
+ case AST::UseTree::Rebind:
+ {
auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
flatten_rebind (*rebind, imports);
break;
}
- case AST::UseTree::List: {
+ case AST::UseTree::List:
+ {
auto list = static_cast<const AST::UseTreeList *> (tree);
flatten_list (*list, imports);
break;
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
index 776dd53..d31f910 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -153,8 +153,7 @@ private:
#if CHECKING_P
namespace selftest {
-extern void
-rust_simple_path_resolve_test (void);
+extern void rust_simple_path_resolve_test (void);
} // namespace selftest
#endif // CHECKING_P
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
index ee84be8..3b80f9f 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
@@ -62,6 +62,11 @@ PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type,
void
PatternDeclaration::visit (AST::IdentifierPattern &pattern)
{
+ if (pattern.has_subpattern ())
+ {
+ pattern.get_subpattern ().accept_vis (*this);
+ }
+
Mutability mut = pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm;
add_new_binding (pattern.get_ident (), pattern.get_node_id (),
BindingTypeInfo (mut, pattern.get_is_ref (),
@@ -94,13 +99,15 @@ PatternDeclaration::visit (AST::TupleStructPattern &pattern)
AST::TupleStructItems &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case AST::TupleStructItems::RANGE: {
+ case AST::TupleStructItems::RANGE:
+ {
// TODO
rust_unreachable ();
}
break;
- case AST::TupleStructItems::NO_RANGE: {
+ case AST::TupleStructItems::NO_RANGE:
+ {
auto &items_no_range
= static_cast<AST::TupleStructItemsNoRange &> (items);
@@ -123,7 +130,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern)
{
switch (field->get_item_type ())
{
- case AST::StructPatternField::ItemType::TUPLE_PAT: {
+ case AST::StructPatternField::ItemType::TUPLE_PAT:
+ {
AST::StructPatternFieldTuplePat &tuple
= static_cast<AST::StructPatternFieldTuplePat &> (*field);
@@ -131,7 +139,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern)
}
break;
- case AST::StructPatternField::ItemType::IDENT_PAT: {
+ case AST::StructPatternField::ItemType::IDENT_PAT:
+ {
AST::StructPatternFieldIdentPat &ident
= static_cast<AST::StructPatternFieldIdentPat &> (*field);
@@ -139,7 +148,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern)
}
break;
- case AST::StructPatternField::ItemType::IDENT: {
+ case AST::StructPatternField::ItemType::IDENT:
+ {
auto &ident = static_cast<AST::StructPatternFieldIdent &> (*field);
Mutability mut
@@ -160,7 +170,8 @@ PatternDeclaration::visit (AST::TuplePattern &pattern)
auto &items = pattern.get_items ();
switch (items.get_pattern_type ())
{
- case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
+ case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE:
+ {
auto &ref = static_cast<AST::TuplePatternItemsMultiple &> (
pattern.get_items ());
@@ -169,7 +180,8 @@ PatternDeclaration::visit (AST::TuplePattern &pattern)
}
break;
- case AST::TuplePatternItems::TuplePatternItemType::RANGED: {
+ case AST::TuplePatternItems::TuplePatternItemType::RANGED:
+ {
auto &ref
= static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ());
@@ -348,14 +360,16 @@ resolve_range_pattern_bound (AST::RangePatternBound &bound)
// Nothing to resolve for a literal.
break;
- case AST::RangePatternBound::RangePatternBoundType::PATH: {
+ case AST::RangePatternBound::RangePatternBoundType::PATH:
+ {
auto &ref = static_cast<AST::RangePatternBoundPath &> (bound);
ResolvePath::go (ref.get_path ());
}
break;
- case AST::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ case AST::RangePatternBound::RangePatternBoundType::QUALPATH:
+ {
auto &ref = static_cast<AST::RangePatternBoundQualPath &> (bound);
ResolvePath::go (ref.get_qualified_path ());
@@ -374,9 +388,30 @@ PatternDeclaration::visit (AST::RangePattern &pattern)
void
PatternDeclaration::visit (AST::SlicePattern &pattern)
{
- for (auto &p : pattern.get_items ())
+ auto &items = pattern.get_items ();
+ switch (items.get_pattern_type ())
{
- p->accept_vis (*this);
+ case AST::SlicePatternItems::SlicePatternItemType::NO_REST:
+ {
+ auto &ref
+ = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ());
+
+ for (auto &p : ref.get_patterns ())
+ p->accept_vis (*this);
+ }
+ break;
+
+ case AST::SlicePatternItems::SlicePatternItemType::HAS_REST:
+ {
+ auto &ref
+ = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ());
+
+ for (auto &p : ref.get_lower_patterns ())
+ p->accept_vis (*this);
+ for (auto &p : ref.get_upper_patterns ())
+ p->accept_vis (*this);
+ }
+ break;
}
}
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index d413a7c..d714511 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -67,7 +67,8 @@ public:
});
ResolveType::go (constant.get_type ());
- ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix);
+ if (constant.has_expr ())
+ ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix);
}
void visit (AST::LetStmt &stmt) override
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
index 8fd69c3..a040228 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -140,7 +140,7 @@ ResolveType::visit (AST::ImplTraitType &type)
void
ResolveType::visit (AST::ImplTraitTypeOneBound &type)
{
- ResolveTypeBound::go (type.get_trait_bound ());
+ ResolveTypeBound::go (*type.get_trait_bound ().get ());
}
// resolve relative type-paths
@@ -210,7 +210,8 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
switch (segment->get_type ())
{
- case AST::TypePathSegment::SegmentType::GENERIC: {
+ case AST::TypePathSegment::SegmentType::GENERIC:
+ {
AST::TypePathSegmentGeneric *s
= static_cast<AST::TypePathSegmentGeneric *> (segment.get ());
if (s->has_generic_args ())
@@ -509,7 +510,8 @@ ResolveTypeToCanonicalPath::visit (AST::TypePath &path)
auto &final_seg = path.get_segments ().back ();
switch (final_seg->get_type ())
{
- case AST::TypePathSegment::SegmentType::GENERIC: {
+ case AST::TypePathSegment::SegmentType::GENERIC:
+ {
AST::TypePathSegmentGeneric *s
= static_cast<AST::TypePathSegmentGeneric *> (final_seg.get ());
@@ -651,7 +653,8 @@ ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &type)
switch (additional_bound->get_bound_type ())
{
- case AST::TypeParamBound::TRAIT: {
+ case AST::TypeParamBound::TRAIT:
+ {
auto bound_path = CanonicalPath::create_empty ();
auto &bound_type_path
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index 3e3c992..2208f70 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -24,8 +24,7 @@
#include "rust-ast-resolve-expr.h"
#include "rust-ast-resolve-struct-expr-field.h"
-extern bool
-saw_errors (void);
+extern bool saw_errors (void);
namespace Rust {
namespace Resolver {
diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc
index 480034c..f1c0e5c 100644
--- a/gcc/rust/resolve/rust-default-resolver.cc
+++ b/gcc/rust/resolve/rust-default-resolver.cc
@@ -25,6 +25,21 @@ namespace Rust {
namespace Resolver2_0 {
void
+DefaultResolver::visit (AST::Crate &crate)
+{
+ auto inner_fn = [this, &crate] () { AST::DefaultASTVisitor::visit (crate); };
+
+ auto &mappings = Analysis::Mappings::get ();
+
+ auto crate_num = mappings.lookup_crate_num (crate.get_node_id ());
+ rust_assert (crate_num.has_value ());
+ auto crate_name = mappings.get_crate_name (*crate_num);
+ rust_assert (crate_name.has_value ());
+
+ ctx.canonical_ctx.scope_crate (crate.get_node_id (), *crate_name, inner_fn);
+}
+
+void
DefaultResolver::visit (AST::BlockExpr &expr)
{
// extracting the lambda from the `scoped` call otherwise the code looks like
@@ -38,19 +53,32 @@ DefaultResolver::visit (AST::BlockExpr &expr)
void
DefaultResolver::visit (AST::Module &module)
{
- auto item_fn = [this, &module] () { AST::DefaultASTVisitor::visit (module); };
+ auto item_fn_1
+ = [this, &module] () { AST::DefaultASTVisitor::visit (module); };
+
+ auto item_fn_2 = [this, &module, &item_fn_1] () {
+ ctx.canonical_ctx.scope (module.get_node_id (), module.get_name (),
+ std::move (item_fn_1));
+ };
- ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn,
+ ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn_2,
module.get_name ());
}
void
DefaultResolver::visit (AST::Function &function)
{
- auto def_fn
+ auto def_fn_1
= [this, &function] () { AST::DefaultASTVisitor::visit (function); };
- ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn);
+ auto def_fn_2 = [this, &function, &def_fn_1] () {
+ ctx.canonical_ctx.scope (function.get_node_id (),
+ function.get_function_name (),
+ std::move (def_fn_1));
+ };
+
+ ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn_2,
+ function.get_function_name ());
}
void
@@ -61,73 +89,252 @@ DefaultResolver::visit (AST::ForLoopExpr &expr)
}
void
-DefaultResolver::visit (AST::Trait &trait)
+DefaultResolver::visit_if_let_patterns (AST::IfLetExpr &expr)
+{
+ for (auto &pattern : expr.get_patterns ())
+ visit (pattern);
+}
+
+void
+DefaultResolver::visit (AST::IfLetExpr &expr)
{
- auto inner_fn = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); };
+ auto inner_vis = [this, &expr] () {
+ visit_if_let_patterns (expr);
+ visit (expr.get_if_block ());
+ };
+
+ visit_outer_attrs (expr);
+
+ visit (expr.get_value_expr ());
+
+ ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), inner_vis);
+}
+
+void
+DefaultResolver::visit (AST::IfLetExprConseqElse &expr)
+{
+ DefaultResolver::visit (static_cast<AST::IfLetExpr &> (expr));
+ visit (expr.get_else_block ());
+}
- ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn,
+void
+DefaultResolver::visit (AST::Trait &trait)
+{
+ visit_outer_attrs (trait);
+ visit (trait.get_visibility ());
+ visit_inner_attrs (trait);
+
+ auto inner_fn_1 = [this, &trait] () {
+ for (auto &item : trait.get_trait_items ())
+ visit (item);
+ };
+
+ auto inner_fn_2 = [this, &trait, &inner_fn_1] () {
+ visit (trait.get_implicit_self ());
+ for (auto &generic : trait.get_generic_params ())
+ visit (generic);
+ if (trait.has_where_clause ())
+ visit (trait.get_where_clause ());
+ for (auto &bound : trait.get_type_param_bounds ())
+ visit (bound);
+
+ ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn_1);
+ };
+
+ auto inner_fn_3 = [this, &trait, &inner_fn_2] () {
+ ctx.canonical_ctx.scope (trait.get_node_id (), trait.get_identifier (),
+ std::move (inner_fn_2));
+ };
+
+ ctx.scoped (Rib::Kind::Generics, trait.get_node_id (), inner_fn_3,
trait.get_identifier () /* FIXME: Is that valid?*/);
}
void
DefaultResolver::visit (AST::InherentImpl &impl)
{
- auto inner_fn = [this, &impl] () { AST::DefaultASTVisitor::visit (impl); };
-
- ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn);
+ visit_outer_attrs (impl);
+ visit (impl.get_visibility ());
+ visit_inner_attrs (impl);
+
+ auto inner_fn_1 = [this, &impl] () {
+ for (auto &item : impl.get_impl_items ())
+ visit (item);
+ };
+
+ auto inner_fn_2 = [this, &impl, &inner_fn_1] () {
+ maybe_insert_big_self (impl);
+ for (auto &generic : impl.get_generic_params ())
+ visit (generic);
+ if (impl.has_where_clause ())
+ visit (impl.get_where_clause ());
+ visit_impl_type (impl.get_type ());
+
+ ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1);
+ };
+
+ auto inner_fn_3 = [this, &impl, &inner_fn_2] () {
+ ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2));
+ };
+
+ ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3);
}
void
DefaultResolver::visit (AST::TraitImpl &impl)
{
- auto inner_fn = [this, &impl] () { AST::DefaultASTVisitor::visit (impl); };
-
- ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn);
+ visit_outer_attrs (impl);
+ visit (impl.get_visibility ());
+ visit_inner_attrs (impl);
+
+ auto inner_fn_1 = [this, &impl] () {
+ for (auto &item : impl.get_impl_items ())
+ visit (item);
+ };
+
+ auto inner_fn_2 = [this, &impl, &inner_fn_1] () {
+ maybe_insert_big_self (impl);
+ for (auto &generic : impl.get_generic_params ())
+ visit (generic);
+ if (impl.has_where_clause ())
+ visit (impl.get_where_clause ());
+ visit_impl_type (impl.get_type ());
+ visit (impl.get_trait_path ());
+
+ ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1);
+ };
+
+ auto inner_fn_3 = [this, &impl, &inner_fn_2] () {
+ ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2));
+ };
+
+ ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3);
}
void
DefaultResolver::visit (AST::StructStruct &type)
{
- auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- inner_fn, type.get_struct_name ());
+ inner_fn_2, type.get_struct_name ());
}
void
DefaultResolver::visit (AST::TupleStruct &type)
{
- auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- inner_fn, type.get_struct_name ());
+ inner_fn_2, type.get_struct_name ());
+}
+
+void
+DefaultResolver::visit (AST::EnumItem &item)
+{
+ auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ inner_fn);
+}
+
+void
+DefaultResolver::visit (AST::EnumItemTuple &item)
+{
+ auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ inner_fn);
+}
+
+void
+DefaultResolver::visit (AST::EnumItemStruct &item)
+{
+ auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ inner_fn);
+}
+
+void
+DefaultResolver::visit (AST::EnumItemDiscriminant &item)
+{
+ auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ inner_fn);
}
void
DefaultResolver::visit (AST::Enum &type)
{
- auto variant_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- variant_fn, type.get_identifier ());
+ inner_fn_2, type.get_identifier ());
}
void
DefaultResolver::visit (AST::Union &type)
{
- auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- inner_fn, type.get_identifier ());
+ inner_fn_2, type.get_identifier ());
}
void
DefaultResolver::visit (AST::TypeAlias &type)
{
- auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_new_type_name (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- inner_fn, type.get_new_type_name ());
+ inner_fn_2, type.get_new_type_name ());
+}
+
+void
+DefaultResolver::visit_closure_params (AST::ClosureExpr &expr)
+{
+ for (auto &param : expr.get_params ())
+ visit (param);
+}
+
+void
+DefaultResolver::visit (AST::ClosureExpr &expr)
+{
+ auto expr_fn = [this, &expr] () {
+ visit_closure_params (expr);
+ visit (expr.get_definition_expr ());
+ };
+
+ visit_outer_attrs (expr);
+
+ ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), expr_fn);
}
void
@@ -136,7 +343,7 @@ DefaultResolver::visit (AST::ClosureExprInner &expr)
if (expr.is_marked_for_strip ())
return;
- AST::DefaultASTVisitor::visit (expr);
+ visit (static_cast<AST::ClosureExpr &> (expr));
}
void
@@ -145,7 +352,8 @@ DefaultResolver::visit (AST::ClosureExprInnerTyped &expr)
if (expr.is_marked_for_strip ())
return;
- AST::DefaultASTVisitor::visit (expr);
+ visit (static_cast<AST::ClosureExpr &> (expr));
+ visit (expr.get_return_type ());
}
void
@@ -160,23 +368,29 @@ DefaultResolver::visit (AST::MatchExpr &expr)
void
DefaultResolver::visit (AST::ConstantItem &item)
{
- if (item.has_expr ())
- {
- auto expr_vis
- = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+ auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
- // FIXME: Why do we need a Rib here?
- ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis);
- }
+ auto expr_vis_2 = [this, &item, &expr_vis_1] () {
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ std::move (expr_vis_1));
+ };
+
+ // FIXME: Why do we need a Rib here?
+ ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2);
}
void
DefaultResolver::visit (AST::StaticItem &item)
{
- auto expr_vis = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+ auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ auto expr_vis_2 = [this, &item, &expr_vis_1] () {
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ std::move (expr_vis_1));
+ };
// FIXME: Why do we need a Rib here?
- ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis);
+ ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2);
}
void
@@ -187,5 +401,46 @@ DefaultResolver::visit (AST::TypeParam &param)
ctx.scoped (Rib::Kind::ForwardTypeParamBan, param.get_node_id (), expr_vis);
}
+void
+DefaultResolver::visit_extern_crate (AST::ExternCrate &extern_crate,
+ AST::Crate &crate, CrateNum num)
+{
+ visit (crate);
+}
+
+void
+DefaultResolver::visit (AST::ExternCrate &crate)
+{
+ auto &mappings = Analysis::Mappings::get ();
+ auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ());
+
+ if (!num_opt)
+ {
+ rust_error_at (crate.get_locus (), "unknown crate %qs",
+ crate.get_referenced_crate ().c_str ());
+ return;
+ }
+
+ CrateNum num = *num_opt;
+
+ AST::Crate &referenced_crate = mappings.get_ast_crate (num);
+
+ auto sub_visitor_1
+ = [&, this] () { visit_extern_crate (crate, referenced_crate, num); };
+
+ auto sub_visitor_2 = [&] () {
+ ctx.canonical_ctx.scope_crate (referenced_crate.get_node_id (),
+ crate.get_referenced_crate (),
+ std::move (sub_visitor_1));
+ };
+
+ if (crate.has_as_clause ())
+ ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (),
+ sub_visitor_2, crate.get_as_clause ());
+ else
+ ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (),
+ sub_visitor_2, crate.get_referenced_crate ());
+}
+
} // namespace Resolver2_0
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h
index 2a987ef..cf0df68 100644
--- a/gcc/rust/resolve/rust-default-resolver.h
+++ b/gcc/rust/resolve/rust-default-resolver.h
@@ -39,6 +39,7 @@ public:
virtual ~DefaultResolver () {}
+ void visit (AST::Crate &) override;
// First, our lexical scope expressions - these visit their sub nodes, always
// these nodes create new scopes and ribs - they are often used to declare new
// variables, such as a for loop's iterator, or a function's arguments
@@ -46,20 +47,35 @@ public:
void visit (AST::Module &) override;
void visit (AST::Function &) override;
void visit (AST::ForLoopExpr &expr) override;
+ virtual void visit_if_let_patterns (AST::IfLetExpr &expr);
+ void visit (AST::IfLetExpr &expr) override;
+ void visit (AST::IfLetExprConseqElse &expr) override;
void visit (AST::Trait &) override;
+ // used to handle Self insertion in TopLevel
+ virtual void maybe_insert_big_self (AST::Impl &) {}
+ virtual void visit_impl_type (AST::Type &type) { visit (type); }
void visit (AST::InherentImpl &) override;
void visit (AST::TraitImpl &) override;
void visit (AST::TypeParam &) override;
+ virtual void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum);
+ void visit (AST::ExternCrate &) override;
+
// type dec nodes, which visit their fields or variants by default
void visit (AST::StructStruct &) override;
void visit (AST::TupleStruct &) override;
+ void visit (AST::EnumItem &) override;
+ void visit (AST::EnumItemTuple &) override;
+ void visit (AST::EnumItemStruct &) override;
+ void visit (AST::EnumItemDiscriminant &) override;
void visit (AST::Enum &) override;
void visit (AST::Union &) override;
void visit (AST::TypeAlias &) override;
// Visitors that visit their expression node(s)
+ virtual void visit_closure_params (AST::ClosureExpr &);
+ virtual void visit (AST::ClosureExpr &);
void visit (AST::ClosureExprInner &) override;
void visit (AST::ClosureExprInnerTyped &) override;
void visit (AST::MatchExpr &) override;
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 3390f09..4fd1dd2 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -17,8 +17,11 @@
// <http://www.gnu.org/licenses/>.
#include "rust-early-name-resolver-2.0.h"
-#include "rust-ast-full.h"
+#include "optional.h"
+#include "options.h"
#include "rust-diagnostics.h"
+#include "rust-hir-map.h"
+#include "rust-item.h"
#include "rust-toplevel-name-resolver-2.0.h"
#include "rust-attributes.h"
#include "rust-finalize-imports-2.0.h"
@@ -62,8 +65,9 @@ Early::go (AST::Crate &crate)
// We now proceed with resolving macros, which can be nested in almost any
// items
textual_scope.push ();
- for (auto &item : crate.items)
- item->accept_vis (*this);
+
+ visit (crate);
+
textual_scope.pop ();
}
@@ -74,8 +78,9 @@ Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
if (!resolved.has_value ())
return false;
- auto result
- = Analysis::Mappings::get ().lookup_ast_module (resolved->get_node_id ());
+ auto result = Analysis::Mappings::get ().lookup_glob_container (
+ resolved->get_node_id ());
+
if (!result)
return false;
@@ -249,7 +254,12 @@ Early::visit (AST::Module &module)
void
Early::visit (AST::MacroInvocation &invoc)
{
- auto path = invoc.get_invoc_data ().get_path ();
+ auto &path = invoc.get_invoc_data ().get_path ();
+
+ // We special case the `offset_of!()` macro if the flag is here, otherwise
+ // we accept whatever `offset_of!()` definition we resolved to.
+ auto resolve_offset_of
+ = flag_assume_builtin_offset_of && (path.as_string () == "offset_of");
if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
@@ -272,14 +282,16 @@ Early::visit (AST::MacroInvocation &invoc)
// we won't have changed `definition` from `nullopt` if there are more
// than one segments in our path
if (!definition.has_value ())
- definition = ctx.resolve_path (path.get_segments (), Namespace::Macros);
+ definition = ctx.resolve_path (path, Namespace::Macros);
- // if the definition still does not have a value, then it's an error
+ // if the definition still does not have a value, then it's an error - unless
+ // we should automatically resolve offset_of!() calls
if (!definition.has_value ())
{
- collect_error (Error (invoc.get_locus (), ErrorCode::E0433,
- "could not resolve macro invocation %qs",
- path.as_string ().c_str ()));
+ if (!resolve_offset_of)
+ collect_error (Error (invoc.get_locus (), ErrorCode::E0433,
+ "could not resolve macro invocation %qs",
+ path.as_string ().c_str ()));
return;
}
@@ -314,8 +326,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
auto traits = attr.get_traits_to_derive ();
for (auto &trait : traits)
{
- auto definition = ctx.resolve_path (trait.get ().get_segments (),
- Namespace::Macros);
+ auto definition
+ = ctx.resolve_path (trait.get (), Namespace::Macros);
if (!definition.has_value ())
{
// FIXME: Change to proper error message
@@ -337,8 +349,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
->lookup_builtin (name)
.is_error ()) // Do not resolve builtins
{
- auto definition = ctx.resolve_path (attr.get_path ().get_segments (),
- Namespace::Macros);
+ auto definition
+ = ctx.resolve_path (attr.get_path (), Namespace::Macros);
if (!definition.has_value ())
{
// FIXME: Change to proper error message
@@ -350,7 +362,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
auto pm_def = mappings.lookup_attribute_proc_macro_def (
definition->get_node_id ());
- rust_assert (pm_def.has_value ());
+ if (!pm_def.has_value ())
+ return;
mappings.insert_attribute_proc_macro_invocation (attr.get_path (),
pm_def.value ());
@@ -392,12 +405,12 @@ void
Early::finalize_glob_import (NameResolutionContext &ctx,
const Early::ImportPair &mapping)
{
- auto module = Analysis::Mappings::get ().lookup_ast_module (
- mapping.data.module ().get_node_id ());
- rust_assert (module);
+ auto container = Analysis::Mappings::get ().lookup_glob_container (
+ mapping.data.container ().get_node_id ());
+
+ rust_assert (container);
- GlobbingVisitor glob_visitor (ctx);
- glob_visitor.go (module.value ());
+ GlobbingVisitor (ctx).go (container.value ());
}
void
@@ -419,7 +432,8 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping)
declared_name = rebind.get_identifier ().as_string ();
locus = rebind.get_identifier ().get_locus ();
break;
- case AST::UseTreeRebind::NewBindType::NONE: {
+ case AST::UseTreeRebind::NewBindType::NONE:
+ {
const auto &segments = path.get_segments ();
// We don't want to insert `self` with `use module::self`
if (path.get_final_segment ().is_lower_self_seg ())
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
index e78bec0..960de0e 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -83,15 +83,15 @@ public:
return ImportData (Kind::Rebind, std::move (definitions));
}
- static ImportData Glob (Rib::Definition module)
+ static ImportData Glob (Rib::Definition container)
{
- return ImportData (Kind::Glob, module);
+ return ImportData (Kind::Glob, container);
}
- Rib::Definition module () const
+ Rib::Definition container () const
{
rust_assert (kind == Kind::Glob);
- return glob_module;
+ return glob_container;
}
std::vector<std::pair<Rib::Definition, Namespace>> definitions () const
@@ -107,8 +107,8 @@ public:
: kind (kind), resolved_definitions (std::move (definitions))
{}
- ImportData (Kind kind, Rib::Definition module)
- : kind (kind), glob_module (module)
+ ImportData (Kind kind, Rib::Definition container)
+ : kind (kind), glob_container (container)
{}
// TODO: Should this be a union?
@@ -117,7 +117,7 @@ public:
std::vector<std::pair<Rib::Definition, Namespace>> resolved_definitions;
// For Glob
- Rib::Definition glob_module;
+ Rib::Definition glob_container;
};
struct ImportPair
diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc
index fc9a26c..7b365ef 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver.cc
@@ -205,7 +205,7 @@ EarlyNameResolver::visit (AST::MetaItemLitExpr &)
{}
void
-EarlyNameResolver::visit (AST::MetaItemPathLit &)
+EarlyNameResolver::visit (AST::MetaItemPathExpr &)
{}
void
diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h
index 26fc84d..d3c5225 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.h
+++ b/gcc/rust/resolve/rust-early-name-resolver.h
@@ -142,7 +142,7 @@ private:
virtual void visit (AST::AttrInputLiteral &attr_input);
virtual void visit (AST::AttrInputMacro &attr_input);
virtual void visit (AST::MetaItemLitExpr &meta_item);
- virtual void visit (AST::MetaItemPathLit &meta_item);
+ virtual void visit (AST::MetaItemPathExpr &meta_item);
virtual void visit (AST::StructExprStruct &expr);
virtual void visit (AST::StructExprFieldIdentifier &field);
virtual void visit (AST::StructExprStructBase &expr);
diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.cc b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
index b0e8651..317acb0 100644
--- a/gcc/rust/resolve/rust-finalize-imports-2.0.cc
+++ b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
@@ -21,19 +21,44 @@
#include "rust-hir-map.h"
#include "rust-name-resolution-context.h"
#include "rust-rib.h"
+#include "rust-system.h"
#include "rust-toplevel-name-resolver-2.0.h"
namespace Rust {
namespace Resolver2_0 {
void
-GlobbingVisitor::go (AST::Module *module)
+GlobbingVisitor::go (AST::Item *container)
{
- for (auto &i : module->get_items ())
+ switch (container->get_item_kind ())
+ {
+ case AST::Item::Kind::Module:
+ visit_module_container (static_cast<AST::Module &> (*container));
+ break;
+ case AST::Item::Kind::Enum:
+ visit_enum_container (static_cast<AST::Enum &> (*container));
+ break;
+ default:
+ rust_unreachable ();
+ }
+}
+
+void
+GlobbingVisitor::visit_module_container (AST::Module &module)
+{
+ for (auto &i : module.get_items ())
visit (i);
}
void
+GlobbingVisitor::visit_enum_container (AST::Enum &item)
+{
+ for (auto &variant : item.get_variants ())
+ ctx.insert_globbed (variant->get_identifier (), variant->get_node_id (),
+ Namespace::Types);
+}
+
+void
GlobbingVisitor::visit (AST::Module &module)
{
if (module.get_visibility ().is_public ())
diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.h b/gcc/rust/resolve/rust-finalize-imports-2.0.h
index d587a5e..4ae1d6d 100644
--- a/gcc/rust/resolve/rust-finalize-imports-2.0.h
+++ b/gcc/rust/resolve/rust-finalize-imports-2.0.h
@@ -18,6 +18,7 @@
#include "rust-ast.h"
#include "rust-expr.h"
+#include "rust-item.h"
#include "rust-name-resolution-context.h"
#include "rust-toplevel-name-resolver-2.0.h"
#include "rust-early-name-resolver-2.0.h"
@@ -32,7 +33,11 @@ class GlobbingVisitor : public AST::DefaultASTVisitor
public:
GlobbingVisitor (NameResolutionContext &ctx) : ctx (ctx) {}
- void go (AST::Module *module);
+ void go (AST::Item *container);
+
+ void visit_module_container (AST::Module &module);
+ void visit_enum_container (AST::Enum &item);
+
void visit (AST::Module &module) override;
void visit (AST::MacroRulesDefinition &macro) override;
void visit (AST::Function &function) override;
diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h
index 81468e5..75dd873 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -543,6 +543,13 @@ private:
Node root;
};
+enum class ResolutionMode
+{
+ Normal,
+ FromRoot,
+ FromExtern, // extern prelude
+};
+
template <Namespace N> class ForeverStack
{
public:
@@ -672,14 +679,11 @@ public:
*/
template <typename S>
tl::optional<Rib::Definition> resolve_path (
- const std::vector<S> &segments, bool has_opening_scope_resolution,
+ const std::vector<S> &segments, ResolutionMode mode,
std::function<void (const S &, NodeId)> insert_segment_resolution,
std::vector<Error> &collect_errors);
// FIXME: Documentation
- tl::optional<Resolver::CanonicalPath> to_canonical_path (NodeId id) const;
-
- // FIXME: Documentation
tl::optional<Rib &> to_rib (NodeId rib_id);
tl::optional<const Rib &> to_rib (NodeId rib_id) const;
@@ -739,6 +743,9 @@ private:
tl::optional<Node &> parent; // `None` only if the node is a root
};
+ // private overload which allows specifying a starting point
+ tl::optional<Rib::Definition> get (Node &start, const Identifier &name);
+
/* Should we keep going upon seeing a Rib? */
enum class KeepGoing
{
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 069111ee..1ed87b3 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -291,12 +291,16 @@ ForeverStack<N>::update_cursor (Node &new_cursor)
template <Namespace N>
tl::optional<Rib::Definition>
-ForeverStack<N>::get (const Identifier &name)
+ForeverStack<N>::get (Node &start, const Identifier &name)
{
tl::optional<Rib::Definition> resolved_definition = tl::nullopt;
// TODO: Can we improve the API? have `reverse_iter` return an optional?
- reverse_iter ([&resolved_definition, &name] (Node &current) {
+ reverse_iter (start, [&resolved_definition, &name] (Node &current) {
+ // we can't reference associated types/functions like this
+ if (current.rib.kind == Rib::Kind::TraitOrImpl)
+ return KeepGoing::Yes;
+
auto candidate = current.rib.get (name.as_string ());
return candidate.map_or (
@@ -320,6 +324,13 @@ ForeverStack<N>::get (const Identifier &name)
template <Namespace N>
tl::optional<Rib::Definition>
+ForeverStack<N>::get (const Identifier &name)
+{
+ return get (cursor (), name);
+}
+
+template <Namespace N>
+tl::optional<Rib::Definition>
ForeverStack<N>::get_lang_prelude (const Identifier &name)
{
return lang_prelude.rib.get (name.as_string ());
@@ -542,6 +553,14 @@ ForeverStack<N>::resolve_segments (
bool searched_prelude = false;
while (true)
{
+ if (is_start (iterator, segments)
+ && current_node->rib.kind == Rib::Kind::TraitOrImpl)
+ {
+ // we can't reference associated types/functions like this
+ current_node = &current_node->parent.value ();
+ continue;
+ }
+
// may set the value of child
for (auto &kv : current_node->children)
{
@@ -625,88 +644,158 @@ template <Namespace N>
template <typename S>
tl::optional<Rib::Definition>
ForeverStack<N>::resolve_path (
- const std::vector<S> &segments, bool has_opening_scope_resolution,
+ const std::vector<S> &segments, ResolutionMode mode,
std::function<void (const S &, NodeId)> insert_segment_resolution,
std::vector<Error> &collect_errors)
{
- // TODO: What to do if segments.empty() ?
+ rust_assert (!segments.empty ());
- // handle paths with opening scopes
- std::function<void (void)> cleanup_current = [] () {};
- if (has_opening_scope_resolution)
+ std::reference_wrapper<Node> starting_point = cursor ();
+ switch (mode)
{
- Node *last_current = &cursor_reference.get ();
- if (get_rust_edition () == Edition::E2015)
- cursor_reference = root;
- else
- cursor_reference = extern_prelude;
- cleanup_current
- = [this, last_current] () { cursor_reference = *last_current; };
+ case ResolutionMode::Normal:
+ break; // default
+ case ResolutionMode::FromRoot:
+ starting_point = root;
+ break;
+ case ResolutionMode::FromExtern:
+ starting_point = extern_prelude;
+ break;
+ default:
+ rust_unreachable ();
}
// if there's only one segment, we just use `get`
if (segments.size () == 1)
{
- auto &seg = segments.front ();
- if (auto lang_item = unwrap_segment_get_lang_item (seg))
+ auto &outer_seg = segments.front ();
+ if (auto lang_item = unwrap_segment_get_lang_item (outer_seg))
{
NodeId seg_id = Analysis::Mappings::get ().get_lang_item_node (
lang_item.value ());
- insert_segment_resolution (seg, seg_id);
- cleanup_current ();
+ insert_segment_resolution (outer_seg, seg_id);
// TODO: does NonShadowable matter?
return Rib::Definition::NonShadowable (seg_id);
}
+ auto &seg = unwrap_type_segment (outer_seg);
+
tl::optional<Rib::Definition> res
- = get (unwrap_type_segment (segments.back ()).as_string ());
+ = get (starting_point.get (), seg.as_string ());
if (!res)
- res = get_lang_prelude (
- unwrap_type_segment (segments.back ()).as_string ());
+ res = get_lang_prelude (seg.as_string ());
+
+ if (N == Namespace::Types && !res)
+ {
+ if (seg.is_crate_path_seg ())
+ {
+ insert_segment_resolution (outer_seg, root.id);
+ // TODO: does NonShadowable matter?
+ return Rib::Definition::NonShadowable (root.id);
+ }
+ else if (seg.is_lower_self_seg ())
+ {
+ NodeId id = find_closest_module (starting_point.get ()).id;
+ insert_segment_resolution (outer_seg, id);
+ // TODO: does NonShadowable matter?
+ return Rib::Definition::NonShadowable (id);
+ }
+ else if (seg.is_super_path_seg ())
+ {
+ Node &closest_module
+ = find_closest_module (starting_point.get ());
+ if (closest_module.is_root ())
+ {
+ rust_error_at (seg.get_locus (), ErrorCode::E0433,
+ "too many leading %<super%> keywords");
+ return tl::nullopt;
+ }
+
+ NodeId id
+ = find_closest_module (closest_module.parent.value ()).id;
+ insert_segment_resolution (outer_seg, id);
+ // TODO: does NonShadowable matter?
+ return Rib::Definition::NonShadowable (id);
+ }
+ else
+ {
+ // HACK: check for a module after we check the language prelude
+ for (auto &kv :
+ find_closest_module (starting_point.get ()).children)
+ {
+ auto &link = kv.first;
+
+ if (link.path.map_or (
+ [&seg] (Identifier path) {
+ auto &path_str = path.as_string ();
+ return path_str == seg.as_string ();
+ },
+ false))
+ {
+ insert_segment_resolution (outer_seg, kv.second.id);
+ return Rib::Definition::NonShadowable (kv.second.id);
+ }
+ }
+ }
+ }
if (res && !res->is_ambiguous ())
- insert_segment_resolution (segments.back (), res->get_node_id ());
- cleanup_current ();
+ insert_segment_resolution (outer_seg, res->get_node_id ());
return res;
}
- std::reference_wrapper<Node> starting_point = cursor ();
+ return find_starting_point (segments, starting_point,
+ insert_segment_resolution, collect_errors)
+ .and_then (
+ [this, &segments, &starting_point, &insert_segment_resolution,
+ &collect_errors] (typename std::vector<S>::const_iterator iterator) {
+ return resolve_segments (starting_point.get (), segments, iterator,
+ insert_segment_resolution, collect_errors);
+ })
+ .and_then ([this, &segments, &insert_segment_resolution] (
+ Node &final_node) -> tl::optional<Rib::Definition> {
+ // leave resolution within impl blocks to type checker
+ if (final_node.rib.kind == Rib::Kind::TraitOrImpl)
+ return tl::nullopt;
+
+ auto &seg = unwrap_type_segment (segments.back ());
+ std::string seg_name = seg.as_string ();
+
+ // assuming this can't be a lang item segment
+ tl::optional<Rib::Definition> res
+ = resolve_final_segment (final_node, seg_name,
+ seg.is_lower_self_seg ());
+ // Ok we didn't find it in the rib, Lets try the prelude...
+ if (!res)
+ res = get_lang_prelude (seg_name);
- auto res
- = find_starting_point (segments, starting_point, insert_segment_resolution,
- collect_errors)
- .and_then (
- [this, &segments, &starting_point, &insert_segment_resolution,
- &collect_errors] (typename std::vector<S>::const_iterator iterator) {
- return resolve_segments (starting_point.get (), segments, iterator,
- insert_segment_resolution, collect_errors);
- })
- .and_then ([this, &segments, &insert_segment_resolution] (
- Node &final_node) -> tl::optional<Rib::Definition> {
- // leave resolution within impl blocks to type checker
- if (final_node.rib.kind == Rib::Kind::TraitOrImpl)
- return tl::nullopt;
-
- auto &seg = unwrap_type_segment (segments.back ());
- std::string seg_name = seg.as_string ();
-
- // assuming this can't be a lang item segment
- tl::optional<Rib::Definition> res
- = resolve_final_segment (final_node, seg_name,
- seg.is_lower_self_seg ());
- // Ok we didn't find it in the rib, Lets try the prelude...
- if (!res)
- res = get_lang_prelude (seg_name);
-
- if (res && !res->is_ambiguous ())
- insert_segment_resolution (segments.back (), res->get_node_id ());
-
- return res;
- });
- cleanup_current ();
- return res;
+ if (N == Namespace::Types && !res)
+ {
+ // HACK: check for a module after we check the language prelude
+ for (auto &kv : final_node.children)
+ {
+ auto &link = kv.first;
+
+ if (link.path.map_or (
+ [&seg_name] (Identifier path) {
+ auto &path_str = path.as_string ();
+ return path_str == seg_name;
+ },
+ false))
+ {
+ insert_segment_resolution (segments.back (), kv.second.id);
+ return Rib::Definition::NonShadowable (kv.second.id);
+ }
+ }
+ }
+
+ if (res && !res->is_ambiguous ())
+ insert_segment_resolution (segments.back (), res->get_node_id ());
+
+ return res;
+ });
}
template <Namespace N>
@@ -771,67 +860,6 @@ ForeverStack<N>::dfs (const ForeverStack<N>::Node &starting_point,
}
template <Namespace N>
-tl::optional<Resolver::CanonicalPath>
-ForeverStack<N>::to_canonical_path (NodeId id) const
-{
- // find the id in the current forever stack, starting from the root,
- // performing either a BFS or DFS once the Node containing the ID is found, go
- // back up to the root (parent().parent().parent()...) accumulate link
- // segments reverse them that's your canonical path
-
- return dfs (root, id).map ([this, id] (ConstDfsResult tuple) {
- auto containing_node = tuple.first;
- auto name = tuple.second;
-
- auto segments = std::vector<Resolver::CanonicalPath> ();
-
- reverse_iter (containing_node, [&segments] (const Node &current) {
- if (current.is_root ())
- return KeepGoing::No;
-
- auto children = current.parent.value ().children;
- const Link *outer_link = nullptr;
-
- for (auto &kv : children)
- {
- auto &link = kv.first;
- auto &child = kv.second;
-
- if (current.id == child.id)
- {
- outer_link = &link;
- break;
- }
- }
-
- rust_assert (outer_link);
-
- outer_link->path.map ([&segments, outer_link] (Identifier path) {
- segments.emplace (segments.begin (),
- Resolver::CanonicalPath::new_seg (outer_link->id,
- path.as_string ()));
- });
-
- return KeepGoing::Yes;
- });
-
- auto &mappings = Analysis::Mappings::get ();
- CrateNum crate_num = mappings.lookup_crate_num (root.id).value ();
- auto path = Resolver::CanonicalPath::new_seg (
- root.id, mappings.get_crate_name (crate_num).value ());
- path.set_crate_num (crate_num);
-
- for (const auto &segment : segments)
- path = path.append (segment);
-
- // Finally, append the name
- path = path.append (Resolver::CanonicalPath::new_seg (id, name));
-
- return path;
- });
-}
-
-template <Namespace N>
tl::optional<Rib &>
ForeverStack<N>::dfs_rib (ForeverStack<N>::Node &starting_point, NodeId to_find)
{
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index a15e17f..e39ca15 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -19,6 +19,7 @@
#include "optional.h"
#include "rust-ast-full.h"
#include "rust-diagnostics.h"
+#include "rust-expr.h"
#include "rust-hir-map.h"
#include "rust-late-name-resolver-2.0.h"
#include "rust-default-resolver.h"
@@ -33,7 +34,9 @@
namespace Rust {
namespace Resolver2_0 {
-Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {}
+Late::Late (NameResolutionContext &ctx)
+ : DefaultResolver (ctx), funny_error (false), block_big_self (false)
+{}
static NodeId
next_node_id ()
@@ -114,8 +117,7 @@ Late::go (AST::Crate &crate)
{
setup_builtin_types ();
- for (auto &item : crate.items)
- item->accept_vis (*this);
+ visit (crate);
}
void
@@ -140,24 +142,21 @@ Late::visit (AST::ForLoopExpr &expr)
ctx.bindings.exit ();
visit (expr.get_iterator_expr ());
- visit (expr.get_loop_label ());
+
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
+
visit (expr.get_loop_block ());
}
void
-Late::visit (AST::IfLetExpr &expr)
+Late::visit_if_let_patterns (AST::IfLetExpr &expr)
{
- visit_outer_attrs (expr);
+ ctx.bindings.enter (BindingSource::IfLet);
- ctx.bindings.enter (BindingSource::Let);
-
- for (auto &pattern : expr.get_patterns ())
- visit (pattern);
+ DefaultResolver::visit_if_let_patterns (expr);
ctx.bindings.exit ();
-
- visit (expr.get_value_expr ());
- visit (expr.get_if_block ());
}
void
@@ -214,45 +213,80 @@ Late::visit (AST::LetStmt &let)
}
void
-Late::visit (AST::IdentifierPattern &identifier)
+Late::visit (AST::WhileLetLoopExpr &while_let)
+{
+ DefaultASTVisitor::visit_outer_attrs (while_let);
+
+ if (while_let.has_loop_label ())
+ visit (while_let.get_loop_label ());
+
+ // visit expression before pattern
+ // this makes variable shadowing work properly
+ visit (while_let.get_scrutinee_expr ());
+
+ ctx.bindings.enter (BindingSource::WhileLet);
+
+ for (auto &pattern : while_let.get_patterns ())
+ visit (pattern);
+
+ ctx.bindings.exit ();
+
+ visit (while_let.get_loop_block ());
+}
+
+static void
+visit_identifier_as_pattern (NameResolutionContext &ctx,
+ const Identifier &ident, location_t locus,
+ NodeId node_id, bool is_ref, bool is_mut)
{
// do we insert in labels or in values
// but values does not allow shadowing... since functions cannot shadow
// do we insert functions in labels as well?
- if (ctx.bindings.peek ().is_and_bound (identifier.get_ident ()))
+ if (ctx.bindings.peek ().is_and_bound (ident))
{
if (ctx.bindings.peek ().get_source () == BindingSource::Param)
rust_error_at (
- identifier.get_locus (), ErrorCode::E0415,
+ locus, ErrorCode::E0415,
"identifier %qs is bound more than once in the same parameter list",
- identifier.as_string ().c_str ());
+ ident.as_string ().c_str ());
else
rust_error_at (
- identifier.get_locus (), ErrorCode::E0416,
+ locus, ErrorCode::E0416,
"identifier %qs is bound more than once in the same pattern",
- identifier.as_string ().c_str ());
+ ident.as_string ().c_str ());
return;
}
- ctx.bindings.peek ().insert_ident (identifier.get_ident ());
+ ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
- if (ctx.bindings.peek ().is_or_bound (identifier.get_ident ()))
+ if (ctx.bindings.peek ().is_or_bound (ident))
{
- // FIXME: map usage instead
- std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
- identifier.get_node_id ());
+ auto res = ctx.values.get (ident);
+ rust_assert (res.has_value () && !res->is_ambiguous ());
+ ctx.map_usage (Usage (node_id), Definition (res->get_node_id ()));
}
else
{
// We do want to ignore duplicated data because some situations rely on
// it.
- std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
- identifier.get_node_id ());
+ std::ignore = ctx.values.insert_shadowable (ident, node_id);
}
}
void
+Late::visit (AST::IdentifierPattern &identifier)
+{
+ DefaultResolver::visit (identifier);
+
+ visit_identifier_as_pattern (ctx, identifier.get_ident (),
+ identifier.get_locus (),
+ identifier.get_node_id (),
+ identifier.get_is_ref (),
+ identifier.get_is_mut ());
+}
+
+void
Late::visit (AST::AltPattern &pattern)
{
ctx.bindings.peek ().push (Binding::Kind::Or);
@@ -279,9 +313,9 @@ Late::visit_function_params (AST::Function &function)
void
Late::visit (AST::StructPatternFieldIdent &field)
{
- // We do want to ignore duplicated data because some situations rely on it.
- std::ignore = ctx.values.insert_shadowable (field.get_identifier (),
- field.get_node_id ());
+ visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (),
+ field.get_node_id (), field.is_ref (),
+ field.is_mut ());
}
void
@@ -375,7 +409,8 @@ Late::visit (AST::IdentifierExpr &expr)
}
else if (funny_error)
{
- diagnostics::text_finalizer (global_dc) = Resolver::funny_ice_text_finalizer;
+ diagnostics::text_finalizer (global_dc)
+ = Resolver::funny_ice_text_finalizer;
emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
"are you trying to break %s? how dare you?",
expr.as_string ().c_str ());
@@ -477,6 +512,16 @@ Late::visit (AST::PathInExpression &expr)
}
void
+Late::visit_impl_type (AST::Type &type)
+{
+ // TODO: does this have to handle reentrancy?
+ rust_assert (!block_big_self);
+ block_big_self = true;
+ visit (type);
+ block_big_self = false;
+}
+
+void
Late::visit (AST::TypePath &type)
{
// should we add type path resolution in `ForeverStack` directly? Since it's
@@ -486,6 +531,16 @@ Late::visit (AST::TypePath &type)
DefaultResolver::visit (type);
+ // prevent "impl Self {}" and similar
+ if (type.get_segments ().size () == 1
+ && !type.get_segments ().front ()->is_lang_item ()
+ && type.get_segments ().front ()->is_big_self_seg () && block_big_self)
+ {
+ rust_error_at (type.get_locus (),
+ "%<Self%> is not valid in the self type of an impl block");
+ return;
+ }
+
// this *should* mostly work
// TODO: make sure typepath-like path resolution (?) is working
auto resolved = ctx.resolve_path (type, Namespace::Types);
@@ -493,15 +548,16 @@ Late::visit (AST::TypePath &type)
if (!resolved.has_value ())
{
if (!ctx.lookup (type.get_segments ().front ()->get_node_id ()))
- rust_error_at (type.get_locus (), "could not resolve type path %qs",
- type.as_string ().c_str ());
+ rust_error_at (type.get_locus (), ErrorCode::E0412,
+ "could not resolve type path %qs",
+ type.make_debug_string ().c_str ());
return;
}
if (resolved->is_ambiguous ())
{
rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
- type.as_string ().c_str ());
+ type.make_debug_string ().c_str ());
return;
}
@@ -518,6 +574,62 @@ Late::visit (AST::TypePath &type)
}
void
+Late::visit (AST::Visibility &vis)
+{
+ if (!vis.has_path ())
+ return;
+
+ AST::SimplePath &path = vis.get_path ();
+
+ rust_assert (path.get_segments ().size ());
+ auto &first_seg = path.get_segments ()[0];
+
+ auto mode = ResolutionMode::Normal;
+
+ if (path.has_opening_scope_resolution ())
+ {
+ if (get_rust_edition () == Edition::E2015)
+ mode = ResolutionMode::FromRoot;
+ else
+ mode = ResolutionMode::FromExtern;
+ }
+ else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
+ && !first_seg.is_lower_self_seg ())
+ {
+ if (get_rust_edition () == Edition::E2015)
+ {
+ mode = ResolutionMode::FromRoot;
+ }
+ else
+ {
+ rust_error_at (path.get_locus (),
+ "relative paths are not supported in visibilities in "
+ "2018 edition or later");
+ return;
+ }
+ }
+
+ auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
+
+ if (!res.has_value ())
+ {
+ rust_error_at (path.get_locus (), ErrorCode::E0433,
+ "could not resolve path %qs", path.as_string ().c_str ());
+ return;
+ }
+
+ // TODO: is this possible?
+ if (res->is_ambiguous ())
+ {
+ rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
+ path.as_string ().c_str ());
+ return;
+ }
+
+ ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id ()));
+}
+
+void
Late::visit (AST::Trait &trait)
{
// kind of weird how this is done
@@ -531,13 +643,6 @@ Late::visit (AST::Trait &trait)
}
void
-Late::visit (AST::StructStruct &s)
-{
- auto s_vis = [this, &s] () { AST::DefaultASTVisitor::visit (s); };
- ctx.scoped (Rib::Kind::Item, s.get_node_id (), s_vis);
-}
-
-void
Late::visit (AST::StructExprStruct &s)
{
visit_outer_attrs (s);
@@ -613,51 +718,27 @@ Late::visit (AST::GenericArg &arg)
DefaultResolver::visit (arg);
}
-template <class Closure>
-static void
-add_captures (Closure &closure, NameResolutionContext &ctx)
-{
- auto vals = ctx.values.peek ().get_values ();
- for (auto &val : vals)
- {
- ctx.mappings.add_capture (closure.get_node_id (),
- val.second.get_node_id ());
- }
-}
-
void
-Late::visit (AST::ClosureExprInner &closure)
+Late::visit_closure_params (AST::ClosureExpr &closure)
{
- add_captures (closure, ctx);
-
- visit_outer_attrs (closure);
-
ctx.bindings.enter (BindingSource::Param);
- for (auto &param : closure.get_params ())
- visit (param);
+ DefaultResolver::visit_closure_params (closure);
ctx.bindings.exit ();
-
- visit (closure.get_definition_expr ());
}
void
-Late::visit (AST::ClosureExprInnerTyped &closure)
+Late::visit (AST::ClosureExpr &expr)
{
- add_captures (closure, ctx);
-
- visit_outer_attrs (closure);
-
- ctx.bindings.enter (BindingSource::Param);
-
- for (auto &param : closure.get_params ())
- visit (param);
-
- ctx.bindings.exit ();
+ // add captures
+ auto vals = ctx.values.peek ().get_values ();
+ for (auto &val : vals)
+ {
+ ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ());
+ }
- visit (closure.get_return_type ());
- visit (closure.get_definition_block ());
+ DefaultResolver::visit (expr);
}
} // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
index 171d9bf..95540e3 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -42,6 +42,7 @@ public:
// some more label declarations
void visit (AST::LetStmt &) override;
+ void visit (AST::WhileLetLoopExpr &) override;
// TODO: Do we need this?
// void visit (AST::Method &) override;
void visit (AST::IdentifierPattern &) override;
@@ -50,7 +51,7 @@ public:
void visit (AST::SelfParam &) override;
void visit (AST::MatchArm &) override;
void visit (AST::ForLoopExpr &) override;
- void visit (AST::IfLetExpr &) override;
+ void visit_if_let_patterns (AST::IfLetExpr &) override;
// resolutions
void visit (AST::IdentifierExpr &) override;
@@ -59,16 +60,17 @@ public:
void visit (AST::ContinueExpr &) override;
void visit (AST::LoopLabel &) override;
void visit (AST::PathInExpression &) override;
+ void visit_impl_type (AST::Type &) override;
void visit (AST::TypePath &) override;
+ void visit (AST::Visibility &) override;
void visit (AST::Trait &) override;
void visit (AST::StructExprStruct &) override;
void visit (AST::StructExprStructBase &) override;
void visit (AST::StructExprStructFields &) override;
- void visit (AST::StructStruct &) override;
void visit (AST::GenericArgs &) override;
void visit (AST::GenericArg &);
- void visit (AST::ClosureExprInner &) override;
- void visit (AST::ClosureExprInnerTyped &) override;
+ void visit_closure_params (AST::ClosureExpr &) override;
+ void visit (AST::ClosureExpr &) override;
private:
void resolve_label (AST::Lifetime &lifetime);
@@ -77,6 +79,9 @@ private:
void setup_builtin_types ();
bool funny_error;
+
+ /* used to prevent "impl Self {}", "impl (Self, i32) {}", etc */
+ bool block_big_self;
};
// TODO: Add missing mappings and data structures
diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc
index f098e48..1b84f1d 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -33,7 +33,8 @@ BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
{
for (auto &bind : bindings)
{
- if (bind.set.find (ident) != bind.set.cend () && bind.kind == kind)
+ if (bind.idents.find (ident.as_string ()) != bind.idents.cend ()
+ && bind.kind == kind)
{
return true;
}
@@ -60,20 +61,66 @@ BindingLayer::is_or_bound (Identifier ident)
}
void
-BindingLayer::insert_ident (Identifier ident)
+BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref,
+ bool is_mut)
{
- bindings.back ().set.insert (ident);
+ bindings.back ().idents.emplace (
+ std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut)));
}
void
BindingLayer::merge ()
{
- auto last_binding = bindings.back ();
+ auto last_binding = std::move (bindings.back ());
bindings.pop_back ();
- for (auto &value : last_binding.set)
+
+ if (bindings.back ().has_expected_bindings)
+ {
+ for (auto &value : bindings.back ().idents)
+ {
+ auto ident = value.first;
+ if (last_binding.idents.find (ident) == last_binding.idents.end ())
+ {
+ location_t locus = value.second.first;
+ rust_error_at (locus, ErrorCode::E0408,
+ "variable %qs is not bound in all patterns",
+ ident.c_str ());
+ }
+ }
+ }
+
+ for (auto &value : last_binding.idents)
{
- bindings.back ().set.insert (value);
+ auto res = bindings.back ().idents.emplace (value);
+ if (res.second)
+ {
+ if (bindings.back ().has_expected_bindings)
+ {
+ auto &ident = value.first;
+ location_t locus = value.second.first;
+ rust_error_at (locus, ErrorCode::E0408,
+ "variable %qs is not bound in all patterns",
+ ident.c_str ());
+ }
+ }
+ else
+ {
+ auto this_mode = value.second.second;
+ auto other_mode = res.first->second.second;
+ if (this_mode != other_mode)
+ {
+ auto &ident = value.first;
+ location_t locus = value.second.first;
+ rust_error_at (locus, ErrorCode::E0409,
+ "variable %qs is bound inconsistently across "
+ "pattern alternatives",
+ ident.c_str ());
+ }
+ }
}
+
+ if (bindings.back ().kind == Binding::Kind::Or)
+ bindings.back ().has_expected_bindings = true;
}
BindingSource
@@ -82,8 +129,63 @@ BindingLayer::get_source () const
return source;
}
+Resolver::CanonicalPath
+CanonicalPathRecordCrateRoot::as_path (const NameResolutionContext &)
+{
+ auto ret = Resolver::CanonicalPath::new_seg (node_id, seg);
+ ret.set_crate_num (crate_num);
+ return ret;
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx)
+{
+ auto parent_path = get_parent ().as_path (ctx);
+ return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg));
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordLookup::as_path (const NameResolutionContext &ctx)
+{
+ if (!cache)
+ {
+ auto res = ctx.lookup (lookup_id).and_then (
+ [&ctx] (NodeId id) { return ctx.canonical_ctx.get_record_opt (id); });
+
+ if (!res)
+ {
+ // HACK: use a dummy value
+ // this should bring us roughly to parity with nr1.0
+ // since nr1.0 doesn't seem to handle canonical paths for generics
+ // quite right anyways
+ return Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "XXX");
+ }
+
+ cache = res.value ();
+ }
+ return cache->as_path (ctx);
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx)
+{
+ auto parent_path = get_parent ().as_path (ctx);
+ return parent_path.append (
+ Resolver::CanonicalPath::inherent_impl_seg (impl_id,
+ type_record.as_path (ctx)));
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordTraitImpl::as_path (const NameResolutionContext &ctx)
+{
+ auto parent_path = get_parent ().as_path (ctx);
+ return parent_path.append (
+ Resolver::CanonicalPath::trait_impl_projection_seg (
+ impl_id, trait_path_record.as_path (ctx), type_record.as_path (ctx)));
+}
+
NameResolutionContext::NameResolutionContext ()
- : mappings (Analysis::Mappings::get ())
+ : mappings (Analysis::Mappings::get ()), canonical_ctx (*this)
{}
tl::expected<NodeId, DuplicateNameError>
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h
index 19ba750..558b3ca 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -24,6 +24,7 @@
#include "rust-hir-map.h"
#include "rust-rib.h"
#include "rust-stacked-contexts.h"
+#include "rust-item.h"
namespace Rust {
namespace Resolver2_0 {
@@ -157,6 +158,22 @@ public:
NodeId id;
};
+struct IdentifierMode
+{
+ bool is_ref;
+ bool is_mut;
+
+ IdentifierMode (bool is_ref, bool is_mut) : is_ref (is_ref), is_mut (is_mut)
+ {}
+
+ bool operator== (const IdentifierMode &other)
+ {
+ return other.is_ref == is_ref && other.is_mut == is_mut;
+ }
+
+ bool operator!= (const IdentifierMode &other) { return !(*this == other); }
+};
+
struct Binding
{
enum class Kind
@@ -165,9 +182,12 @@ struct Binding
Or,
} kind;
- std::unordered_set<Identifier> set;
+ // used to check the correctness of or-bindings
+ bool has_expected_bindings;
- Binding (Binding::Kind kind) : kind (kind) {}
+ std::unordered_map<std::string, std::pair<location_t, IdentifierMode>> idents;
+
+ Binding (Binding::Kind kind) : kind (kind), has_expected_bindings (false) {}
};
/**
@@ -177,6 +197,8 @@ enum class BindingSource
{
Match,
Let,
+ IfLet,
+ WhileLet,
For,
/* Closure param or function param */
Param
@@ -206,13 +228,256 @@ public:
*/
bool is_or_bound (Identifier ident);
- void insert_ident (Identifier ident);
+ void insert_ident (std::string ident, location_t locus, bool is_ref,
+ bool is_mut);
void merge ();
BindingSource get_source () const;
};
+class NameResolutionContext;
+/*
+ * Used to handle canonical paths
+ * Similar to ForeverStack, but namespace independent and more specialized
+ */
+class CanonicalPathRecord
+{
+public:
+ virtual Resolver::CanonicalPath as_path (const NameResolutionContext &) = 0;
+
+ virtual bool is_root () const = 0;
+
+ virtual ~CanonicalPathRecord () = default;
+};
+
+class CanonicalPathRecordWithParent : public CanonicalPathRecord
+{
+public:
+ CanonicalPathRecordWithParent (CanonicalPathRecord &parent) : parent (&parent)
+ {}
+
+ CanonicalPathRecord &get_parent () { return *parent; }
+
+ bool is_root () const override final { return false; }
+
+private:
+ CanonicalPathRecord *parent;
+};
+
+class CanonicalPathRecordCrateRoot : public CanonicalPathRecord
+{
+public:
+ CanonicalPathRecordCrateRoot (NodeId node_id, std::string seg)
+ : node_id (node_id), seg (std::move (seg))
+ {
+ rust_assert (Analysis::Mappings::get ().node_is_crate (node_id));
+ crate_num = Analysis::Mappings::get ().lookup_crate_num (node_id).value ();
+ }
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+ bool is_root () const override final { return true; }
+
+private:
+ NodeId node_id;
+ CrateNum crate_num;
+ std::string seg;
+};
+
+class CanonicalPathRecordNormal : public CanonicalPathRecordWithParent
+{
+public:
+ CanonicalPathRecordNormal (CanonicalPathRecord &parent, NodeId node_id,
+ std::string seg)
+ : CanonicalPathRecordWithParent (parent), node_id (node_id),
+ seg (std::move (seg))
+ {
+ rust_assert (!Analysis::Mappings::get ().node_is_crate (node_id));
+ }
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+private:
+ NodeId node_id;
+ std::string seg;
+};
+
+class CanonicalPathRecordLookup : public CanonicalPathRecord
+{
+public:
+ CanonicalPathRecordLookup (NodeId lookup_id)
+ : lookup_id (lookup_id), cache (nullptr)
+ {}
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+ bool is_root () const override final { return true; }
+
+private:
+ NodeId lookup_id;
+ CanonicalPathRecord *cache;
+};
+
+class CanonicalPathRecordImpl : public CanonicalPathRecordWithParent
+{
+public:
+ CanonicalPathRecordImpl (CanonicalPathRecord &parent, NodeId impl_id,
+ NodeId type_id)
+ : CanonicalPathRecordWithParent (parent), impl_id (impl_id),
+ type_record (type_id)
+ {}
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+private:
+ NodeId impl_id;
+ CanonicalPathRecordLookup type_record;
+};
+
+class CanonicalPathRecordTraitImpl : public CanonicalPathRecordWithParent
+{
+public:
+ CanonicalPathRecordTraitImpl (CanonicalPathRecord &parent, NodeId impl_id,
+ NodeId type_id, NodeId trait_path_id)
+ : CanonicalPathRecordWithParent (parent), impl_id (impl_id),
+ type_record (type_id), trait_path_record (trait_path_id)
+ {}
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+private:
+ NodeId impl_id;
+ CanonicalPathRecordLookup type_record;
+ CanonicalPathRecordLookup trait_path_record;
+};
+
+class CanonicalPathCtx
+{
+public:
+ CanonicalPathCtx (const NameResolutionContext &ctx)
+ : current_record (nullptr), nr_ctx (&ctx)
+ {}
+
+ Resolver::CanonicalPath get_path (NodeId id) const
+ {
+ return get_record (id).as_path (*nr_ctx);
+ }
+
+ CanonicalPathRecord &get_record (NodeId id) const
+ {
+ auto it = records.find (id);
+ rust_assert (it != records.end ());
+ return *it->second;
+ }
+
+ tl::optional<CanonicalPathRecord *> get_record_opt (NodeId id) const
+ {
+ auto it = records.find (id);
+ if (it == records.end ())
+ return tl::nullopt;
+ else
+ return it->second.get ();
+ }
+
+ void insert_record (NodeId id, const Identifier &ident)
+ {
+ insert_record (id, ident.as_string ());
+ }
+
+ void insert_record (NodeId id, std::string seg)
+ {
+ rust_assert (current_record != nullptr);
+
+ auto it = records.find (id);
+ if (it == records.end ())
+ {
+ auto record = new CanonicalPathRecordNormal (*current_record, id,
+ std::move (seg));
+ bool ok
+ = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record))
+ .second;
+ rust_assert (ok);
+ }
+ }
+
+ template <typename F> void scope (NodeId id, const Identifier &ident, F &&f)
+ {
+ scope (id, ident.as_string (), std::forward<F> (f));
+ }
+
+ template <typename F> void scope (NodeId id, std::string seg, F &&f)
+ {
+ rust_assert (current_record != nullptr);
+
+ scope_inner (id, std::forward<F> (f), [this, id, &seg] () {
+ return new CanonicalPathRecordNormal (*current_record, id,
+ std::move (seg));
+ });
+ }
+
+ template <typename F> void scope_impl (AST::InherentImpl &impl, F &&f)
+ {
+ rust_assert (current_record != nullptr);
+
+ NodeId id = impl.get_node_id ();
+ scope_inner (id, std::forward<F> (f), [this, id, &impl] () {
+ return new CanonicalPathRecordImpl (*current_record, id,
+ impl.get_type ().get_node_id ());
+ });
+ }
+
+ template <typename F> void scope_impl (AST::TraitImpl &impl, F &&f)
+ {
+ rust_assert (current_record != nullptr);
+
+ NodeId id = impl.get_node_id ();
+ scope_inner (id, std::forward<F> (f), [this, id, &impl] () {
+ return new CanonicalPathRecordTraitImpl (
+ *current_record, id, impl.get_type ().get_node_id (),
+ impl.get_trait_path ().get_node_id ());
+ });
+ }
+
+ template <typename F>
+ void scope_crate (NodeId node_id, std::string crate_name, F &&f)
+ {
+ scope_inner (node_id, std::forward<F> (f), [node_id, &crate_name] () {
+ return new CanonicalPathRecordCrateRoot (node_id, std::move (crate_name));
+ });
+ }
+
+private:
+ template <typename FCreate, typename FCallback>
+ void scope_inner (NodeId id, FCallback &&f_callback, FCreate &&f_create)
+ {
+ auto it = records.find (id);
+ if (it == records.end ())
+ {
+ CanonicalPathRecord *record = std::forward<FCreate> (f_create) ();
+ it = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record))
+ .first;
+ }
+
+ rust_assert (it->second->is_root ()
+ || &static_cast<CanonicalPathRecordWithParent &> (*it->second)
+ .get_parent ()
+ == current_record);
+
+ CanonicalPathRecord *stash = it->second.get ();
+ std::swap (stash, current_record);
+
+ std::forward<FCallback> (f_callback) ();
+
+ std::swap (stash, current_record);
+ }
+
+ std::unordered_map<NodeId, std::unique_ptr<CanonicalPathRecord>> records;
+ CanonicalPathRecord *current_record;
+
+ const NameResolutionContext *nr_ctx;
+};
+
// Now our resolver, which keeps track of all the `ForeverStack`s we could want
class NameResolutionContext
{
@@ -271,16 +536,22 @@ public:
Analysis::Mappings &mappings;
StackedContexts<BindingLayer> bindings;
+ CanonicalPathCtx canonical_ctx;
+
// TODO: Rename
// TODO: Use newtype pattern for Usage and Definition
void map_usage (Usage usage, Definition definition);
tl::optional<NodeId> lookup (NodeId usage) const;
+ Resolver::CanonicalPath to_canonical_path (NodeId id) const
+ {
+ return canonical_ctx.get_path (id);
+ }
+
template <typename S>
tl::optional<Rib::Definition>
- resolve_path (const std::vector<S> &segments,
- bool has_opening_scope_resolution,
+ resolve_path (const std::vector<S> &segments, ResolutionMode mode,
std::vector<Error> &collect_errors, Namespace ns)
{
std::function<void (const S &, NodeId)> insert_segment_resolution
@@ -292,17 +563,17 @@ public:
switch (ns)
{
case Namespace::Values:
- return values.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution, collect_errors);
+ return values.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
case Namespace::Types:
- return types.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution, collect_errors);
+ return types.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
case Namespace::Macros:
- return macros.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution, collect_errors);
+ return macros.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
case Namespace::Labels:
- return labels.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution, collect_errors);
+ return labels.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
default:
rust_unreachable ();
}
@@ -310,8 +581,7 @@ public:
template <typename S, typename... Args>
tl::optional<Rib::Definition>
- resolve_path (const std::vector<S> &segments,
- bool has_opening_scope_resolution,
+ resolve_path (const std::vector<S> &segments, ResolutionMode mode,
tl::optional<std::vector<Error> &> collect_errors,
Namespace ns_first, Args... ns_args)
{
@@ -320,8 +590,7 @@ public:
for (auto ns : namespaces)
{
std::vector<Error> collect_errors_inner;
- if (auto ret = resolve_path (segments, has_opening_scope_resolution,
- collect_errors_inner, ns))
+ if (auto ret = resolve_path (segments, mode, collect_errors_inner, ns))
return ret;
if (!collect_errors_inner.empty ())
{
@@ -343,52 +612,68 @@ public:
return tl::nullopt;
}
- template <typename... Args>
+ template <typename S, typename... Args>
tl::optional<Rib::Definition>
- resolve_path (const AST::SimplePath &path,
+ resolve_path (const std::vector<S> &path_segments,
+ bool has_opening_scope_resolution,
tl::optional<std::vector<Error> &> collect_errors,
Namespace ns_first, Args... ns_args)
{
- return resolve_path (path.get_segments (),
- path.has_opening_scope_resolution (), collect_errors,
- ns_first, ns_args...);
+ auto mode = ResolutionMode::Normal;
+ if (has_opening_scope_resolution)
+ {
+ if (get_rust_edition () == Edition::E2015)
+ mode = ResolutionMode::FromRoot;
+ else
+ mode = ResolutionMode::FromExtern;
+ }
+ return resolve_path (path_segments, mode, collect_errors, ns_first,
+ ns_args...);
}
- template <typename... Args>
+ template <typename S, typename... Args>
tl::optional<Rib::Definition>
- resolve_path (const AST::PathInExpression &path,
- tl::optional<std::vector<Error> &> collect_errors,
- Namespace ns_first, Args... ns_args)
+ resolve_path (const std::vector<S> &path_segments,
+ bool has_opening_scope_resolution, Namespace ns_first,
+ Args... ns_args)
{
- return resolve_path (path.get_segments (), path.opening_scope_resolution (),
- collect_errors, ns_first, ns_args...);
+ return resolve_path (path_segments, has_opening_scope_resolution,
+ tl::nullopt, ns_first, ns_args...);
}
- template <typename... Args>
+ template <typename S, typename... Args>
tl::optional<Rib::Definition>
- resolve_path (const AST::TypePath &path,
- tl::optional<std::vector<Error> &> collect_errors,
+ resolve_path (const std::vector<S> &path_segments, ResolutionMode mode,
Namespace ns_first, Args... ns_args)
{
+ return resolve_path (path_segments, mode, tl::nullopt, ns_first,
+ ns_args...);
+ }
+
+ template <typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const AST::SimplePath &path,
+ Args &&...args)
+ {
return resolve_path (path.get_segments (),
- path.has_opening_scope_resolution_op (),
- collect_errors, ns_first, ns_args...);
+ path.has_opening_scope_resolution (),
+ std::forward<Args> (args)...);
}
- template <typename P, typename... Args>
- tl::optional<Rib::Definition> resolve_path (const P &path, Namespace ns_first,
- Args... ns_args)
+ template <typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const AST::PathInExpression &path,
+ Args &&...args)
{
- return resolve_path (path, tl::nullopt, ns_first, ns_args...);
+ return resolve_path (path.get_segments (), path.opening_scope_resolution (),
+ std::forward<Args> (args)...);
}
- template <typename P, typename... Args>
- tl::optional<Rib::Definition>
- resolve_path (const P &path_segments, bool has_opening_scope_resolution,
- Namespace ns_first, Args... ns_args)
+ template <typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const AST::TypePath &path,
+ Args &&...args)
{
- return resolve_path (path_segments, has_opening_scope_resolution,
- tl::nullopt, ns_first, ns_args...);
+ return resolve_path (path.get_segments (),
+ path.has_opening_scope_resolution_op (),
+ std::forward<Args> (args)...);
}
private:
diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h
index c498328..140c991 100644
--- a/gcc/rust/resolve/rust-rib.h
+++ b/gcc/rust/resolve/rust-rib.h
@@ -188,6 +188,8 @@ public:
* restriction that you cannot `use` items from the Prelude
*/
Prelude,
+ /* Generic rib, used to store generics */
+ Generics,
} kind;
static std::string kind_to_string (Rib::Kind kind)
@@ -214,9 +216,13 @@ public:
return "Forward type param ban";
case Rib::Kind::ConstParamType:
return "Const Param Type";
- default:
- rust_unreachable ();
+ case Kind::Prelude:
+ return "Prelude";
+ case Kind::Generics:
+ return "Generics";
}
+
+ rust_unreachable ();
}
Rib (Kind kind);
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index 2f036fe..0930f96 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -95,41 +95,17 @@ TopLevel::go (AST::Crate &crate)
// times in a row in a fixed-point fashion, so it would make the code
// responsible for this ugly and perfom a lot of error checking.
- for (auto &item : crate.items)
- item->accept_vis (*this);
+ visit (crate);
}
void
TopLevel::visit (AST::Module &module)
{
- insert_or_error_out (module.get_name (), module, Namespace::Types);
-
- // Parse the module's items if they haven't been expanded and the file
- // should be parsed (i.e isn't hidden behind an untrue or impossible cfg
- // directive
- // TODO: make sure this is right
- // TODO: avoid loading items if cfg attributes are present?
- // might not be needed if this runs after early resolution?
- // This was copied from the old early resolver method
- // 'accumulate_escaped_macros'
- if (module.get_kind () == AST::Module::UNLOADED)
- {
- module.load_items ();
-
- // If the module was previously unloaded, then we don't want to visit it
- // this time around as the CfgStrip hasn't run on its inner items yet.
- // Skip it for now, mark the visitor as dirty and try again
-
- dirty = true;
-
- return;
- }
-
DefaultResolver::visit (module);
- if (Analysis::Mappings::get ().lookup_ast_module (module.get_node_id ())
+ if (Analysis::Mappings::get ().lookup_glob_container (module.get_node_id ())
== tl::nullopt)
- Analysis::Mappings::get ().insert_ast_module (&module);
+ Analysis::Mappings::get ().insert_glob_container (&module);
}
void
@@ -141,33 +117,10 @@ TopLevel::visit (AST::Trait &trait)
}
void
-TopLevel::visit (AST::InherentImpl &impl)
-{
- auto inner_fn = [this, &impl] () {
- insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()),
- impl.get_type (), Namespace::Types);
-
- // We do want to visit with the default visitor instead of default resolver
- // because we don't want to insert the scope twice.
- AST::DefaultASTVisitor::visit (impl);
- };
-
- ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn);
-}
-
-void
-TopLevel::visit (AST::TraitImpl &impl)
+TopLevel::maybe_insert_big_self (AST::Impl &impl)
{
- auto inner_fn = [this, &impl] () {
- insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()),
- impl.get_type (), Namespace::Types);
-
- // We do want to visit using the default visitor instead of default resolver
- // because we don't want to insert the scope twice.
- AST::DefaultASTVisitor::visit (impl);
- };
-
- ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn);
+ insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()),
+ impl.get_type (), Namespace::Types);
}
void
@@ -197,19 +150,10 @@ insert_macros (std::vector<PROC_MACRO> &macros, NameResolutionContext &ctx)
}
void
-TopLevel::visit (AST::ExternCrate &crate)
+TopLevel::visit_extern_crate (AST::ExternCrate &extern_crate, AST::Crate &crate,
+ CrateNum num)
{
auto &mappings = Analysis::Mappings::get ();
- auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ());
-
- if (!num_opt)
- {
- rust_error_at (crate.get_locus (), "unknown crate %qs",
- crate.get_referenced_crate ().c_str ());
- return;
- }
-
- CrateNum num = *num_opt;
auto attribute_macros = mappings.lookup_attribute_proc_macros (num);
@@ -217,34 +161,27 @@ TopLevel::visit (AST::ExternCrate &crate)
auto derive_macros = mappings.lookup_derive_proc_macros (num);
- auto sub_visitor = [&] () {
- // TODO: Find a way to keep this part clean without the double dispatch.
- if (derive_macros.has_value ())
- {
- insert_macros (derive_macros.value (), ctx);
- for (auto &macro : derive_macros.value ())
- mappings.insert_derive_proc_macro_def (macro);
- }
- if (attribute_macros.has_value ())
- {
- insert_macros (attribute_macros.value (), ctx);
- for (auto &macro : attribute_macros.value ())
- mappings.insert_attribute_proc_macro_def (macro);
- }
- if (bang_macros.has_value ())
- {
- insert_macros (bang_macros.value (), ctx);
- for (auto &macro : bang_macros.value ())
- mappings.insert_bang_proc_macro_def (macro);
- }
- };
+ // TODO: Find a way to keep this part clean without the double dispatch.
+ if (derive_macros.has_value ())
+ {
+ insert_macros (derive_macros.value (), ctx);
+ for (auto &macro : derive_macros.value ())
+ mappings.insert_derive_proc_macro_def (macro);
+ }
+ if (attribute_macros.has_value ())
+ {
+ insert_macros (attribute_macros.value (), ctx);
+ for (auto &macro : attribute_macros.value ())
+ mappings.insert_attribute_proc_macro_def (macro);
+ }
+ if (bang_macros.has_value ())
+ {
+ insert_macros (bang_macros.value (), ctx);
+ for (auto &macro : bang_macros.value ())
+ mappings.insert_bang_proc_macro_def (macro);
+ }
- if (crate.has_as_clause ())
- ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor,
- crate.get_as_clause ());
- else
- ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor,
- crate.get_referenced_crate ());
+ visit (crate);
}
static bool
@@ -321,14 +258,7 @@ TopLevel::visit (AST::ExternalStaticItem &static_item)
void
TopLevel::visit (AST::StructStruct &struct_item)
{
- auto generic_vis = [this, &struct_item] () {
- for (auto &g : struct_item.get_generic_params ())
- {
- g->accept_vis (*this);
- }
- };
-
- ctx.scoped (Rib::Kind::Item, struct_item.get_node_id (), generic_vis);
+ DefaultResolver::visit (struct_item);
insert_or_error_out (struct_item.get_struct_name (), struct_item,
Namespace::Types);
@@ -374,24 +304,32 @@ void
TopLevel::visit (AST::EnumItem &variant)
{
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
+
+ DefaultResolver::visit (variant);
}
void
TopLevel::visit (AST::EnumItemTuple &variant)
{
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
+
+ DefaultResolver::visit (variant);
}
void
TopLevel::visit (AST::EnumItemStruct &variant)
{
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
+
+ DefaultResolver::visit (variant);
}
void
TopLevel::visit (AST::EnumItemDiscriminant &variant)
{
insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+
+ DefaultResolver::visit (variant);
}
void
@@ -401,6 +339,13 @@ TopLevel::visit (AST::Enum &enum_item)
Namespace::Types);
DefaultResolver::visit (enum_item);
+
+ // Since enums can be containers for imports, we need to insert them like we
+ // do for modules
+ if (Analysis::Mappings::get ().lookup_glob_container (
+ enum_item.get_node_id ())
+ == tl::nullopt)
+ Analysis::Mappings::get ().insert_glob_container (&enum_item);
}
void
@@ -430,21 +375,18 @@ TopLevel::visit (AST::TypeAlias &type_item)
DefaultResolver::visit (type_item);
}
-static void
-flatten_rebind (
+static void flatten_rebind (
const AST::UseTreeRebind &glob,
std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths);
-static void
-flatten_list (
+static void flatten_list (
const AST::UseTreeList &glob, std::vector<AST::SimplePath> &paths,
std::vector<AST::SimplePath> &glob_paths,
std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths,
NameResolutionContext &ctx);
-static void
-flatten_glob (const AST::UseTreeGlob &glob,
- std::vector<AST::SimplePath> &glob_paths,
- NameResolutionContext &ctx);
+static void flatten_glob (const AST::UseTreeGlob &glob,
+ std::vector<AST::SimplePath> &glob_paths,
+ NameResolutionContext &ctx);
static void
flatten (
@@ -455,17 +397,20 @@ flatten (
{
switch (tree->get_kind ())
{
- case AST::UseTree::Rebind: {
+ case AST::UseTree::Rebind:
+ {
auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
flatten_rebind (*rebind, rebind_paths);
break;
}
- case AST::UseTree::List: {
+ case AST::UseTree::List:
+ {
auto list = static_cast<const AST::UseTreeList *> (tree);
flatten_list (*list, paths, glob_paths, rebind_paths, ctx);
break;
}
- case AST::UseTree::Glob: {
+ case AST::UseTree::Glob:
+ {
auto glob = static_cast<const AST::UseTreeGlob *> (tree);
flatten_glob (*glob, glob_paths, ctx);
break;
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
index 3ff37ed..8d3da92 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
@@ -160,8 +160,7 @@ private:
void visit (AST::Module &module) override;
void visit (AST::Trait &trait) override;
- void visit (AST::InherentImpl &impl) override;
- void visit (AST::TraitImpl &impl) override;
+ void maybe_insert_big_self (AST::Impl &impl) override;
void visit (AST::TraitItemType &trait_item) override;
void visit (AST::MacroRulesDefinition &macro) override;
void visit (AST::Function &function) override;
@@ -177,7 +176,7 @@ private:
void visit (AST::Union &union_item) override;
void visit (AST::ConstantItem &const_item) override;
void visit (AST::TypeAlias &type_item) override;
- void visit (AST::ExternCrate &crate) override;
+ void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum) override;
void visit (AST::TypeParam &type_param) override;
void visit (AST::ConstGenericParam &const_param) override;
diff --git a/gcc/rust/rust-attribs.cc b/gcc/rust/rust-attribs.cc
index 74cb2af..a98c1fa 100644
--- a/gcc/rust/rust-attribs.cc
+++ b/gcc/rust/rust-attribs.cc
@@ -38,35 +38,27 @@ along with GCC; see the file COPYING3. If not see
* future.
*/
-extern const attribute_spec grs_langhook_common_attribute_table[];
+extern const struct scoped_attribute_specs grs_langhook_gnu_attribute_table;
+extern const struct scoped_attribute_specs grs_langhook_common_attribute_table;
/* Internal attribute handlers for built-in functions. */
-static tree
-handle_noreturn_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_leaf_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_const_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_malloc_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_pure_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_novops_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_nonnull_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_nothrow_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_type_generic_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_fnspec_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *);
+static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
+static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
+static tree handle_const_attribute (tree *, tree, tree, int, bool *);
+static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
+static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
+static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
+static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
+static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
+static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *);
+
+/* Rust attribute handlers for user defined attributes. */
+static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
+static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
/* Helper to define attribute exclusions. */
#define ATTR_EXCL(name, function, type, variable) \
@@ -74,6 +66,10 @@ handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *);
name, function, type, variable \
}
+// clang-format off
+// Disabling clang-format because it insists in having several ATTR_EXCL() on a
+// single line.
+
static const struct attribute_spec::exclusions attr_noreturn_exclusions[] = {
// ATTR_EXCL ("alloc_size", true, true, true),
ATTR_EXCL ("const", true, true, true),
@@ -89,11 +85,22 @@ static const struct attribute_spec::exclusions attr_returns_twice_exclusions[]
ATTR_EXCL (NULL, false, false, false),
};
+extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] = {
+
+ ATTR_EXCL ("cold", true, true, true),
+ ATTR_EXCL ("hot", true, true, true),
+ ATTR_EXCL (NULL, false, false, false)
+};
+
static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = {
// ATTR_EXCL ("alloc_size", true, true, true),
ATTR_EXCL ("const", true, true, true),
ATTR_EXCL ("noreturn", true, true, true),
- ATTR_EXCL ("pure", true, true, true), ATTR_EXCL (NULL, false, false, false)};
+ ATTR_EXCL ("pure", true, true, true),
+ ATTR_EXCL (NULL, false, false, false)
+};
+
+// clang-format on
/* Helper to define an attribute. */
#define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \
@@ -105,7 +112,7 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = {
/* Table of machine-independent attributes.
For internal use (marking of built-ins) only. */
-const attribute_spec grs_langhook_common_attribute_table[] = {
+static const attribute_spec grs_langhook_common_attributes[] = {
ATTR_SPEC ("noreturn", 0, 0, true, false, false, false,
handle_noreturn_attribute, attr_noreturn_exclusions),
ATTR_SPEC ("leaf", 0, 0, true, false, false, false, handle_leaf_attribute,
@@ -132,9 +139,21 @@ const attribute_spec grs_langhook_common_attribute_table[] = {
NULL),
ATTR_SPEC ("omp declare simd", 0, -1, true, false, false, false,
handle_omp_declare_simd_attribute, NULL),
- ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
};
+const scoped_attribute_specs grs_langhook_common_attribute_table
+ = {"gnu", {grs_langhook_common_attributes}};
+
+static const attribute_spec grs_langhook_gnu_attributes[] = {
+ ATTR_SPEC ("cold", 0, 0, true, false, false, false, handle_cold_attribute,
+ attr_cold_hot_exclusions),
+ ATTR_SPEC ("hot", 0, 0, true, false, false, false, handle_hot_attribute,
+ attr_cold_hot_exclusions),
+};
+
+const scoped_attribute_specs grs_langhook_gnu_attribute_table
+ = {"gnu", {grs_langhook_gnu_attributes}};
+
/* Built-in attribute handlers.
These functions take the arguments:
(tree *node, tree name, tree args, int flags, bool *no_add_attrs) */
@@ -204,7 +223,7 @@ handle_const_attribute (tree *node, tree, tree, int, bool *)
/* Handle a "malloc" attribute; arguments as in
struct attribute_spec.handler. */
-tree
+static tree
handle_malloc_attribute (tree *node, tree, tree, int, bool *)
{
gcc_assert (TREE_CODE (*node) == FUNCTION_DECL
@@ -217,9 +236,14 @@ handle_malloc_attribute (tree *node, tree, tree, int, bool *)
struct attribute_spec.handler. */
static tree
-handle_pure_attribute (tree *node, tree, tree, int, bool *)
+handle_pure_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
DECL_PURE_P (*node) = 1;
return NULL_TREE;
}
@@ -228,9 +252,14 @@ handle_pure_attribute (tree *node, tree, tree, int, bool *)
struct attribute_spec.handler. */
static tree
-handle_novops_attribute (tree *node, tree, tree, int, bool *)
+handle_novops_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
DECL_IS_NOVOPS (*node) = 1;
return NULL_TREE;
}
@@ -301,9 +330,14 @@ handle_nonnull_attribute (tree *node, tree, tree args, int, bool *)
struct attribute_spec.handler. */
static tree
-handle_nothrow_attribute (tree *node, tree, tree, int, bool *)
+handle_nothrow_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
TREE_NOTHROW (*node) = 1;
return NULL_TREE;
}
@@ -339,9 +373,14 @@ handle_transaction_pure_attribute (tree *node, tree, tree, int, bool *)
struct attribute_spec.handler. */
static tree
-handle_returns_twice_attribute (tree *node, tree, tree, int, bool *)
+handle_returns_twice_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
DECL_IS_RETURNS_TWICE (*node) = 1;
@@ -351,7 +390,7 @@ handle_returns_twice_attribute (tree *node, tree, tree, int, bool *)
/* Handle a "fn spec" attribute; arguments as in
struct attribute_spec.handler. */
-tree
+static tree
handle_fnspec_attribute (tree *, tree, tree args, int, bool *)
{
gcc_assert (args && TREE_CODE (TREE_VALUE (args)) == STRING_CST
@@ -362,9 +401,46 @@ handle_fnspec_attribute (tree *, tree, tree args, int, bool *)
/* Handle an "omp declare simd" attribute; arguments as in
struct attribute_spec.handler. */
-tree
-handle_omp_declare_simd_attribute (tree *node, tree, tree, int, bool *)
+static tree
+handle_omp_declare_simd_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Language specific attribute handlers.
+ These functions take the arguments:
+ (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */
+
+/* Handle a "cold" and attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_cold_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+static tree
+handle_hot_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
return NULL_TREE;
}
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index 414799e..95ca7a9 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -27,6 +27,8 @@
#include "rust-linemap.h"
#include "rust-diagnostics.h"
#include "util/rust-operators.h"
+#include "util/rust-ggc.h"
+#include "util/optional.h"
#include "tree.h"
#include "rust-gcc.h"
@@ -42,69 +44,60 @@ class Bvariable;
namespace Backend {
-void
-init ();
+namespace GGC {
+
+using Rust::GGC::Ident;
+
+} // namespace GGC
+
+void init ();
// Name/type/location. Used for function parameters, struct fields,
// interface methods.
struct typed_identifier
{
- std::string name;
+ GGC::Ident name;
tree type;
location_t location;
- typed_identifier () : name (), type (NULL_TREE), location (UNKNOWN_LOCATION)
- {}
-
- typed_identifier (const std::string &a_name, tree a_type,
- location_t a_location)
+ typed_identifier (GGC::Ident a_name, tree a_type, location_t a_location)
: name (a_name), type (a_type), location (a_location)
{}
};
// debug
void debug (tree);
-void
-debug (Bvariable *);
+void debug (Bvariable *);
-tree
-get_identifier_node (const std::string &str);
+tree get_identifier_node (const std::string &str);
// Types.
// Get the wchar type
-tree
-wchar_type ();
+tree wchar_type ();
// Get the Host pointer size in bits
-int
-get_pointer_size ();
+int get_pointer_size ();
// Get the raw str type const char*
-tree
-raw_str_type ();
+tree raw_str_type ();
// Get an unnamed integer type with the given signedness and number
// of bits.
-tree
-integer_type (bool is_unsigned, int bits);
+tree integer_type (bool is_unsigned, int bits);
// Get an unnamed floating point type with the given number of bits
// (32 or 64).
-tree
-float_type (int bits);
+tree float_type (int bits);
// Get a pointer type.
-tree
-pointer_type (tree to_type);
+tree pointer_type (tree to_type);
// Get a reference type.
-tree
-reference_type (tree to_type);
+tree reference_type (tree to_type);
// make type immutable
-tree
-immutable_type (tree base);
+tree immutable_type (tree base);
// Get a function type. The receiver, parameter, and results are
// generated from the types in the Function_type. The Function_type
@@ -115,41 +108,36 @@ immutable_type (tree base);
// one result, RESULT_STRUCT is a struct type to hold the results,
// and RESULTS may be ignored; if there are zero or one results,
// RESULT_STRUCT is NULL.
-tree
-function_type (const typed_identifier &receiver,
- const std::vector<typed_identifier> &parameters,
- const std::vector<typed_identifier> &results, tree result_struct,
- location_t location);
-
-tree
-function_type_variadic (const typed_identifier &receiver,
- const std::vector<typed_identifier> &parameters,
- const std::vector<typed_identifier> &results,
- tree result_struct, location_t location);
-
-tree
-function_ptr_type (tree result, const std::vector<tree> &praameters,
- location_t location);
+tree function_type (const typed_identifier &receiver,
+ const std::vector<typed_identifier> &parameters,
+ const std::vector<typed_identifier> &results,
+ tree result_struct, location_t location);
+
+tree function_type_variadic (const typed_identifier &receiver,
+ const std::vector<typed_identifier> &parameters,
+ const std::vector<typed_identifier> &results,
+ tree result_struct, location_t location);
+
+tree function_ptr_type (tree result, const std::vector<tree> &praameters,
+ location_t location);
// Get a struct type.
-tree
-struct_type (const std::vector<typed_identifier> &fields, bool layout = true);
+tree struct_type (const std::vector<typed_identifier> &fields,
+ bool layout = true);
// Get a union type.
-tree
-union_type (const std::vector<typed_identifier> &fields, bool layout = true);
+tree union_type (const std::vector<typed_identifier> &fields,
+ bool layout = true);
// Get an array type.
-tree
-array_type (tree element_type, tree length);
+tree array_type (tree element_type, tree length);
// Return a named version of a type. The location is the location
// of the type definition. This will not be called for a type
// created via placeholder_pointer_type, placeholder_struct_type, or
// placeholder_array_type.. (It may be called for a pointer,
// struct, or array type in a case like "type P *byte; type Q P".)
-tree
-named_type (const std::string &name, tree, location_t);
+tree named_type (GGC::Ident name, tree, location_t);
// Return the size of a type.
int64_t type_size (tree);
@@ -164,8 +152,7 @@ int64_t type_field_alignment (tree);
// Return the offset of field INDEX in a struct type. INDEX is the
// entry in the FIELDS std::vector parameter of struct_type or
// set_placeholder_struct_type.
-int64_t
-type_field_offset (tree, size_t index);
+int64_t type_field_offset (tree, size_t index);
// Expressions.
@@ -175,155 +162,135 @@ type_field_offset (tree, size_t index);
tree zero_expression (tree);
// Create a reference to a variable.
-tree
-var_expression (Bvariable *var, location_t);
+tree var_expression (Bvariable *var, location_t);
// Return an expression for the floating point value VAL in BTYPE.
-tree
-float_constant_expression (tree btype, mpfr_t val);
+tree float_constant_expression (tree btype, mpfr_t val);
// Return an expression for the string value VAL.
-tree
-string_constant_expression (const std::string &val);
+tree string_constant_expression (const std::string &val);
// Get a char literal
-tree
-char_constant_expression (char c);
+tree char_constant_expression (char c);
// Get a char literal
-tree
-wchar_constant_expression (wchar_t c);
+tree wchar_constant_expression (wchar_t c);
+
+// Get a size literal
+tree size_constant_expression (size_t val);
// Return an expression for the boolean value VAL.
-tree
-boolean_constant_expression (bool val);
+tree boolean_constant_expression (bool val);
// Return an expression that converts EXPR to TYPE.
-tree
-convert_expression (tree type, tree expr, location_t);
+tree convert_expression (tree type, tree expr, location_t);
// Return an expression for the field at INDEX in BSTRUCT.
-tree
-struct_field_expression (tree bstruct, size_t index, location_t);
+tree struct_field_expression (tree bstruct, size_t index, location_t);
// Create an expression that executes BSTAT before BEXPR.
-tree
-compound_expression (tree bstat, tree bexpr, location_t);
+tree compound_expression (tree bstat, tree bexpr, location_t);
// Return an expression that executes THEN_EXPR if CONDITION is true, or
// ELSE_EXPR otherwise and returns the result as type BTYPE, within the
// specified function FUNCTION. ELSE_EXPR may be NULL. BTYPE may be NULL.
-tree
-conditional_expression (tree function, tree btype, tree condition,
- tree then_expr, tree else_expr, location_t);
+tree conditional_expression (tree function, tree btype, tree condition,
+ tree then_expr, tree else_expr, location_t);
// Return an expression for the negation operation OP EXPR.
// Supported values of OP are enumerated in NegationOperator.
-tree
-negation_expression (NegationOperator op, tree expr, location_t);
+tree negation_expression (NegationOperator op, tree expr, location_t);
// Return an expression for the operation LEFT OP RIGHT.
// Supported values of OP are enumerated in ArithmeticOrLogicalOperator.
-tree
-arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left,
- tree right, location_t loc);
+tree arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op,
+ tree left, tree right, location_t loc);
// Return an expression for the operation LEFT OP RIGHT.
// Supported values of OP are enumerated in ArithmeticOrLogicalOperator.
// This function adds overflow checking and returns a list of statements to
// add to the current function context. The `receiver` variable refers to the
// variable which will contain the result of that operation.
-tree
-arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op,
- tree left, tree right, location_t loc,
- Bvariable *receiver);
+tree arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op,
+ tree left, tree right,
+ location_t loc,
+ Bvariable *receiver);
// Return an expression for the operation LEFT OP RIGHT.
// Supported values of OP are enumerated in ComparisonOperator.
-tree
-comparison_expression (ComparisonOperator op, tree left, tree right,
- location_t loc);
+tree comparison_expression (ComparisonOperator op, tree left, tree right,
+ location_t loc);
// Return an expression for the operation LEFT OP RIGHT.
// Supported values of OP are enumerated in LazyBooleanOperator.
-tree
-lazy_boolean_expression (LazyBooleanOperator op, tree left, tree right,
- location_t);
+tree lazy_boolean_expression (LazyBooleanOperator op, tree left, tree right,
+ location_t);
// Return an expression that constructs BTYPE with VALS. BTYPE must be the
// backend representation a of struct. VALS must be in the same order as the
// corresponding fields in BTYPE.
-tree
-constructor_expression (tree btype, bool is_variant,
- const std::vector<tree> &vals, int, location_t);
+tree constructor_expression (tree btype, bool is_variant,
+ const std::vector<tree> &vals, int, location_t);
// Return an expression that constructs an array of BTYPE with INDEXES and
// VALS. INDEXES and VALS must have the same amount of elements. Each index
// in INDEXES must be in the same order as the corresponding value in VALS.
-tree
-array_constructor_expression (tree btype,
- const std::vector<unsigned long> &indexes,
- const std::vector<tree> &vals, location_t);
+tree array_constructor_expression (tree btype,
+ const std::vector<unsigned long> &indexes,
+ const std::vector<tree> &vals, location_t);
-tree
-array_initializer (tree, tree, tree, tree, tree, tree *, location_t);
+tree array_initializer (tree, tree, tree, tree, tree, tree *, location_t);
// Return an expression for ARRAY[INDEX] as an l-value. ARRAY is a valid
// fixed-length array, not a slice.
-tree
-array_index_expression (tree array, tree index, location_t);
+tree array_index_expression (tree array, tree index, location_t);
+
+// Return an expresison for SLICE[INDEX] as an l-value. SLICE is represented
+// with a DST.
+tree slice_index_expression (tree slice, tree index, location_t);
// Create an expression for a call to FN with ARGS, taking place within
// caller CALLER.
-tree
-call_expression (tree fn, const std::vector<tree> &args, tree static_chain,
- location_t);
+tree call_expression (tree fn, const std::vector<tree> &args, tree static_chain,
+ location_t);
// Statements.
// Create a variable initialization statement in the specified
// function. This initializes a local variable at the point in the
// program flow where it is declared.
-tree
-init_statement (tree, Bvariable *var, tree init);
+tree init_statement (tree, Bvariable *var, tree init);
// Create an assignment statement within the specified function.
-tree
-assignment_statement (tree lhs, tree rhs, location_t);
+tree assignment_statement (tree lhs, tree rhs, location_t);
// Create return statement for an decl for a value (can be NULL_TREE) at a
// location
-tree
-return_statement (tree fndecl, tree val, location_t);
+tree return_statement (tree fndecl, tree val, location_t);
// Create an if statement within a function. ELSE_BLOCK may be NULL.
-tree
-if_statement (tree, tree condition, tree then_block, tree else_block,
- location_t);
+tree if_statement (tree, tree condition, tree then_block, tree else_block,
+ location_t);
// infinite loop expressions
-tree
-loop_expression (tree body, location_t);
+tree loop_expression (tree body, location_t);
// exit expressions
-tree
-exit_expression (tree condition, location_t);
+tree exit_expression (tree condition, location_t);
// Create a single statement from two statements.
tree compound_statement (tree, tree);
// Create a single statement from a list of statements.
-tree
-statement_list (const std::vector<tree> &);
+tree statement_list (const std::vector<tree> &);
// Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if
// an exception occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and
// if not NULL, it will always be executed. This is used for handling defers
// in Go functions. In C++, the resulting code is of this form:
// try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; }
-tree
-exception_handler_statement (tree bstat, tree except_stmt, tree finally_stmt,
- location_t);
+tree exception_handler_statement (tree bstat, tree except_stmt,
+ tree finally_stmt, location_t);
// Blocks.
@@ -337,16 +304,14 @@ exception_handler_statement (tree bstat, tree except_stmt, tree finally_stmt,
// the initial curly brace. END_LOCATION is the location of the end
// of the block, more or less the location of the final curly brace.
// The statements will be added after the block is created.
-tree
-block (tree function, tree enclosing, const std::vector<Bvariable *> &vars,
- location_t start_location, location_t end_location);
+tree block (tree function, tree enclosing, const std::vector<Bvariable *> &vars,
+ location_t start_location, location_t end_location);
// Add the statements to a block. The block is created first. Then
// the statements are created. Then the statements are added to the
// block. This will called exactly once per block. The vector may
// be empty if there are no statements.
-void
-block_add_statements (tree, const std::vector<tree> &);
+void block_add_statements (tree, const std::vector<tree> &);
// Variables.
@@ -360,10 +325,9 @@ block_add_statements (tree, const std::vector<tree> &);
// be put into a unique section if possible; this is intended to
// permit the linker to garbage collect the variable if it is not
// referenced. LOCATION is where the variable was defined.
-Bvariable *
-global_variable (const std::string &name, const std::string &asm_name,
- tree btype, bool is_external, bool is_hidden,
- bool in_unique_section, location_t location);
+Bvariable *global_variable (GGC::Ident name, GGC::Ident asm_name, tree btype,
+ bool is_external, bool is_hidden,
+ bool in_unique_section, location_t location);
// A global variable will 1) be initialized to zero, or 2) be
// initialized to a constant value, or 3) be initialized in the init
@@ -371,8 +335,7 @@ global_variable (const std::string &name, const std::string &asm_name,
// global_variable_set_init to set the initial value. If this is
// not called, the backend should initialize a global variable to 0.
// The init function may then assign a value to it.
-void
-global_variable_set_init (Bvariable *, tree);
+void global_variable_set_init (Bvariable *, tree);
// Create a local variable. The frontend will create the local
// variables first, and then create the block which contains them.
@@ -386,21 +349,18 @@ global_variable_set_init (Bvariable *, tree);
// the function, as otherwise the variable would be on the heap).
// LOCATION is where the variable is defined. For each local variable
// the frontend will call init_statement to set the initial value.
-Bvariable *
-local_variable (tree function, const std::string &name, tree type,
- Bvariable *decl_var, location_t location);
+Bvariable *local_variable (tree function, GGC::Ident name, tree type,
+ Bvariable *decl_var, location_t location);
// Create a function parameter. This is an incoming parameter, not
// a result parameter (result parameters are treated as local
// variables). The arguments are as for local_variable.
-Bvariable *
-parameter_variable (tree function, const std::string &name, tree type,
- location_t location);
+Bvariable *parameter_variable (tree function, GGC::Ident name, tree type,
+ location_t location);
// Create a static chain parameter. This is the closure parameter.
-Bvariable *
-static_chain_variable (tree function, const std::string &name, tree type,
- location_t location);
+Bvariable *static_chain_variable (tree function, GGC::Ident name, tree type,
+ location_t location);
// Create a temporary variable. A temporary variable has no name,
// just a type. We pass in FUNCTION and BLOCK in case they are
@@ -413,18 +373,16 @@ static_chain_variable (tree function, const std::string &name, tree type,
// variable, and may not be very useful. This function should
// return a variable which can be referenced later and should set
// *PSTATEMENT to a statement which initializes the variable.
-Bvariable *
-temporary_variable (tree fndecl, tree bind_tree, tree type, tree init,
- bool address_is_taken, location_t location,
- tree *pstatement);
+Bvariable *temporary_variable (tree fndecl, tree bind_tree, tree type,
+ tree init, bool address_is_taken,
+ location_t location, tree *pstatement);
// Labels.
-// Create a new label. NAME will be empty if this is a label
+// Create a new label. NAME will be tl::nullopt if this is a label
// created by the frontend for a loop construct. The location is
// where the label is defined.
-tree
-label (tree, const std::string &name, location_t);
+tree label (tree, tl::optional<GGC::Ident> name, location_t);
// Create a statement which defines a label. This statement will be
// put into the codestream at the point where the label should be
@@ -439,6 +397,12 @@ tree goto_statement (tree, location_t);
// recover.
tree label_address (tree, location_t);
+// Lookup a field from a type given its name.
+// Build the `component` tree with `Backend::get_identifier_node`.
+//
+// Forked from the C frontend.
+tree lookup_field (const_tree, tree);
+
// Functions.
// Bit flags to pass to the function method.
@@ -460,43 +424,38 @@ static const unsigned int function_does_not_return = 1 << 2;
static const unsigned int function_in_unique_section = 1 << 3;
// Declare or define a function of FNTYPE.
-// NAME is the Go name of the function. ASM_NAME, if not the empty
-// string, is the name that should be used in the symbol table; this
+// NAME is the Go name of the function. ASM_NAME, if not tl::nullopt,
+// is the name that should be used in the symbol table; this
// will be non-empty if a magic extern comment is used. FLAGS is
// bit flags described above.
-tree
-function (tree fntype, const std::string &name, const std::string &asm_name,
- unsigned int flags, location_t);
+tree function (tree fntype, GGC::Ident name, tl::optional<GGC::Ident> asm_name,
+ unsigned int flags, location_t);
// Create a statement that runs all deferred calls for FUNCTION. This should
// be a statement that looks like this in C++:
// finish:
// try { DEFER_RETURN; } catch { CHECK_DEFER; goto finish; }
-tree
-function_defer_statement (tree function, tree undefer, tree check_defer,
- location_t);
+tree function_defer_statement (tree function, tree undefer, tree check_defer,
+ location_t);
// Record PARAM_VARS as the variables to use for the parameters of FUNCTION.
// This will only be called for a function definition. Returns true on
// success, false on failure.
-bool
-function_set_parameters (tree function,
- const std::vector<Bvariable *> &param_vars);
+bool function_set_parameters (tree function,
+ const std::vector<Bvariable *> &param_vars);
// Utility.
// Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
// FUNCTION_DECLS, and VARIABLE_DECLS declared globally.
-void
-write_global_definitions (const std::vector<tree> &type_decls,
- const std::vector<tree> &constant_decls,
- const std::vector<tree> &function_decls,
- const std::vector<Bvariable *> &variable_decls);
+void write_global_definitions (const std::vector<tree> &type_decls,
+ const std::vector<tree> &constant_decls,
+ const std::vector<tree> &function_decls,
+ const std::vector<Bvariable *> &variable_decls);
// TODO: make static
-tree
-fill_in_fields (tree, const std::vector<typed_identifier> &, bool);
+tree fill_in_fields (tree, const std::vector<typed_identifier> &, bool);
tree fill_in_array (tree, tree, tree);
diff --git a/gcc/rust/rust-diagnostics.cc b/gcc/rust/rust-diagnostics.cc
index 702da71..5965bb4 100644
--- a/gcc/rust/rust-diagnostics.cc
+++ b/gcc/rust/rust-diagnostics.cc
@@ -48,27 +48,33 @@ expand_format (const char *fmt)
c++;
switch (*c)
{
- case '\0': {
+ case '\0':
+ {
// malformed format string
rust_unreachable ();
}
- case '%': {
+ case '%':
+ {
ss << "%";
break;
}
- case 'm': {
+ case 'm':
+ {
ss << mformat_value ();
break;
}
- case '<': {
+ case '<':
+ {
ss << rust_open_quote ();
break;
}
- case '>': {
+ case '>':
+ {
ss << rust_close_quote ();
break;
}
- case 'q': {
+ case 'q':
+ {
ss << rust_open_quote ();
c++;
if (*c == 'm')
@@ -82,7 +88,8 @@ expand_format (const char *fmt)
ss << rust_close_quote ();
break;
}
- default: {
+ default:
+ {
ss << "%" << *c;
}
}
@@ -104,8 +111,8 @@ expand_format (const char *fmt)
// calling function must need to have attribute gnu_printf as well, even
// though there is already an attribute declaration for it.
-static std::string
-expand_message (const char *fmt, va_list ap) RUST_ATTRIBUTE_GCC_DIAG (1, 0);
+static std::string expand_message (const char *fmt, va_list ap)
+ RUST_ATTRIBUTE_GCC_DIAG (1, 0);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
@@ -420,24 +427,24 @@ namespace Rust {
*/
// simple location
-static Error
-va_constructor (Error::Kind kind, location_t locus, const char *fmt,
- va_list args) RUST_ATTRIBUTE_GCC_DIAG (3, 0);
+static Error va_constructor (Error::Kind kind, location_t locus,
+ const char *fmt, va_list args)
+ RUST_ATTRIBUTE_GCC_DIAG (3, 0);
// simple location + error code
-static Error
-va_constructor (Error::Kind kind, location_t locus, const ErrorCode code,
- const char *fmt, va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0);
+static Error va_constructor (Error::Kind kind, location_t locus,
+ const ErrorCode code, const char *fmt,
+ va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0);
// rich location
-static Error
-va_constructor (Error::Kind kind, rich_location *r_locus, const char *fmt,
- va_list args) RUST_ATTRIBUTE_GCC_DIAG (3, 0);
+static Error va_constructor (Error::Kind kind, rich_location *r_locus,
+ const char *fmt, va_list args)
+ RUST_ATTRIBUTE_GCC_DIAG (3, 0);
// rich location + error code
-static Error
-va_constructor (Error::Kind kind, rich_location *r_locus, const ErrorCode code,
- const char *fmt, va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0);
+static Error va_constructor (Error::Kind kind, rich_location *r_locus,
+ const ErrorCode code, const char *fmt,
+ va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0);
// simple location
static Error
diff --git a/gcc/rust/rust-diagnostics.h b/gcc/rust/rust-diagnostics.h
index a13dc6a2..09d5e24 100644
--- a/gcc/rust/rust-diagnostics.h
+++ b/gcc/rust/rust-diagnostics.h
@@ -31,7 +31,7 @@
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
#define RUST_ATTRIBUTE_GCC_DIAG(m, n) \
__attribute__ ((__format__ (__gcc_tdiag__, m, n))) \
- __attribute__ ((__nonnull__ (m)))
+ __attribute__ ((__nonnull__ (m)))
#else
#define RUST_ATTRIBUTE_GCC_DIAG(m, n)
#endif
@@ -119,10 +119,8 @@ rust_error_at(rich_location *richloc, const ErrorCode, const char *fmt, ...)
// These interfaces provide a way for the front end to ask for
// the open/close quote characters it should use when formatting
// diagnostics (warnings, errors).
-extern const char *
-rust_open_quote ();
-extern const char *
-rust_close_quote ();
+extern const char *rust_open_quote ();
+extern const char *rust_close_quote ();
// These interfaces are used by utilities above to pass warnings and
// errors (once format specifiers have been expanded) to the back end,
@@ -185,7 +183,7 @@ struct Error
Error (Kind kind, location_t locus, std::string message)
: kind (kind), locus (locus), message (std::move (message))
{
- message.shrink_to_fit ();
+ this->message.shrink_to_fit ();
}
// simple location + error code
Error (Kind kind, location_t locus, ErrorCode code, std::string message)
@@ -193,13 +191,13 @@ struct Error
message (std::move (message))
{
is_errorcode = true;
- message.shrink_to_fit ();
+ this->message.shrink_to_fit ();
}
// rich location
Error (Kind kind, rich_location *richlocus, std::string message)
: kind (kind), richlocus (richlocus), message (std::move (message))
{
- message.shrink_to_fit ();
+ this->message.shrink_to_fit ();
}
// rich location + error code
Error (Kind kind, rich_location *richlocus, ErrorCode code,
@@ -208,7 +206,7 @@ struct Error
message (std::move (message))
{
is_errorcode = true;
- message.shrink_to_fit ();
+ this->message.shrink_to_fit ();
}
// simple location
Error (location_t locus, std::string message)
@@ -306,8 +304,7 @@ struct Error
#define rust_sorry_at(location, ...) sorry_at (location, __VA_ARGS__)
-void
-rust_debug_loc (const location_t location, const char *fmt,
- ...) ATTRIBUTE_PRINTF_2;
+void rust_debug_loc (const location_t location, const char *fmt,
+ ...) ATTRIBUTE_PRINTF_2;
#endif // !defined(RUST_DIAGNOSTICS_H)
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index e5319d3..398dea1 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -91,12 +91,6 @@ Bvariable::error_variable ()
// A helper function to create a GCC identifier from a C++ string.
-static inline tree
-get_identifier_from_string (const std::string &str)
-{
- return get_identifier_with_length (str.data (), str.length ());
-}
-
namespace Backend {
// Define the built-in functions that are exposed to GCCRust.
@@ -609,7 +603,7 @@ fill_in_fields (tree fill, const std::vector<typed_identifier> &fields,
tree *pp = &field_trees;
for (const auto &p : fields)
{
- tree name_tree = get_identifier_from_string (p.name);
+ tree name_tree = p.name.as_tree ();
tree type_tree = p.type;
if (error_operand_p (type_tree))
return error_mark_node;
@@ -675,7 +669,7 @@ fill_in_array (tree fill, tree element_type, tree length_tree)
// Return a named version of a type.
tree
-named_type (const std::string &name, tree type, location_t location)
+named_type (GGC::Ident name, tree type, location_t location)
{
if (error_operand_p (type))
return error_mark_node;
@@ -688,15 +682,14 @@ named_type (const std::string &name, tree type, location_t location)
|| TREE_CODE (type) == COMPLEX_TYPE
|| TREE_CODE (type) == BOOLEAN_TYPE))
{
- tree decl = build_decl (BUILTINS_LOCATION, TYPE_DECL,
- get_identifier_from_string (name), type);
+ tree decl
+ = build_decl (BUILTINS_LOCATION, TYPE_DECL, name.as_tree (), type);
TYPE_NAME (type) = decl;
return type;
}
tree copy = build_variant_type_copy (type);
- tree decl
- = build_decl (location, TYPE_DECL, get_identifier_from_string (name), copy);
+ tree decl = build_decl (location, TYPE_DECL, name.as_tree (), copy);
DECL_ORIGINAL_TYPE (decl) = type;
TYPE_NAME (copy) = decl;
return copy;
@@ -825,6 +818,12 @@ char_constant_expression (char c)
return build_int_cst (char_type_node, c);
}
+tree
+size_constant_expression (size_t val)
+{
+ return size_int (val);
+}
+
// Make a constant boolean expression.
tree
@@ -1505,6 +1504,34 @@ array_index_expression (tree array_tree, tree index_tree, location_t location)
return ret;
}
+// Return an expression representing SLICE[INDEX]
+
+tree
+slice_index_expression (tree slice_tree, tree index_tree, location_t location)
+{
+ if (error_operand_p (slice_tree) || error_operand_p (index_tree))
+ return error_mark_node;
+
+ // A slice is created in TyTyResolvecompile::create_slice_type_record
+ // For example:
+ // &[i32] is turned directly into a struct { i32* data, usize len };
+ // [i32] is also turned into struct { i32* data, usize len }
+
+ // it should have RS_DST_FLAG set to 1
+ rust_assert (RS_DST_FLAG_P (TREE_TYPE (slice_tree)));
+
+ tree data_field = struct_field_expression (slice_tree, 0, location);
+ tree data_field_deref = build_fold_indirect_ref_loc (location, data_field);
+
+ tree element_type = TREE_TYPE (data_field_deref);
+ tree data_pointer = TREE_OPERAND (data_field_deref, 0);
+ rust_assert (POINTER_TYPE_P (TREE_TYPE (data_pointer)));
+ tree data_offset_expr
+ = Rust::pointer_offset_expression (data_pointer, index_tree, location);
+
+ return build1_loc (location, INDIRECT_REF, element_type, data_offset_expr);
+}
+
// Create an expression for a call to FN_EXPR with FN_ARGS.
tree
call_expression (tree fn, const std::vector<tree> &fn_args, tree chain_expr,
@@ -1876,7 +1903,8 @@ non_zero_size_type (tree type)
}
return rust_non_zero_struct;
- case ARRAY_TYPE: {
+ case ARRAY_TYPE:
+ {
tree element_type = non_zero_size_type (TREE_TYPE (type));
return build_array_type_nelts (element_type, 1);
}
@@ -1923,9 +1951,9 @@ convert_tree (tree type_tree, tree expr_tree, location_t location)
// Make a global variable.
Bvariable *
-global_variable (const std::string &var_name, const std::string &asm_name,
- tree type_tree, bool is_external, bool is_hidden,
- bool in_unique_section, location_t location)
+global_variable (GGC::Ident var_name, GGC::Ident asm_name, tree type_tree,
+ bool is_external, bool is_hidden, bool in_unique_section,
+ location_t location)
{
if (error_operand_p (type_tree))
return Bvariable::error_variable ();
@@ -1935,8 +1963,7 @@ global_variable (const std::string &var_name, const std::string &asm_name,
if ((is_external || !is_hidden) && int_size_in_bytes (type_tree) == 0)
type_tree = non_zero_size_type (type_tree);
- tree decl = build_decl (location, VAR_DECL,
- get_identifier_from_string (var_name), type_tree);
+ tree decl = build_decl (location, VAR_DECL, var_name.as_tree (), type_tree);
if (is_external)
DECL_EXTERNAL (decl) = 1;
else
@@ -1944,11 +1971,11 @@ global_variable (const std::string &var_name, const std::string &asm_name,
if (!is_hidden)
{
TREE_PUBLIC (decl) = 1;
- SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
+ SET_DECL_ASSEMBLER_NAME (decl, asm_name.as_tree ());
}
else
{
- SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
+ SET_DECL_ASSEMBLER_NAME (decl, asm_name.as_tree ());
}
TREE_USED (decl) = 1;
@@ -1988,13 +2015,12 @@ global_variable_set_init (Bvariable *var, tree expr_tree)
// Make a local variable.
Bvariable *
-local_variable (tree function, const std::string &name, tree type_tree,
+local_variable (tree function, GGC::Ident name, tree type_tree,
Bvariable *decl_var, location_t location)
{
if (error_operand_p (type_tree))
return Bvariable::error_variable ();
- tree decl = build_decl (location, VAR_DECL, get_identifier_from_string (name),
- type_tree);
+ tree decl = build_decl (location, VAR_DECL, name.as_tree (), type_tree);
DECL_CONTEXT (decl) = function;
if (decl_var != NULL)
@@ -2009,13 +2035,12 @@ local_variable (tree function, const std::string &name, tree type_tree,
// Make a function parameter variable.
Bvariable *
-parameter_variable (tree function, const std::string &name, tree type_tree,
+parameter_variable (tree function, GGC::Ident name, tree type_tree,
location_t location)
{
if (error_operand_p (type_tree))
return Bvariable::error_variable ();
- tree decl = build_decl (location, PARM_DECL,
- get_identifier_from_string (name), type_tree);
+ tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree);
DECL_CONTEXT (decl) = function;
DECL_ARG_TYPE (decl) = type_tree;
@@ -2026,13 +2051,12 @@ parameter_variable (tree function, const std::string &name, tree type_tree,
// Make a static chain variable.
Bvariable *
-static_chain_variable (tree fndecl, const std::string &name, tree type_tree,
+static_chain_variable (tree fndecl, GGC::Ident name, tree type_tree,
location_t location)
{
if (error_operand_p (type_tree))
return Bvariable::error_variable ();
- tree decl = build_decl (location, PARM_DECL,
- get_identifier_from_string (name), type_tree);
+ tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree);
DECL_CONTEXT (decl) = fndecl;
DECL_ARG_TYPE (decl) = type_tree;
TREE_USED (decl) = 1;
@@ -2123,10 +2147,10 @@ temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree init_tree,
// Make a label.
tree
-label (tree func_tree, const std::string &name, location_t location)
+label (tree func_tree, tl::optional<GGC::Ident> name, location_t location)
{
tree decl;
- if (name.empty ())
+ if (!name.has_value ())
{
if (DECL_STRUCT_FUNCTION (func_tree) == NULL)
push_struct_function (func_tree);
@@ -2139,7 +2163,7 @@ label (tree func_tree, const std::string &name, location_t location)
}
else
{
- tree id = get_identifier_from_string (name);
+ tree id = name->as_tree ();
decl = build_decl (location, LABEL_DECL, id, void_type_node);
DECL_CONTEXT (decl) = func_tree;
}
@@ -2178,7 +2202,7 @@ label_address (tree label, location_t location)
// Declare or define a new function.
tree
-function (tree functype, const std::string &name, const std::string &asm_name,
+function (tree functype, GGC::Ident name, tl::optional<GGC::Ident> asm_name,
unsigned int flags, location_t location)
{
if (error_operand_p (functype))
@@ -2186,13 +2210,13 @@ function (tree functype, const std::string &name, const std::string &asm_name,
gcc_assert (FUNCTION_POINTER_TYPE_P (functype));
functype = TREE_TYPE (functype);
- tree id = get_identifier_from_string (name);
+ tree id = name.as_tree ();
if (error_operand_p (id))
return error_mark_node;
tree decl = build_decl (location, FUNCTION_DECL, id, functype);
- if (!asm_name.empty ())
- SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
+ if (asm_name.has_value ())
+ SET_DECL_ASSEMBLER_NAME (decl, asm_name->as_tree ());
if ((flags & function_is_declaration) != 0)
DECL_EXTERNAL (decl) = 1;
@@ -2235,7 +2259,7 @@ function_defer_statement (tree function, tree undefer_tree, tree defer_tree,
push_cfun (DECL_STRUCT_FUNCTION (function));
tree stmt_list = NULL;
- tree label = Backend::label (function, "", location);
+ tree label = Backend::label (function, tl::nullopt, location);
tree label_def = label_definition_statement (label);
append_to_statement_list (label_def, &stmt_list);
@@ -2342,4 +2366,30 @@ write_global_definitions (const std::vector<tree> &type_decls,
delete[] defs;
}
+tree
+lookup_field (const_tree type, tree component)
+{
+ tree field;
+
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ if (DECL_NAME (field) == NULL_TREE
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)))
+ {
+ tree anon = lookup_field (TREE_TYPE (field), component);
+
+ if (anon)
+ return tree_cons (NULL_TREE, field, anon);
+ }
+
+ if (DECL_NAME (field) == component)
+ break;
+ }
+
+ if (field == NULL_TREE)
+ return NULL_TREE;
+
+ return tree_cons (NULL_TREE, field, NULL_TREE);
+}
+
} // namespace Backend
diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc
index f3a155d..93ce041 100644
--- a/gcc/rust/rust-lang.cc
+++ b/gcc/rust/rust-lang.cc
@@ -51,10 +51,10 @@
// FIXME: test saving intellisense
#include "options.h"
-// version check to stop compiling if c++ isn't c++11 or higher
-#if __cplusplus < 201103
+// version check to stop compiling if c++ isn't c++14 or higher
+#if __cplusplus < 201402
#error \
- "GCC Rust frontend requires C++11 or higher. You can compile the g++ frontend first and then compile the Rust frontend using that."
+ "GCC Rust frontend requires C++14 or higher. You can compile the g++ frontend first and then compile the Rust frontend using that."
#endif
// TODO: is this best way to do it? Is it allowed? (should be)
@@ -373,7 +373,13 @@ rust_localize_identifier (const char *ident)
return identifier_to_locale (ident);
}
-extern const attribute_spec grs_langhook_common_attribute_table[];
+extern const struct scoped_attribute_specs grs_langhook_gnu_attribute_table;
+extern const struct scoped_attribute_specs grs_langhook_common_attribute_table;
+
+const scoped_attribute_specs *const grs_langhook_attribute_table[] = {
+ &grs_langhook_gnu_attribute_table,
+ &grs_langhook_common_attribute_table,
+};
/* The language hooks data structure. This is the main interface between the GCC
* front-end and the GCC middle-end/back-end. A list of language hooks could be
@@ -394,8 +400,7 @@ extern const attribute_spec grs_langhook_common_attribute_table[];
#undef LANG_HOOKS_WRITE_GLOBALS
#undef LANG_HOOKS_GIMPLIFY_EXPR
#undef LANG_HOOKS_EH_PERSONALITY
-
-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+#undef LANG_HOOKS_ATTRIBUTE_TABLE
#define LANG_HOOKS_NAME "GNU Rust"
#define LANG_HOOKS_INIT grs_langhook_init
@@ -417,7 +422,7 @@ extern const attribute_spec grs_langhook_common_attribute_table[];
#define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr
#define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE grs_langhook_common_attribute_table
+#define LANG_HOOKS_ATTRIBUTE_TABLE grs_langhook_attribute_table
#if CHECKING_P
diff --git a/gcc/rust/rust-object-export.h b/gcc/rust/rust-object-export.h
index fe055c3..784fef3 100644
--- a/gcc/rust/rust-object-export.h
+++ b/gcc/rust/rust-object-export.h
@@ -21,13 +21,10 @@
#include "rust-system.h"
-extern unsigned int
-rust_field_alignment (tree t);
-
-extern const char *
-rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen,
- int *perr);
-extern void
-rust_write_export_data (const char *bytes, unsigned int size);
+extern unsigned int rust_field_alignment (tree t);
+
+extern const char *rust_read_export_data (int fd, off_t offset, char **pbuf,
+ size_t *plen, int *perr);
+extern void rust_write_export_data (const char *bytes, unsigned int size);
#endif // RUST_OBJECT_EXPORT_H
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 48acbf34..17f9c06 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -20,7 +20,9 @@
#include "rust-collect-lang-items.h"
#include "rust-desugar-for-loops.h"
#include "rust-desugar-question-mark.h"
+#include "rust-desugar-apit.h"
#include "rust-diagnostics.h"
+#include "rust-expression-yeast.h"
#include "rust-hir-pattern-analysis.h"
#include "rust-immutable-name-resolution-context.h"
#include "rust-unsafe-checker.h"
@@ -61,11 +63,9 @@
#include "tm.h"
#include "rust-target.h"
-extern bool
-saw_errors (void);
+extern bool saw_errors (void);
-extern Linemap *
-rust_get_linemap ();
+extern Linemap *rust_get_linemap ();
namespace Rust {
@@ -150,9 +150,9 @@ validate_crate_name (const std::string &crate_name, Error &error)
{
if (!(is_alphabetic (c.value) || is_numeric (c.value) || c.value == '_'))
{
- error = Error (UNDEF_LOCATION,
- "invalid character %qs in crate name: %qs",
- c.as_string ().c_str (), crate_name.c_str ());
+ error
+ = Error (UNDEF_LOCATION, "invalid character %qs in crate name: %qs",
+ c.as_string ().c_str (), crate_name.c_str ());
return false;
}
}
@@ -203,14 +203,16 @@ Session::handle_option (
switch (code)
{
case OPT_I:
- case OPT_L: {
+ case OPT_L:
+ {
// TODO: add search path
const std::string p = std::string (arg);
add_search_path (p);
}
break;
- case OPT_frust_extern_: {
+ case OPT_frust_extern_:
+ {
std::string input (arg);
ret = handle_extern_option (input);
}
@@ -251,7 +253,8 @@ Session::handle_option (
Compile::Mangler::set_mangling (flag_rust_mangling);
break;
- case OPT_frust_cfg_: {
+ case OPT_frust_cfg_:
+ {
auto string_arg = std::string (arg);
ret = handle_cfg_option (string_arg);
break;
@@ -617,9 +620,6 @@ Session::compile_crate (const char *filename)
expansion (parsed_crate, name_resolution_ctx);
- AST::DesugarForLoops ().go (parsed_crate);
- AST::DesugarQuestionMark ().go (parsed_crate);
-
rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m");
if (options.dump_option_enabled (CompileOptions::EXPANSION_DUMP))
{
@@ -682,6 +682,7 @@ Session::compile_crate (const char *filename)
Resolver2_0::ImmutableNameResolutionContext::init (name_resolution_ctx);
// type resolve
+ Compile::Context *ctx = Compile::Context::get ();
Resolver::TypeResolution::Resolve (hir);
Resolver::TypeCheckContext::get ()->get_variance_analysis_ctx ().solve ();
@@ -729,16 +730,15 @@ Session::compile_crate (const char *filename)
return;
// do compile to gcc generic
- Compile::Context ctx;
- Compile::CompileCrate::Compile (hir, &ctx);
+ Compile::CompileCrate::Compile (hir, ctx);
// we can't do static analysis if there are errors to worry about
if (!saw_errors ())
{
// lints
Analysis::ScanDeadcode::Scan (hir);
- Analysis::UnusedVariables::Lint (ctx);
- Analysis::ReadonlyCheck::Lint (ctx);
+ Analysis::UnusedVariables::Lint (*ctx);
+ Analysis::ReadonlyCheck::Lint (*ctx);
// metadata
bool specified_emit_metadata
@@ -759,7 +759,7 @@ Session::compile_crate (const char *filename)
}
// pass to GCC middle-end
- ctx.write_to_backend ();
+ ctx->write_to_backend ();
}
void
@@ -983,6 +983,20 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx)
rust_error_at (range, "reached recursion limit");
}
+ // handle AST desugaring
+ if (!saw_errors ())
+ {
+ AST::ExpressionYeast ().go (crate);
+
+ AST::DesugarApit ().go (crate);
+
+ // HACK: we may need a final TopLevel pass
+ // however, this should not count towards the recursion limit
+ // and we don't need a full Early pass
+ if (flag_name_resolution_2_0)
+ Resolver2_0::TopLevel (ctx).go (crate);
+ }
+
// error reporting - check unused macros, get missing fragment specifiers
// build test harness
@@ -1108,8 +1122,7 @@ Session::load_extern_crate (const std::string &crate_name, location_t locus)
if (stream == NULL // No stream and
&& proc_macros.empty ()) // no proc macros
{
- rust_error_at (locus, "failed to locate crate %qs",
- import_name.c_str ());
+ rust_error_at (locus, "failed to locate crate %qs", import_name.c_str ());
return UNKNOWN_NODEID;
}
@@ -1177,16 +1190,13 @@ Session::load_extern_crate (const std::string &crate_name, location_t locus)
mappings.insert_bang_proc_macros (crate_num, bang_macros);
mappings.insert_derive_proc_macros (crate_num, derive_macros);
- // name resolve it
- Resolver::NameResolution::Resolve (parsed_crate);
-
- // perform hir lowering
- std::unique_ptr<HIR::Crate> lowered
- = HIR::ASTLowering::Resolve (parsed_crate);
- HIR::Crate &hir = mappings.insert_hir_crate (std::move (lowered));
-
- // perform type resolution
- Resolver::TypeResolution::Resolve (hir);
+ // if flag_name_resolution_2_0 is enabled
+ // then we perform resolution later
+ if (!flag_name_resolution_2_0)
+ {
+ // name resolve it
+ Resolver::NameResolution::Resolve (parsed_crate);
+ }
// always restore the crate_num
mappings.set_current_crate (saved_crate_num);
diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h
index 83ba121..9af103c 100644
--- a/gcc/rust/rust-session-manager.h
+++ b/gcc/rust/rust-session-manager.h
@@ -441,8 +441,7 @@ private:
#if CHECKING_P
namespace selftest {
-extern void
-rust_crate_name_validation_test (void);
+extern void rust_crate_name_validation_test (void);
}
#endif // CHECKING_P
diff --git a/gcc/rust/rust-system.h b/gcc/rust/rust-system.h
index 986428b..a455123 100644
--- a/gcc/rust/rust-system.h
+++ b/gcc/rust/rust-system.h
@@ -88,10 +88,8 @@ constexpr static const char *file_separator = "/";
*/
#define rust_unreachable() (fancy_abort (__FILE__, __LINE__, __FUNCTION__))
-extern void
-rust_preserve_from_gc (tree t);
+extern void rust_preserve_from_gc (tree t);
-extern const char *
-rust_localize_identifier (const char *ident);
+extern const char *rust_localize_identifier (const char *ident);
#endif // !defined(RUST_SYSTEM_H)
diff --git a/gcc/rust/rust-target.h b/gcc/rust/rust-target.h
index dbc2baf..e61ea51 100644
--- a/gcc/rust/rust-target.h
+++ b/gcc/rust/rust-target.h
@@ -26,8 +26,7 @@
#include "rust-target.def"
/* Used by target to add target-related info. */
-extern void
-rust_add_target_info (const char *, const char *);
+extern void rust_add_target_info (const char *, const char *);
/* Each target can provide their own. */
extern struct gcc_targetrustm targetrustm;
diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc
index 6aa20a8..10a59bd 100644
--- a/gcc/rust/typecheck/rust-autoderef.cc
+++ b/gcc/rust/typecheck/rust-autoderef.cc
@@ -26,8 +26,7 @@
namespace Rust {
namespace Resolver {
-static bool
-resolve_operator_overload_fn (
+static bool resolve_operator_overload_fn (
LangItem::Kind lang_item_type, TyTy::BaseType *ty, TyTy::FnType **resolved_fn,
Adjustment::AdjustmentType *requires_ref_adjustment);
@@ -248,7 +247,6 @@ resolve_operator_overload_fn (
const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (lhs);
auto s = fn->get_self_type ()->get_root ();
- rust_assert (s->can_eq (adt, false));
rust_assert (s->get_kind () == TyTy::TypeKind::ADT);
const TyTy::ADTType *self_adt
= static_cast<const TyTy::ADTType *> (s);
diff --git a/gcc/rust/typecheck/rust-casts.cc b/gcc/rust/typecheck/rust-casts.cc
index 90bdef1..f06d9ed 100644
--- a/gcc/rust/typecheck/rust-casts.cc
+++ b/gcc/rust/typecheck/rust-casts.cc
@@ -17,6 +17,7 @@
// <http://www.gnu.org/licenses/>.
#include "rust-casts.h"
+#include "rust-tyty-util.h"
namespace Rust {
namespace Resolver {
@@ -28,15 +29,20 @@ TypeCastRules::TypeCastRules (location_t locus, TyTy::TyWithLocation from,
TypeCoercionRules::CoercionResult
TypeCastRules::resolve (location_t locus, TyTy::TyWithLocation from,
- TyTy::TyWithLocation to)
+ TyTy::TyWithLocation to, bool emit_error)
{
TypeCastRules cast_rules (locus, from, to);
- return cast_rules.check ();
+ return cast_rules.check (emit_error);
}
TypeCoercionRules::CoercionResult
-TypeCastRules::check ()
+TypeCastRules::check (bool emit_error)
{
+ // try the simple cast rules
+ auto simple_cast = cast_rules ();
+ if (!simple_cast.is_error ())
+ return simple_cast;
+
// https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/cast.rs#L565-L582
auto possible_coercion
= TypeCoercionRules::TryCoerce (from.get_ty (), to.get_ty (), locus,
@@ -51,13 +57,9 @@ TypeCastRules::check ()
true /*is_cast_site*/);
}
- // try the simple cast rules
- auto simple_cast = cast_rules ();
- if (!simple_cast.is_error ())
- return simple_cast;
+ if (emit_error)
+ TypeCastRules::emit_cast_error (locus, from, to);
- // failed to cast
- emit_cast_error ();
return TypeCoercionRules::CoercionResult::get_error ();
}
@@ -73,7 +75,8 @@ TypeCastRules::cast_rules ()
to.get_ty ()->debug_str ().c_str ());
switch (from_type->get_kind ())
{
- case TyTy::TypeKind::INFER: {
+ case TyTy::TypeKind::INFER:
+ {
TyTy::InferType *from_infer
= static_cast<TyTy::InferType *> (from_type);
switch (from_infer->get_infer_kind ())
@@ -85,7 +88,8 @@ TypeCastRules::cast_rules ()
case TyTy::InferType::InferTypeKind::INTEGRAL:
switch (to.get_ty ()->get_kind ())
{
- case TyTy::TypeKind::CHAR: {
+ case TyTy::TypeKind::CHAR:
+ {
// only u8 and char
bool was_uint
= from.get_ty ()->get_kind () == TyTy::TypeKind::UINT;
@@ -108,7 +112,8 @@ TypeCastRules::cast_rules ()
return TypeCoercionRules::CoercionResult{
{}, to.get_ty ()->clone ()};
- case TyTy::TypeKind::INFER: {
+ case TyTy::TypeKind::INFER:
+ {
TyTy::InferType *to_infer
= static_cast<TyTy::InferType *> (to.get_ty ());
@@ -140,7 +145,8 @@ TypeCastRules::cast_rules ()
return TypeCoercionRules::CoercionResult{
{}, to.get_ty ()->clone ()};
- case TyTy::TypeKind::INFER: {
+ case TyTy::TypeKind::INFER:
+ {
TyTy::InferType *to_infer
= static_cast<TyTy::InferType *> (to.get_ty ());
@@ -187,7 +193,8 @@ TypeCastRules::cast_rules ()
case TyTy::TypeKind::INT:
switch (to.get_ty ()->get_kind ())
{
- case TyTy::TypeKind::CHAR: {
+ case TyTy::TypeKind::CHAR:
+ {
// only u8 and char
bool was_uint = from.get_ty ()->get_kind () == TyTy::TypeKind::UINT;
bool was_u8 = was_uint
@@ -200,7 +207,8 @@ TypeCastRules::cast_rules ()
}
break;
- case TyTy::TypeKind::FLOAT: {
+ case TyTy::TypeKind::FLOAT:
+ {
// can only do this for number types not char
bool from_char
= from.get_ty ()->get_kind () == TyTy::TypeKind::CHAR;
@@ -210,7 +218,8 @@ TypeCastRules::cast_rules ()
}
break;
- case TyTy::TypeKind::POINTER: {
+ case TyTy::TypeKind::POINTER:
+ {
// char can't be casted as a ptr
bool from_char
= from.get_ty ()->get_kind () == TyTy::TypeKind::CHAR;
@@ -244,7 +253,8 @@ TypeCastRules::cast_rules ()
case TyTy::TypeKind::FLOAT:
return TypeCoercionRules::CoercionResult{{}, to.get_ty ()->clone ()};
- case TyTy::TypeKind::INFER: {
+ case TyTy::TypeKind::INFER:
+ {
TyTy::InferType *to_infer
= static_cast<TyTy::InferType *> (to.get_ty ());
@@ -273,7 +283,8 @@ TypeCastRules::cast_rules ()
case TyTy::TypeKind::USIZE:
case TyTy::TypeKind::ISIZE:
case TyTy::TypeKind::UINT:
- case TyTy::TypeKind::INT: {
+ case TyTy::TypeKind::INT:
+ {
// refs should not cast to numeric type
bool from_ptr
= from.get_ty ()->get_kind () == TyTy::TypeKind::POINTER;
@@ -320,7 +331,27 @@ TypeCastRules::check_ptr_ptr_cast ()
}
else if (from_is_ref && to_is_ref)
{
- // mutability must be coercedable
+ const auto &from_ref = *from.get_ty ()->as<TyTy::ReferenceType> ();
+ const auto &to_ref = *to.get_ty ()->as<TyTy::ReferenceType> ();
+
+ if (from_ref.is_dyn_object () != to_ref.is_dyn_object ())
+ {
+ // this needs to be handled by coercion logic
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+
+ // are the underlying types safely simple castable?
+ const auto to_underly = to_ref.get_base ();
+ const auto from_underly = from_ref.get_base ();
+ auto res = resolve (locus, TyTy::TyWithLocation (from_underly),
+ TyTy::TyWithLocation (to_underly), false);
+ if (res.is_error ())
+ {
+ // this needs to be handled by coercion logic
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+
+ // mutability must be coerceable
TyTy::ReferenceType &f
= static_cast<TyTy::ReferenceType &> (*from.get_ty ());
TyTy::ReferenceType &t
@@ -337,7 +368,8 @@ TypeCastRules::check_ptr_ptr_cast ()
}
void
-TypeCastRules::emit_cast_error () const
+TypeCastRules::emit_cast_error (location_t locus, TyTy::TyWithLocation from,
+ TyTy::TyWithLocation to)
{
rich_location r (line_table, locus);
r.add_range (from.get_locus ());
diff --git a/gcc/rust/typecheck/rust-casts.h b/gcc/rust/typecheck/rust-casts.h
index 0d6ed68..10bb006 100644
--- a/gcc/rust/typecheck/rust-casts.h
+++ b/gcc/rust/typecheck/rust-casts.h
@@ -30,15 +30,17 @@ class TypeCastRules
public:
static TypeCoercionRules::CoercionResult resolve (location_t locus,
TyTy::TyWithLocation from,
- TyTy::TyWithLocation to);
+ TyTy::TyWithLocation to,
+ bool emit_error = true);
+
+ static void emit_cast_error (location_t locus, TyTy::TyWithLocation from,
+ TyTy::TyWithLocation to);
protected:
- TypeCoercionRules::CoercionResult check ();
+ TypeCoercionRules::CoercionResult check (bool emit_error);
TypeCoercionRules::CoercionResult cast_rules ();
TypeCoercionRules::CoercionResult check_ptr_ptr_cast ();
- void emit_cast_error () const;
-
protected:
TypeCastRules (location_t locus, TyTy::TyWithLocation from,
TyTy::TyWithLocation to);
diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc
index 5905992..fd12839 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -125,13 +125,15 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
// pointers
switch (expected->get_kind ())
{
- case TyTy::TypeKind::POINTER: {
+ case TyTy::TypeKind::POINTER:
+ {
TyTy::PointerType *ptr = static_cast<TyTy::PointerType *> (expected);
try_result = coerce_unsafe_ptr (receiver, ptr, ptr->mutability ());
return !try_result.is_error ();
}
- case TyTy::TypeKind::REF: {
+ case TyTy::TypeKind::REF:
+ {
TyTy::ReferenceType *ptr
= static_cast<TyTy::ReferenceType *> (expected);
try_result
@@ -147,7 +149,8 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
// https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L210
switch (receiver->get_kind ())
{
- default: {
+ default:
+ {
rust_debug (
"do_coercion default unify and infer expected: %s receiver %s",
receiver->debug_str ().c_str (), expected->debug_str ().c_str ());
@@ -182,7 +185,8 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver,
TyTy::BaseType *element = nullptr;
switch (receiver->get_kind ())
{
- case TyTy::TypeKind::REF: {
+ case TyTy::TypeKind::REF:
+ {
TyTy::ReferenceType *ref
= static_cast<TyTy::ReferenceType *> (receiver);
from_mutbl = ref->mutability ();
@@ -190,16 +194,19 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver,
}
break;
- case TyTy::TypeKind::POINTER: {
+ case TyTy::TypeKind::POINTER:
+ {
TyTy::PointerType *ref = static_cast<TyTy::PointerType *> (receiver);
from_mutbl = ref->mutability ();
element = ref->get_base ();
}
break;
- default: {
- // FIXME this can probably turn into a unify_and
- if (receiver->can_eq (expected, false))
+ default:
+ {
+ if (types_compatable (TyTy::TyWithLocation (receiver),
+ TyTy::TyWithLocation (expected), UNKNOWN_LOCATION,
+ false))
return CoercionResult{{}, expected->clone ()};
return CoercionResult::get_error ();
@@ -264,17 +271,16 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver,
Mutability from_mutbl = Mutability::Imm;
switch (receiver->get_kind ())
{
- case TyTy::TypeKind::REF: {
+ case TyTy::TypeKind::REF:
+ {
TyTy::ReferenceType *from
= static_cast<TyTy::ReferenceType *> (receiver);
from_mutbl = from->mutability ();
}
break;
- default: {
- // FIXME
- // we might be able to replace this with a can_eq because we default
- // back to a final unity anyway
+ default:
+ {
rust_debug ("coerce_borrowed_pointer -- unify");
TyTy::BaseType *result
= unify_site_and (receiver->get_ref (),
@@ -393,7 +399,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
if (expect_dyn && need_unsize)
{
- bool bounds_compatible = b->bounds_compatible (*a, locus, true);
+ bool bounds_compatible = b->bounds_compatible (*a, locus, false);
if (!bounds_compatible)
{
unsafe_error = true;
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index c1165e9..7b7944c 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -102,26 +102,16 @@ MethodResolver::try_hook (const TyTy::BaseType &r)
}
}
-bool
-MethodResolver::select (TyTy::BaseType &receiver)
+std::vector<MethodResolver::impl_item_candidate>
+MethodResolver::assemble_inherent_impl_candidates (
+ const TyTy::BaseType &receiver)
{
- rust_debug ("MethodResolver::select reciever=[%s] path=[%s]",
- receiver.debug_str ().c_str (),
- segment_name.as_string ().c_str ());
-
- struct impl_item_candidate
- {
- HIR::Function *item;
- HIR::ImplBlock *impl_block;
- TyTy::FnType *ty;
- };
-
+ std::vector<impl_item_candidate> inherent_impl_fns;
const TyTy::BaseType *raw = receiver.destructure ();
bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER;
bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF;
- // assemble inherent impl items
- std::vector<impl_item_candidate> inherent_impl_fns;
+ // Assemble inherent impl items (non-trait impl blocks)
mappings.iterate_impl_items (
[&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
bool is_trait_impl = impl->has_trait_ref ();
@@ -190,16 +180,19 @@ MethodResolver::select (TyTy::BaseType &receiver)
return true;
});
- struct trait_item_candidate
- {
- const HIR::TraitItemFunc *item;
- const HIR::Trait *trait;
- TyTy::FnType *ty;
- const TraitReference *reference;
- const TraitItemReference *item_ref;
- };
+ return inherent_impl_fns;
+}
+
+void
+MethodResolver::assemble_trait_impl_candidates (
+ const TyTy::BaseType &receiver,
+ std::vector<impl_item_candidate> &impl_candidates,
+ std::vector<trait_item_candidate> &trait_candidates)
+{
+ const TyTy::BaseType *raw = receiver.destructure ();
+ bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER;
+ bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF;
- std::vector<trait_item_candidate> trait_fns;
mappings.iterate_impl_blocks ([&] (HirId id,
HIR::ImplBlock *impl) mutable -> bool {
bool is_trait_impl = impl->has_trait_ref ();
@@ -266,7 +259,7 @@ MethodResolver::select (TyTy::BaseType &receiver)
continue;
}
- inherent_impl_fns.push_back ({func, impl, fnty});
+ impl_candidates.push_back ({func, impl, fnty});
return true;
}
@@ -293,26 +286,15 @@ MethodResolver::select (TyTy::BaseType &receiver)
TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
trait_item_candidate candidate{func, trait, fnty, trait_ref, item_ref};
- trait_fns.push_back (candidate);
+ trait_candidates.push_back (candidate);
return true;
});
+}
- // lookup specified bounds for an associated item
- struct precdicate_candidate
- {
- TyTy::TypeBoundPredicateItem lookup;
- TyTy::FnType *fntype;
- };
-
- // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L580-L694
-
- rust_debug ("inherent_impl_fns found {%lu}, trait_fns found {%lu}, "
- "predicate_items found {%lu}",
- (unsigned long) inherent_impl_fns.size (),
- (unsigned long) trait_fns.size (),
- (unsigned long) predicate_items.size ());
-
+bool
+MethodResolver::try_select_predicate_candidates (TyTy::BaseType &receiver)
+{
bool found_possible_candidate = false;
for (const auto &predicate : predicate_items)
{
@@ -346,60 +328,33 @@ MethodResolver::select (TyTy::BaseType &receiver)
found_possible_candidate = true;
}
}
- if (found_possible_candidate)
- {
- return true;
- }
+ return found_possible_candidate;
+}
- for (auto &impl_item : inherent_impl_fns)
+bool
+MethodResolver::try_select_inherent_impl_candidates (
+ TyTy::BaseType &receiver, const std::vector<impl_item_candidate> &candidates,
+ bool trait_impl_blocks_only)
+{
+ bool found_possible_candidate = false;
+ for (auto &impl_item : candidates)
{
bool is_trait_impl_block = impl_item.impl_block->has_trait_ref ();
- if (is_trait_impl_block)
+ if (trait_impl_blocks_only && !is_trait_impl_block)
continue;
-
- TyTy::FnType *fn = impl_item.ty;
- rust_assert (fn->is_method ());
-
- TyTy::BaseType *fn_self = fn->get_self_type ();
- rust_debug ("dot-operator impl_item fn_self={%s} can_eq receiver={%s}",
- fn_self->debug_str ().c_str (),
- receiver.debug_str ().c_str ());
-
- auto res
- = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
- false /*allow-autoderef*/);
- bool ok = !res.is_error ();
- if (ok)
- {
- std::vector<Adjustment> adjs = append_adjustments (res.adjustments);
- PathProbeCandidate::ImplItemCandidate c{impl_item.item,
- impl_item.impl_block};
- auto try_result = MethodCandidate{
- PathProbeCandidate (PathProbeCandidate::CandidateType::IMPL_FUNC,
- fn, impl_item.item->get_locus (), c),
- adjs};
- result.insert (std::move (try_result));
- found_possible_candidate = true;
- }
- }
- if (found_possible_candidate)
- {
- return true;
- }
-
- for (auto &impl_item : inherent_impl_fns)
- {
- bool is_trait_impl_block = impl_item.impl_block->has_trait_ref ();
- if (!is_trait_impl_block)
+ if (!trait_impl_blocks_only && is_trait_impl_block)
continue;
TyTy::FnType *fn = impl_item.ty;
rust_assert (fn->is_method ());
TyTy::BaseType *fn_self = fn->get_self_type ();
- rust_debug (
- "dot-operator trait_impl_item fn_self={%s} can_eq receiver={%s}",
- fn_self->debug_str ().c_str (), receiver.debug_str ().c_str ());
+
+ const char *debug_prefix
+ = trait_impl_blocks_only ? "trait_impl_item" : "impl_item";
+ rust_debug ("dot-operator %s fn_self={%s} can_eq receiver={%s}",
+ debug_prefix, fn_self->debug_str ().c_str (),
+ receiver.debug_str ().c_str ());
auto res
= TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
@@ -418,12 +373,15 @@ MethodResolver::select (TyTy::BaseType &receiver)
found_possible_candidate = true;
}
}
- if (found_possible_candidate)
- {
- return true;
- }
+ return found_possible_candidate;
+}
- for (auto trait_item : trait_fns)
+bool
+MethodResolver::try_select_trait_impl_candidates (
+ TyTy::BaseType &receiver, const std::vector<trait_item_candidate> &candidates)
+{
+ bool found_possible_candidate = false;
+ for (auto trait_item : candidates)
{
TyTy::FnType *fn = trait_item.ty;
rust_assert (fn->is_method ());
@@ -451,10 +409,53 @@ MethodResolver::select (TyTy::BaseType &receiver)
found_possible_candidate = true;
}
}
-
return found_possible_candidate;
}
+bool
+MethodResolver::select (TyTy::BaseType &receiver)
+{
+ rust_debug ("MethodResolver::select reciever=[%s] path=[%s]",
+ receiver.debug_str ().c_str (),
+ segment_name.as_string ().c_str ());
+
+ // Assemble candidates
+ std::vector<impl_item_candidate> inherent_impl_fns
+ = assemble_inherent_impl_candidates (receiver);
+ std::vector<impl_item_candidate> trait_impl_fns;
+ std::vector<trait_item_candidate> trait_fns;
+ assemble_trait_impl_candidates (receiver, trait_impl_fns, trait_fns);
+
+ // Combine inherent and trait impl functions
+ inherent_impl_fns.insert (inherent_impl_fns.end (), trait_impl_fns.begin (),
+ trait_impl_fns.end ());
+
+ // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L580-L694
+
+ rust_debug ("inherent_impl_fns found {%lu}, trait_fns found {%lu}, "
+ "predicate_items found {%lu}",
+ (unsigned long) inherent_impl_fns.size (),
+ (unsigned long) trait_fns.size (),
+ (unsigned long) predicate_items.size ());
+
+ // Try selection in the priority order defined by Rust's method resolution:
+
+ // 1. Try predicate candidates first (highest priority)
+ if (try_select_predicate_candidates (receiver))
+ return true;
+
+ // 2. Try inherent impl functions (non-trait impl blocks)
+ if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns, false))
+ return true;
+
+ // 3. Try inherent impl functions from trait impl blocks
+ if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns, true))
+ return true;
+
+ // 4. Try trait functions (lowest priority)
+ return try_select_trait_impl_candidates (receiver, trait_fns);
+}
+
std::vector<MethodResolver::predicate_candidate>
MethodResolver::get_predicate_items (
const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h
index ab95a5a..cc40472 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -65,6 +65,22 @@ public:
const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
+ struct impl_item_candidate
+ {
+ HIR::Function *item;
+ HIR::ImplBlock *impl_block;
+ TyTy::FnType *ty;
+ };
+
+ struct trait_item_candidate
+ {
+ const HIR::TraitItemFunc *item;
+ const HIR::Trait *trait;
+ TyTy::FnType *ty;
+ const TraitReference *reference;
+ const TraitItemReference *item_ref;
+ };
+
protected:
MethodResolver (bool autoderef_flag,
const HIR::PathIdentSegment &segment_name);
@@ -77,6 +93,25 @@ private:
std::vector<Adjustment>
append_adjustments (const std::vector<Adjustment> &adjustments) const;
+ std::vector<impl_item_candidate>
+ assemble_inherent_impl_candidates (const TyTy::BaseType &receiver);
+
+ void assemble_trait_impl_candidates (
+ const TyTy::BaseType &receiver,
+ std::vector<impl_item_candidate> &impl_candidates,
+ std::vector<trait_item_candidate> &trait_candidates);
+
+ bool try_select_predicate_candidates (TyTy::BaseType &receiver);
+
+ bool try_select_inherent_impl_candidates (
+ TyTy::BaseType &receiver,
+ const std::vector<impl_item_candidate> &candidates,
+ bool trait_impl_blocks_only);
+
+ bool try_select_trait_impl_candidates (
+ TyTy::BaseType &receiver,
+ const std::vector<trait_item_candidate> &candidates);
+
private:
// search
const HIR::PathIdentSegment &segment_name;
diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
index 5537b14..a66396f 100644
--- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
+++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
@@ -79,27 +79,29 @@ public:
if (query == candidate)
continue;
- if (query->can_eq (candidate, false))
+ if (!types_compatable (TyTy::TyWithLocation (query),
+ TyTy::TyWithLocation (candidate),
+ UNKNOWN_LOCATION, false))
+ continue;
+
+ // we might be in the case that we have:
+ //
+ // *const T vs *const [T]
+ //
+ // so lets use an equality check when the
+ // candidates are both generic to be sure we dont emit a false
+ // positive
+
+ bool a = query->is_concrete ();
+ bool b = candidate->is_concrete ();
+ bool both_generic = !a && !b;
+ if (both_generic)
{
- // we might be in the case that we have:
- //
- // *const T vs *const [T]
- //
- // so lets use an equality check when the
- // candidates are both generic to be sure we dont emit a false
- // positive
-
- bool a = query->is_concrete ();
- bool b = candidate->is_concrete ();
- bool both_generic = !a && !b;
- if (both_generic)
- {
- if (!query->is_equal (*candidate))
- continue;
- }
-
- possible_collision (it->second, iy->second);
+ if (!query->is_equal (*candidate))
+ continue;
}
+
+ possible_collision (it->second, iy->second);
}
}
}
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc
index 32e2399..c02702f 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.cc
+++ b/gcc/rust/typecheck/rust-hir-path-probe.cc
@@ -137,7 +137,7 @@ PathProbeCandidate::operator< (const PathProbeCandidate &c) const
// PathProbeType
-PathProbeType::PathProbeType (const TyTy::BaseType *receiver,
+PathProbeType::PathProbeType (TyTy::BaseType *receiver,
const HIR::PathIdentSegment &query,
DefId specific_trait_id)
: TypeCheckBase (), receiver (receiver), search (query),
@@ -145,7 +145,7 @@ PathProbeType::PathProbeType (const TyTy::BaseType *receiver,
{}
std::set<PathProbeCandidate>
-PathProbeType::Probe (const TyTy::BaseType *receiver,
+PathProbeType::Probe (TyTy::BaseType *receiver,
const HIR::PathIdentSegment &segment_name,
bool probe_impls, bool probe_bounds,
bool ignore_mandatory_trait_items,
@@ -443,7 +443,7 @@ PathProbeType::is_receiver_generic () const
// PathProbImplTrait
-PathProbeImplTrait::PathProbeImplTrait (const TyTy::BaseType *receiver,
+PathProbeImplTrait::PathProbeImplTrait (TyTy::BaseType *receiver,
const HIR::PathIdentSegment &query,
const TraitReference *trait_reference)
: PathProbeType (receiver, query, UNKNOWN_DEFID),
@@ -451,7 +451,7 @@ PathProbeImplTrait::PathProbeImplTrait (const TyTy::BaseType *receiver,
{}
std::set<PathProbeCandidate>
-PathProbeImplTrait::Probe (const TyTy::BaseType *receiver,
+PathProbeImplTrait::Probe (TyTy::BaseType *receiver,
const HIR::PathIdentSegment &segment_name,
const TraitReference *trait_reference)
{
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index 59ffeb1..936bcb9 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -108,9 +108,8 @@ class PathProbeType : public TypeCheckBase, public HIR::HIRImplVisitor
{
public:
static std::set<PathProbeCandidate>
- Probe (const TyTy::BaseType *receiver,
- const HIR::PathIdentSegment &segment_name, bool probe_impls,
- bool probe_bounds, bool ignore_mandatory_trait_items,
+ Probe (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);
void visit (HIR::TypeAlias &alias) override;
@@ -135,8 +134,8 @@ protected:
bool ignore_mandatory_trait_items);
protected:
- PathProbeType (const TyTy::BaseType *receiver,
- const HIR::PathIdentSegment &query, DefId specific_trait_id);
+ PathProbeType (TyTy::BaseType *receiver, const HIR::PathIdentSegment &query,
+ DefId specific_trait_id);
std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
union_bounds (
@@ -147,7 +146,7 @@ protected:
bool is_receiver_generic () const;
- const TyTy::BaseType *receiver;
+ TyTy::BaseType *receiver;
const HIR::PathIdentSegment &search;
std::set<PathProbeCandidate> candidates;
HIR::ImplBlock *current_impl;
@@ -178,12 +177,11 @@ class PathProbeImplTrait : public PathProbeType
{
public:
static std::set<PathProbeCandidate>
- Probe (const TyTy::BaseType *receiver,
- const HIR::PathIdentSegment &segment_name,
+ Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name,
const TraitReference *trait_reference);
private:
- PathProbeImplTrait (const TyTy::BaseType *receiver,
+ PathProbeImplTrait (TyTy::BaseType *receiver,
const HIR::PathIdentSegment &query,
const TraitReference *trait_reference);
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.cc b/gcc/rust/typecheck/rust-hir-trait-reference.cc
index 83985f0..74856f0 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.cc
@@ -342,7 +342,15 @@ TraitReference::on_resolved ()
{
for (auto &item : item_refs)
{
- item.on_resolved ();
+ if (item.get_trait_item_type ()
+ == TraitItemReference::TraitItemType::TYPE)
+ item.on_resolved ();
+ }
+ for (auto &item : item_refs)
+ {
+ if (item.get_trait_item_type ()
+ != TraitItemReference::TraitItemType::TYPE)
+ item.on_resolved ();
}
}
@@ -424,7 +432,13 @@ TraitReference::trait_has_generics () const
return !trait_substs.empty ();
}
-std::vector<TyTy::SubstitutionParamMapping>
+std::vector<TyTy::SubstitutionParamMapping> &
+TraitReference::get_trait_substs ()
+{
+ return trait_substs;
+}
+
+const std::vector<TyTy::SubstitutionParamMapping> &
TraitReference::get_trait_substs () const
{
return trait_substs;
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h
index 8b1ac7d..473513e 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -224,7 +224,9 @@ public:
bool trait_has_generics () const;
- std::vector<TyTy::SubstitutionParamMapping> get_trait_substs () const;
+ std::vector<TyTy::SubstitutionParamMapping> &get_trait_substs ();
+
+ const std::vector<TyTy::SubstitutionParamMapping> &get_trait_substs () const;
bool satisfies_bound (const TraitReference &reference) const;
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 032bb58..0fd0147 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -22,9 +22,6 @@
#include "rust-type-util.h"
#include "rust-immutable-name-resolution-context.h"
-// used for flag_name_resolution_2_0
-#include "options.h"
-
namespace Rust {
namespace Resolver {
@@ -123,28 +120,16 @@ bool
TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
HIR::Trait **resolved) const
{
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+
NodeId ref;
- bool ok;
- if (flag_name_resolution_2_0)
+ if (auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid ()))
{
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid ());
-
- if ((ok = ref_opt.has_value ()))
- ref = *ref_opt;
+ ref = *ref_opt;
}
else
{
- auto path_nodeid = path.get_mappings ().get_nodeid ();
- ok = resolver->lookup_resolved_type (path_nodeid, &ref)
- || resolver->lookup_resolved_name (path_nodeid, &ref)
- || resolver->lookup_resolved_macro (path_nodeid, &ref);
- }
-
- if (!ok)
- {
rust_error_at (path.get_locus (), "Failed to resolve path to node-id");
return false;
}
@@ -224,7 +209,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
// handling.
break;
- case HIR::GenericParam::GenericKind::TYPE: {
+ case HIR::GenericParam::GenericKind::TYPE:
+ {
auto &typaram = static_cast<HIR::TypeParam &> (*generic_param);
bool is_self
= typaram.get_type_representation ().as_string ().compare ("Self")
@@ -287,7 +273,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
auto predicate = get_predicate_from_bound (
b->get_path (),
- tl::nullopt /*this will setup a PLACEHOLDER for self*/);
+ tl::nullopt /*this will setup a PLACEHOLDER for self*/,
+ BoundPolarity::RegularBound, false, true);
if (predicate.is_error ())
return &TraitReference::error_node ();
@@ -443,11 +430,27 @@ TraitItemReference::associated_type_set (TyTy::BaseType *ty) const
{
rust_assert (get_trait_item_type () == TraitItemType::TYPE);
+ // this isnt super safe there are cases like the FnTraits where the type is
+ // set to the impls placeholder associated type. For example
+ //
+ // type Output = F::Output; -- see the fn trait impls in libcore
+ //
+ // then this projection ends up resolving back to this placeholder so it just
+ // ends up being cyclical
+
TyTy::BaseType *item_ty = get_tyty ();
rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
TyTy::PlaceholderType *placeholder
= static_cast<TyTy::PlaceholderType *> (item_ty);
+ if (ty->is<TyTy::ProjectionType> ())
+ {
+ const auto &projection = *static_cast<const TyTy::ProjectionType *> (ty);
+ const auto resolved = projection.get ();
+ if (resolved == item_ty)
+ return;
+ }
+
placeholder->set_associated_type (ty->get_ty_ref ());
}
@@ -543,7 +546,8 @@ AssociatedImplTrait::setup_associated_types (
// handling.
break;
- case HIR::GenericParam::GenericKind::TYPE: {
+ case HIR::GenericParam::GenericKind::TYPE:
+ {
TyTy::BaseType *l = nullptr;
bool ok = context->lookup_type (
generic_param->get_mappings ().get_hirid (), &l);
@@ -580,8 +584,8 @@ AssociatedImplTrait::setup_associated_types (
}
else
{
- TyTy::ParamType *param = p.get_param_ty ();
- TyTy::BaseType *resolved = param->destructure ();
+ auto param = p.get_param_ty ();
+ auto resolved = param->destructure ();
subst_args.push_back (TyTy::SubstitutionArg (&p, resolved));
param_mappings[param->get_symbol ()] = resolved->get_ref ();
}
@@ -609,8 +613,8 @@ AssociatedImplTrait::setup_associated_types (
if (i == 0)
continue;
- const TyTy::ParamType *p = arg.get_param_ty ();
- TyTy::BaseType *r = p->resolve ();
+ const auto p = arg.get_param_ty ();
+ auto r = p->resolve ();
if (!r->is_concrete ())
{
r = SubstMapperInternal::Resolve (r, infer_arguments);
@@ -626,8 +630,8 @@ AssociatedImplTrait::setup_associated_types (
if (i == 0)
continue;
- const TyTy::ParamType *p = arg.get_param_ty ();
- TyTy::BaseType *r = p->resolve ();
+ const auto p = arg.get_param_ty ();
+ auto r = p->resolve ();
if (!r->is_concrete ())
{
r = SubstMapperInternal::Resolve (r, infer_arguments);
@@ -753,7 +757,8 @@ TraitItemReference::is_object_safe () const
// https://doc.rust-lang.org/reference/items/traits.html#object-safety
switch (get_trait_item_type ())
{
- case TraitItemReference::TraitItemType::FN: {
+ case TraitItemReference::TraitItemType::FN:
+ {
// lets be boring and just check that this is indeed a method will do
// for now
const HIR::TraitItem *item = get_hir_trait_item ();
diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h
index 82333f1..5384700 100644
--- a/gcc/rust/typecheck/rust-hir-type-bounds.h
+++ b/gcc/rust/typecheck/rust-hir-type-bounds.h
@@ -37,7 +37,11 @@ public:
private:
void scan ();
- void assemble_sized_builtin ();
+ bool
+ process_impl_block (HirId id, HIR::ImplBlock *impl,
+ std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
+ &possible_trait_paths);
+ void assemble_marker_builtins ();
void add_trait_bound (HIR::Trait *trait);
void assemble_builtin_candidate (LangItem::Kind item);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 14b8ab8..68001bf 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -17,28 +17,33 @@
// <http://www.gnu.org/licenses/>.
#include "rust-hir-type-check-base.h"
+#include "rust-compile-base.h"
+#include "rust-hir-item.h"
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-type.h"
#include "rust-hir-trait-resolve.h"
#include "rust-type-util.h"
#include "rust-attribute-values.h"
+#include "rust-tyty.h"
+#include "tree.h"
namespace Rust {
namespace Resolver {
TypeCheckBase::TypeCheckBase ()
- : mappings (Analysis::Mappings::get ()), resolver (Resolver::get ()),
- context (TypeCheckContext::get ())
+ : mappings (Analysis::Mappings::get ()), context (TypeCheckContext::get ())
{}
void
TypeCheckBase::ResolveGenericParams (
+ const HIR::Item::ItemKind item_kind, location_t item_locus,
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
ABI abi)
{
TypeCheckBase ctx;
- ctx.resolve_generic_params (generic_params, substitutions, is_foreign, abi);
+ ctx.resolve_generic_params (item_kind, item_locus, generic_params,
+ substitutions, is_foreign, abi);
}
static void
@@ -47,10 +52,10 @@ walk_types_to_constrain (std::set<HirId> &constrained_symbols,
{
for (const auto &c : constraints.get_mappings ())
{
- const TyTy::BaseType *arg = c.get_tyty ();
+ auto arg = c.get_tyty ();
if (arg != nullptr)
{
- const TyTy::BaseType *p = arg->get_root ();
+ const auto p = arg->get_root ();
constrained_symbols.insert (p->get_ty_ref ());
if (p->has_substitutions_defined ())
{
@@ -66,7 +71,7 @@ TypeCheckBase::check_for_unconstrained (
const std::vector<TyTy::SubstitutionParamMapping> &params_to_constrain,
const TyTy::SubstitutionArgumentMappings &constraint_a,
const TyTy::SubstitutionArgumentMappings &constraint_b,
- const TyTy::BaseType *reference)
+ TyTy::BaseType *reference)
{
bool check_result = false;
bool check_completed
@@ -124,7 +129,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
TyTy::BaseType *infered = nullptr;
switch (literal.get_lit_type ())
{
- case HIR::Literal::LitType::INT: {
+ case HIR::Literal::LitType::INT:
+ {
bool ok = false;
switch (literal.get_type_hint ())
@@ -191,7 +197,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
}
break;
- case HIR::Literal::LitType::FLOAT: {
+ case HIR::Literal::LitType::FLOAT:
+ {
bool ok = false;
switch (literal.get_type_hint ())
@@ -216,25 +223,29 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
}
break;
- case HIR::Literal::LitType::BOOL: {
+ case HIR::Literal::LitType::BOOL:
+ {
auto ok = context->lookup_builtin ("bool", &infered);
rust_assert (ok);
}
break;
- case HIR::Literal::LitType::CHAR: {
+ case HIR::Literal::LitType::CHAR:
+ {
auto ok = context->lookup_builtin ("char", &infered);
rust_assert (ok);
}
break;
- case HIR::Literal::LitType::BYTE: {
+ case HIR::Literal::LitType::BYTE:
+ {
auto ok = context->lookup_builtin ("u8", &infered);
rust_assert (ok);
}
break;
- case HIR::Literal::LitType::STRING: {
+ case HIR::Literal::LitType::STRING:
+ {
TyTy::BaseType *base = nullptr;
auto ok = context->lookup_builtin ("str", &base);
rust_assert (ok);
@@ -246,7 +257,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
}
break;
- case HIR::Literal::LitType::BYTE_STRING: {
+ case HIR::Literal::LitType::BYTE_STRING:
+ {
/* This is an arraytype of u8 reference (&[u8;size]). It isn't in
UTF-8, but really just a byte array. Code to construct the array
reference copied from ArrayElemsValues and ArrayType. */
@@ -280,10 +292,21 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
crate_num),
UNKNOWN_LOCAL_DEFID);
+ auto ctx = Compile::Context::get ();
+ tree capacity = Compile::HIRCompileBase::query_compile_const_expr (
+ ctx, expected_ty, *literal_capacity);
+
+ TyTy::ConstType *capacity_expr
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "",
+ expected_ty, capacity, {},
+ literal_capacity->get_locus (),
+ literal_capacity->get_mappings ().get_hirid (),
+ literal_capacity->get_mappings ().get_hirid (),
+ {});
+
TyTy::ArrayType *array
= new TyTy::ArrayType (array_mapping.get_hirid (), locus,
- *literal_capacity,
- TyTy::TyVar (u8->get_ref ()));
+ capacity_expr, TyTy::TyVar (u8->get_ref ()));
context->insert_type (array_mapping, array);
infered = new TyTy::ReferenceType (expr_mappings.get_hirid (),
@@ -432,6 +455,7 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus)
void
TypeCheckBase::resolve_generic_params (
+ const HIR::Item::ItemKind item_kind, location_t item_locus,
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
ABI abi)
@@ -440,7 +464,8 @@ TypeCheckBase::resolve_generic_params (
{
switch (generic_param->get_kind ())
{
- case HIR::GenericParam::GenericKind::LIFETIME: {
+ case HIR::GenericParam::GenericKind::LIFETIME:
+ {
auto lifetime_param
= static_cast<HIR::LifetimeParam &> (*generic_param);
auto lifetime = lifetime_param.get_lifetime ();
@@ -449,7 +474,8 @@ TypeCheckBase::resolve_generic_params (
}
break;
- case HIR::GenericParam::GenericKind::CONST: {
+ case HIR::GenericParam::GenericKind::CONST:
+ {
if (is_foreign && abi != Rust::ABI::INTRINSIC)
{
rust_error_at (generic_param->get_locus (), ErrorCode::E0044,
@@ -462,6 +488,27 @@ TypeCheckBase::resolve_generic_params (
if (param.has_default_expression ())
{
+ switch (item_kind)
+ {
+ case HIR::Item::ItemKind::Struct:
+ case HIR::Item::ItemKind::Enum:
+ case HIR::Item::ItemKind::TypeAlias:
+ case HIR::Item::ItemKind::Trait:
+ case HIR::Item::ItemKind::Union:
+ break;
+
+ default:
+ {
+ rich_location r (line_table, item_locus);
+ r.add_fixit_remove (param.get_locus ());
+ rust_error_at (
+ r,
+ "default values for const generic parameters are not "
+ "allowed here");
+ }
+ break;
+ }
+
auto expr_type
= TypeCheckExpr::Resolve (param.get_default_expression ());
@@ -471,14 +518,39 @@ TypeCheckBase::resolve_generic_params (
expr_type,
param.get_default_expression ().get_locus ()),
param.get_locus ());
+
+ // fold the default value
+ auto ctx = Compile::Context::get ();
+ auto &expr = param.get_default_expression ();
+ tree default_value
+ = Compile::HIRCompileBase::query_compile_const_expr (
+ ctx, specified_type, expr);
+
+ TyTy::ConstType *default_const_decl
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value,
+ param.get_name (), specified_type,
+ default_value, {}, param.get_locus (),
+ expr.get_mappings ().get_hirid (),
+ expr.get_mappings ().get_hirid (), {});
+
+ context->insert_type (expr.get_mappings (), default_const_decl);
}
- context->insert_type (generic_param->get_mappings (),
- specified_type);
+ TyTy::ConstType *const_decl
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Decl,
+ param.get_name (), specified_type,
+ error_mark_node, {}, param.get_locus (),
+ param.get_mappings ().get_hirid (),
+ param.get_mappings ().get_hirid (), {});
+
+ context->insert_type (generic_param->get_mappings (), const_decl);
+ TyTy::SubstitutionParamMapping p (*generic_param, const_decl);
+ substitutions.push_back (p);
}
break;
- case HIR::GenericParam::GenericKind::TYPE: {
+ case HIR::GenericParam::GenericKind::TYPE:
+ {
if (is_foreign && abi != Rust::ABI::INTRINSIC)
{
rust_error_at (generic_param->get_locus (), ErrorCode::E0044,
@@ -489,8 +561,7 @@ TypeCheckBase::resolve_generic_params (
*generic_param, false /*resolve_trait_bounds*/);
context->insert_type (generic_param->get_mappings (), param_type);
- auto &param = static_cast<HIR::TypeParam &> (*generic_param);
- TyTy::SubstitutionParamMapping p (param, param_type);
+ TyTy::SubstitutionParamMapping p (*generic_param, param_type);
substitutions.push_back (p);
}
break;
@@ -500,9 +571,16 @@ TypeCheckBase::resolve_generic_params (
// now walk them to setup any specified type param bounds
for (auto &subst : substitutions)
{
- auto pty = subst.get_param_ty ();
- TypeResolveGenericParam::ApplyAnyTraitBounds (subst.get_generic_param (),
- pty);
+ auto &generic = subst.get_generic_param ();
+ if (generic.get_kind () != HIR::GenericParam::GenericKind::TYPE)
+ continue;
+
+ auto &type_param = static_cast<HIR::TypeParam &> (generic);
+ auto bpty = subst.get_param_ty ();
+ rust_assert (bpty->get_kind () == TyTy::TypeKind::PARAM);
+ auto pty = static_cast<TyTy::ParamType *> (bpty);
+
+ TypeResolveGenericParam::ApplyAnyTraitBounds (type_param, pty);
}
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index 580082a..6430089 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -33,6 +33,7 @@ public:
virtual ~TypeCheckBase () {}
static void ResolveGenericParams (
+ const HIR::Item::ItemKind item_kind, location_t item_locus,
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
ABI abi);
@@ -46,13 +47,13 @@ protected:
HIR::TypePath &path,
tl::optional<std::reference_wrapper<HIR::Type>> associated_self,
BoundPolarity polarity = BoundPolarity::RegularBound,
- bool is_qualified_type = false);
+ bool is_qualified_type = false, bool is_super_trait = false);
bool check_for_unconstrained (
const std::vector<TyTy::SubstitutionParamMapping> &params_to_constrain,
const TyTy::SubstitutionArgumentMappings &constraint_a,
const TyTy::SubstitutionArgumentMappings &constraint_b,
- const TyTy::BaseType *reference);
+ TyTy::BaseType *reference);
TyTy::BaseType *resolve_literal (const Analysis::NodeMapping &mappings,
HIR::Literal &literal, location_t locus);
@@ -61,6 +62,7 @@ protected:
location_t locus);
void resolve_generic_params (
+ const HIR::Item::ItemKind item_kind, location_t item_locus,
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions,
bool is_foreign = false, ABI abi = ABI::RUST);
@@ -69,7 +71,6 @@ protected:
location_t locus);
Analysis::Mappings &mappings;
- Resolver *resolver;
TypeCheckContext *context;
};
diff --git a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc
index c80a12f..23a8cca 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc
@@ -23,9 +23,6 @@
#include "rust-type-util.h"
#include "rust-immutable-name-resolution-context.h"
-// for flag_name_resolution_2_0
-#include "options.h"
-
namespace Rust {
namespace Resolver {
@@ -79,25 +76,13 @@ TypeCheckEnumItem::visit (HIR::EnumItem &item)
rust_assert (ok);
context->insert_type (mapping, isize);
- tl::optional<CanonicalPath> canonical_path;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path
- = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path.has_value ());
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, item.get_locus ()};
+ RustIdent ident{canonical_path, item.get_locus ()};
variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
item.get_mappings ().get_defid (),
item.get_identifier ().as_string (), ident,
@@ -123,25 +108,13 @@ TypeCheckEnumItem::visit (HIR::EnumItemDiscriminant &item)
TyTy::TyWithLocation (expected_ty),
TyTy::TyWithLocation (capacity_type), item.get_locus ());
- tl::optional<CanonicalPath> canonical_path;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path
- = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path.has_value ());
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, item.get_locus ()};
+ RustIdent ident{canonical_path, item.get_locus ()};
variant
= new TyTy::VariantDef (item.get_mappings ().get_hirid (),
item.get_mappings ().get_defid (),
@@ -185,25 +158,13 @@ TypeCheckEnumItem::visit (HIR::EnumItemTuple &item)
rust_assert (ok);
context->insert_type (mapping, isize);
- tl::optional<CanonicalPath> canonical_path;
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path
- = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ());
- }
-
- rust_assert (canonical_path.has_value ());
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, item.get_locus ()};
+ RustIdent ident{canonical_path, item.get_locus ()};
variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
item.get_mappings ().get_defid (),
item.get_identifier ().as_string (), ident,
@@ -245,25 +206,13 @@ TypeCheckEnumItem::visit (HIR::EnumItemStruct &item)
rust_assert (ok);
context->insert_type (mapping, isize);
- tl::optional<CanonicalPath> canonical_path;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path
- = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path.has_value ());
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, item.get_locus ()};
+ RustIdent ident{canonical_path, item.get_locus ()};
variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
item.get_mappings ().get_defid (),
item.get_identifier ().as_string (), ident,
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index cbf529a7..438200b 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -17,6 +17,7 @@
// <http://www.gnu.org/licenses/>.
#include "optional.h"
+#include "rust-common.h"
#include "rust-hir-expr.h"
#include "rust-system.h"
#include "rust-tyty-call.h"
@@ -31,9 +32,9 @@
#include "rust-hir-type-check-item.h"
#include "rust-type-util.h"
#include "rust-immutable-name-resolution-context.h"
-
-// for flag_name_resolution_2_0
-#include "options.h"
+#include "rust-compile-base.h"
+#include "rust-tyty-util.h"
+#include "tree.h"
namespace Rust {
namespace Resolver {
@@ -58,6 +59,19 @@ TypeCheckExpr::Resolve (HIR::Expr &expr)
return resolver.infered;
}
+TyTy::BaseType *
+TypeCheckExpr::ResolveOpOverload (LangItem::Kind lang_item_type,
+ HIR::OperatorExprMeta expr,
+ TyTy::BaseType *lhs, TyTy::BaseType *rhs,
+ HIR::PathIdentSegment specified_segment)
+{
+ TypeCheckExpr resolver;
+
+ resolver.resolve_operator_overload (lang_item_type, expr, lhs, rhs,
+ specified_segment);
+ return resolver.infered;
+}
+
void
TypeCheckExpr::visit (HIR::TupleIndexExpr &expr)
{
@@ -373,7 +387,8 @@ TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
switch (expr.get_expr_type ())
{
case ArithmeticOrLogicalOperator::LEFT_SHIFT:
- case ArithmeticOrLogicalOperator::RIGHT_SHIFT: {
+ case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
+ {
TyTy::TyWithLocation from (rhs, expr.get_rhs ().get_locus ());
TyTy::TyWithLocation to (lhs, expr.get_lhs ().get_locus ());
infered = cast_site (expr.get_mappings ().get_hirid (), from, to,
@@ -381,7 +396,8 @@ TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
}
break;
- default: {
+ default:
+ {
infered = unify_site (
expr.get_mappings ().get_hirid (),
TyTy::TyWithLocation (lhs, expr.get_lhs ().get_locus ()),
@@ -470,7 +486,8 @@ TypeCheckExpr::visit (HIR::NegationExpr &expr)
// https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators
switch (expr.get_expr_type ())
{
- case NegationOperator::NEGATE: {
+ case NegationOperator::NEGATE:
+ {
bool valid
= (negated_expr_ty->get_kind () == TyTy::TypeKind::INT)
|| (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT)
@@ -492,7 +509,8 @@ TypeCheckExpr::visit (HIR::NegationExpr &expr)
}
break;
- case NegationOperator::NOT: {
+ case NegationOperator::NOT:
+ {
bool valid
= (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL)
|| (negated_expr_ty->get_kind () == TyTy::TypeKind::INT)
@@ -643,6 +661,33 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
}
void
+TypeCheckExpr::visit (HIR::AnonConst &expr)
+{
+ if (!expr.is_deferred ())
+ {
+ infered = TypeCheckExpr::Resolve (expr.get_inner_expr ());
+ return;
+ }
+
+ auto locus = expr.get_locus ();
+ auto infer_ty_var = TyTy::TyVar::get_implicit_infer_var (locus);
+
+ HirId next = mappings.get_next_hir_id ();
+ infered = new TyTy::ConstType (TyTy::ConstType::ConstKind::Infer, "",
+ infer_ty_var.get_tyty (), error_mark_node, {},
+ locus, next, next, {});
+
+ context->insert_implicit_type (infered->get_ref (), infered);
+ mappings.insert_location (infered->get_ref (), locus);
+}
+
+void
+TypeCheckExpr::visit (HIR::ConstBlock &expr)
+{
+ infered = TypeCheckExpr::Resolve (expr.get_const_expr ());
+}
+
+void
TypeCheckExpr::visit (HIR::RangeFromToExpr &expr)
{
auto lang_item_type = LangItem::Kind::RANGE;
@@ -790,38 +835,45 @@ typecheck_inline_asm_operand (HIR::InlineAsm &expr)
{
switch (operand.get_register_type ())
{
- case RegisterType::In: {
+ case RegisterType::In:
+ {
auto in = operand.get_in ();
TypeCheckExpr::Resolve (*in.expr);
break;
}
- case RegisterType::Out: {
+ case RegisterType::Out:
+ {
auto out = operand.get_out ();
TypeCheckExpr::Resolve (*out.expr);
break;
}
- case RegisterType::InOut: {
+ case RegisterType::InOut:
+ {
auto in_out = operand.get_in_out ();
TypeCheckExpr::Resolve (*in_out.expr);
break;
}
- case RegisterType::SplitInOut: {
+ case RegisterType::SplitInOut:
+ {
auto split_in_out = operand.get_split_in_out ();
TypeCheckExpr::Resolve (*split_in_out.in_expr);
TypeCheckExpr::Resolve (*split_in_out.out_expr);
break;
}
- case RegisterType::Const: {
+ case RegisterType::Const:
+ {
auto anon_const = operand.get_const ().anon_const;
- TypeCheckExpr::Resolve (*anon_const.expr);
+ TypeCheckExpr::Resolve (anon_const.get_inner_expr ());
break;
}
- case RegisterType::Sym: {
+ case RegisterType::Sym:
+ {
auto sym = operand.get_sym ();
TypeCheckExpr::Resolve (*sym.expr);
break;
}
- case RegisterType::Label: {
+ case RegisterType::Label:
+ {
auto label = operand.get_label ();
TypeCheckExpr::Resolve (*label.expr);
break;
@@ -837,7 +889,7 @@ TypeCheckExpr::visit (HIR::InlineAsm &expr)
// NOTE: Hoise out if we have noreturn as an option
// to return a never type
// TODO : new keyword for memory seems sooooo shaky
- if (expr.options.count (AST::InlineAsmOption::NORETURN) == 1)
+ if (expr.options.count (AST::InlineAsm::Option::NORETURN) == 1)
infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
else
infered = TyTy::TupleType::get_unit_type ();
@@ -857,6 +909,19 @@ TypeCheckExpr::visit (HIR::LlvmInlineAsm &expr)
}
void
+TypeCheckExpr::visit (HIR::OffsetOf &expr)
+{
+ TypeCheckType::Resolve (expr.get_type ());
+
+ // FIXME: Does offset_of always return a usize?
+ TyTy::BaseType *size_ty;
+ bool ok = context->lookup_builtin ("usize", &size_ty);
+ rust_assert (ok);
+
+ infered = size_ty;
+}
+
+void
TypeCheckExpr::visit (HIR::RangeFullExpr &expr)
{
auto lang_item_type = LangItem::Kind::RANGE_FULL;
@@ -960,7 +1025,10 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
bool ok = context->lookup_builtin ("usize", &size_ty);
rust_assert (ok);
- bool maybe_simple_array_access = index_expr_ty->can_eq (size_ty, false);
+ bool maybe_simple_array_access
+ = types_compatable (TyTy::TyWithLocation (index_expr_ty),
+ TyTy::TyWithLocation (size_ty), expr.get_locus (),
+ false);
if (maybe_simple_array_access
&& direct_array_expr_ty->get_kind () == TyTy::TypeKind::ARRAY)
{
@@ -996,8 +1064,7 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
rich_location r (line_table, expr.get_locus ());
r.add_range (expr.get_array_expr ().get_locus ());
r.add_range (expr.get_index_expr ().get_locus ());
- rust_error_at (r, ErrorCode::E0277,
- "the type %qs cannot be indexed by %qs",
+ rust_error_at (r, ErrorCode::E0277, "the type %qs cannot be indexed by %qs",
array_expr_ty->get_name ().c_str (),
index_expr_ty->get_name ().c_str ());
}
@@ -1007,35 +1074,40 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
{
auto &elements = expr.get_internal_elements ();
+ TyTy::BaseType *expected_ty = nullptr;
+ bool ok = context->lookup_builtin ("usize", &expected_ty);
+ rust_assert (ok);
+
HIR::Expr *capacity_expr = nullptr;
TyTy::BaseType *element_type = nullptr;
+ TyTy::BaseType *capacity_type = nullptr;
switch (elements.get_array_expr_type ())
{
- case HIR::ArrayElems::ArrayExprType::COPIED: {
+ case HIR::ArrayElems::ArrayExprType::COPIED:
+ {
HIR::ArrayElemsCopied &elems
= static_cast<HIR::ArrayElemsCopied &> (elements);
element_type = TypeCheckExpr::Resolve (elems.get_elem_to_copy ());
- auto capacity_type
+ auto capacity_expr_ty
= TypeCheckExpr::Resolve (elems.get_num_copies_expr ());
- TyTy::BaseType *expected_ty = nullptr;
- bool ok = context->lookup_builtin ("usize", &expected_ty);
- rust_assert (ok);
context->insert_type (elems.get_num_copies_expr ().get_mappings (),
expected_ty);
- unify_site (expr.get_mappings ().get_hirid (),
- TyTy::TyWithLocation (expected_ty),
- TyTy::TyWithLocation (
- capacity_type, elems.get_num_copies_expr ().get_locus ()),
- expr.get_locus ());
+ unify_site (
+ expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty),
+ TyTy::TyWithLocation (capacity_expr_ty,
+ elems.get_num_copies_expr ().get_locus ()),
+ expr.get_locus ());
capacity_expr = &elems.get_num_copies_expr ();
+ capacity_type = expected_ty;
}
break;
- case HIR::ArrayElems::ArrayExprType::VALUES: {
+ case HIR::ArrayElems::ArrayExprType::VALUES:
+ {
HIR::ArrayElemsValues &elems
= static_cast<HIR::ArrayElemsValues &> (elements);
@@ -1068,17 +1140,26 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
UNDEF_LOCATION, {});
// mark the type for this implicit node
- TyTy::BaseType *expected_ty = nullptr;
- bool ok = context->lookup_builtin ("usize", &expected_ty);
- rust_assert (ok);
context->insert_type (mapping, expected_ty);
+ capacity_type = expected_ty;
}
break;
}
- infered = new TyTy::ArrayType (expr.get_mappings ().get_hirid (),
- expr.get_locus (), *capacity_expr,
- TyTy::TyVar (element_type->get_ref ()));
+ rust_assert (capacity_expr);
+ rust_assert (capacity_type);
+ auto ctx = Compile::Context::get ();
+ tree capacity_value
+ = Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type,
+ *capacity_expr);
+ HirId size_id = capacity_expr->get_mappings ().get_hirid ();
+ TyTy::ConstType *const_type
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", expected_ty,
+ capacity_value, {}, capacity_expr->get_locus (),
+ size_id, size_id);
+ infered
+ = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), expr.get_locus (),
+ const_type, TyTy::TyVar (element_type->get_ref ()));
}
// empty struct
@@ -1408,26 +1489,11 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
// store the expected fntype
context->insert_type (expr.get_method_name ().get_mappings (), lookup);
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
- Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
+ auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
- nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
- Resolver2_0::Definition (resolved_node_id));
- }
- // set up the resolved name on the path
- else if (resolver->get_name_scope ().decl_was_declared_here (
- resolved_node_id))
- {
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
- }
- else
- {
- resolver->insert_resolved_misc (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
- }
+ nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
+ Resolver2_0::Definition (resolved_node_id));
// return the result of the function back
infered = function_ret_tyty;
@@ -1702,16 +1768,22 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr)
void
TypeCheckExpr::visit (HIR::ClosureExpr &expr)
{
- TypeCheckContextItem current_context = context->peek_context ();
- TyTy::FnType *current_context_fndecl = current_context.get_context_type ();
-
+ std::vector<TyTy::SubstitutionParamMapping> subst_refs;
HirId ref = expr.get_mappings ().get_hirid ();
DefId id = expr.get_mappings ().get_defid ();
- RustIdent ident{current_context_fndecl->get_ident ().path, expr.get_locus ()};
+ RustIdent ident{CanonicalPath::create_empty (), expr.get_locus ()};
- // get from parent context
- std::vector<TyTy::SubstitutionParamMapping> subst_refs
- = current_context_fndecl->clone_substs ();
+ if (context->have_function_context ())
+ {
+ TypeCheckContextItem current_context = context->peek_context ();
+ TyTy::FnType *current_context_fndecl
+ = current_context.get_context_type ();
+
+ ident = RustIdent{current_context_fndecl->get_ident ().path,
+ expr.get_locus ()};
+
+ subst_refs = current_context_fndecl->clone_substs ();
+ }
std::vector<TyTy::TyVar> parameter_types;
for (auto &p : expr.get_params ())
@@ -1763,19 +1835,12 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr)
// Resolve closure captures
std::set<NodeId> captures;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
- Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
+ auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
- if (auto opt_cap = nr_ctx.mappings.lookup_captures (closure_node_id))
- for (auto cap : opt_cap.value ())
- captures.insert (cap);
- }
- else
- {
- captures = resolver->get_captures (closure_node_id);
- }
+ if (auto opt_cap = nr_ctx.mappings.lookup_captures (closure_node_id))
+ for (auto cap : opt_cap.value ())
+ captures.insert (cap);
infered = new TyTy::ClosureType (ref, id, ident, closure_args, result_type,
subst_refs, captures);
@@ -1826,7 +1891,7 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr)
args.get_type_args ().push_back (std::unique_ptr<HIR::Type> (implicit_tuple));
// apply the arguments
- predicate.apply_generic_arguments (&args, false);
+ predicate.apply_generic_arguments (&args, false, false);
// finally inherit the trait bound
infered->inherit_bounds ({predicate});
@@ -1845,7 +1910,16 @@ TypeCheckExpr::resolve_operator_overload (
// probe for the lang-item
if (!lang_item_defined)
return false;
+
DefId &respective_lang_item_id = lang_item_defined.value ();
+ auto def_lookup = mappings.lookup_defid (respective_lang_item_id);
+ rust_assert (def_lookup.has_value ());
+
+ HIR::Item *def_item = def_lookup.value ();
+ rust_assert (def_item->get_item_kind () == HIR::Item::ItemKind::Trait);
+ HIR::Trait &trait = *static_cast<HIR::Trait *> (def_item);
+ TraitReference *defid_trait_reference = TraitResolver::Resolve (trait);
+ rust_assert (!defid_trait_reference->is_error ());
// we might be in a static or const context and unknown is fine
TypeCheckContextItem current_context = TypeCheckContextItem::get_error ();
@@ -1889,15 +1963,49 @@ TypeCheckExpr::resolve_operator_overload (
if (selected_candidates.size () > 1)
{
- // mutliple candidates
- rich_location r (line_table, expr.get_locus ());
- for (auto &c : resolved_candidates)
- r.add_range (c.candidate.locus);
+ auto infer
+ = TyTy::TyVar::get_implicit_infer_var (expr.get_locus ()).get_tyty ();
+ auto trait_subst = defid_trait_reference->get_trait_substs ();
+ rust_assert (trait_subst.size () > 0);
- rust_error_at (
- r, "multiple candidates found for possible operator overload");
+ TyTy::TypeBoundPredicate pred (respective_lang_item_id, trait_subst,
+ BoundPolarity::RegularBound,
+ expr.get_locus ());
- return false;
+ std::vector<TyTy::SubstitutionArg> mappings;
+ auto &self_param_mapping = trait_subst[0];
+ mappings.push_back (TyTy::SubstitutionArg (&self_param_mapping, lhs));
+
+ if (rhs != nullptr)
+ {
+ rust_assert (trait_subst.size () == 2);
+ auto &rhs_param_mapping = trait_subst[1];
+ mappings.push_back (TyTy::SubstitutionArg (&rhs_param_mapping, lhs));
+ }
+
+ std::map<std::string, TyTy::BaseType *> binding_args;
+ binding_args["Output"] = infer;
+
+ TyTy::SubstitutionArgumentMappings arg_mappings (mappings, binding_args,
+ TyTy::RegionParamList (
+ trait_subst.size ()),
+ expr.get_locus ());
+ pred.apply_argument_mappings (arg_mappings, false);
+
+ infer->inherit_bounds ({pred});
+ DeferredOpOverload defer (expr.get_mappings ().get_hirid (),
+ lang_item_type, specified_segment, pred, expr);
+ context->insert_deferred_operator_overload (std::move (defer));
+
+ if (rhs != nullptr)
+ lhs = unify_site (expr.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (lhs),
+ TyTy::TyWithLocation (rhs), expr.get_locus ());
+
+ infered = unify_site (expr.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (lhs),
+ TyTy::TyWithLocation (infer), expr.get_locus ());
+ return true;
}
// Get the adjusted self
@@ -2040,19 +2148,11 @@ TypeCheckExpr::resolve_operator_overload (
context->insert_operator_overload (expr.get_mappings ().get_hirid (), type);
// set up the resolved name on the path
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
- Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
+ auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
- nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
- Resolver2_0::Definition (resolved_node_id));
- }
- else
- {
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
- }
+ nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
+ Resolver2_0::Definition (resolved_node_id));
// return the result of the function back
infered = function_ret_tyty;
@@ -2062,16 +2162,13 @@ TypeCheckExpr::resolve_operator_overload (
HIR::PathIdentSegment
TypeCheckExpr::resolve_possible_fn_trait_call_method_name (
- TyTy::BaseType &receiver, TyTy::TypeBoundPredicate *associated_predicate)
+ const TyTy::BaseType &receiver,
+ TyTy::TypeBoundPredicate *associated_predicate)
{
- // Question
- // do we need to probe possible bounds here? I think not, i think when we
- // support Fn traits they are explicitly specified
-
// FIXME
// the logic to map the FnTrait to their respective call trait-item is
// duplicated over in the backend/rust-compile-expr.cc
- for (auto &bound : receiver.get_specified_bounds ())
+ for (const auto &bound : receiver.get_specified_bounds ())
{
bool found_fn = bound.get_name ().compare ("Fn") == 0;
bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0;
@@ -2094,6 +2191,34 @@ TypeCheckExpr::resolve_possible_fn_trait_call_method_name (
}
}
+ if (receiver.is<TyTy::ReferenceType> ())
+ {
+ const auto &ref = static_cast<const TyTy::ReferenceType &> (receiver);
+ const auto &underlying = *ref.get_base ();
+ for (const auto &bound : underlying.get_specified_bounds ())
+ {
+ bool found_fn = bound.get_name ().compare ("Fn") == 0;
+ bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0;
+ bool found_fn_once = bound.get_name ().compare ("FnOnce") == 0;
+
+ if (found_fn)
+ {
+ *associated_predicate = bound;
+ return HIR::PathIdentSegment ("call");
+ }
+ else if (found_fn_mut)
+ {
+ *associated_predicate = bound;
+ return HIR::PathIdentSegment ("call_mut");
+ }
+ else if (found_fn_once)
+ {
+ *associated_predicate = bound;
+ return HIR::PathIdentSegment ("call_once");
+ }
+ }
+ }
+
// nothing
*associated_predicate = TyTy::TypeBoundPredicate::error ();
return HIR::PathIdentSegment ("");
@@ -2220,32 +2345,15 @@ TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr,
context->insert_operator_overload (expr.get_mappings ().get_hirid (), fn);
// set up the resolved name on the path
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
- Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
+ auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
- auto existing = nr_ctx.lookup (expr.get_mappings ().get_nodeid ());
- if (existing)
- rust_assert (*existing == resolved_node_id);
- else
- nr_ctx.map_usage (Resolver2_0::Usage (
- expr.get_mappings ().get_nodeid ()),
- Resolver2_0::Definition (resolved_node_id));
- }
+ auto existing = nr_ctx.lookup (expr.get_mappings ().get_nodeid ());
+ if (existing)
+ rust_assert (*existing == resolved_node_id);
else
- {
- NodeId existing = UNKNOWN_NODEID;
- bool ok
- = resolver->lookup_resolved_name (expr.get_mappings ().get_nodeid (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node_id);
- else
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
- }
+ nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
+ Resolver2_0::Definition (resolved_node_id));
// return the result of the function back
*result = function_ret_tyty;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 79121b3..0343922 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -19,6 +19,7 @@
#ifndef RUST_HIR_TYPE_CHECK_EXPR
#define RUST_HIR_TYPE_CHECK_EXPR
+#include "rust-hir-expr.h"
#include "rust-hir-type-check-base.h"
#include "rust-hir-visitor.h"
#include "rust-tyty.h"
@@ -31,6 +32,11 @@ class TypeCheckExpr : private TypeCheckBase, private HIR::HIRExpressionVisitor
public:
static TyTy::BaseType *Resolve (HIR::Expr &expr);
+ static TyTy::BaseType *
+ ResolveOpOverload (LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr,
+ TyTy::BaseType *lhs, TyTy::BaseType *rhs,
+ HIR::PathIdentSegment specified_segment);
+
void visit (HIR::TupleIndexExpr &expr) override;
void visit (HIR::TupleExpr &expr) override;
void visit (HIR::ReturnExpr &expr) override;
@@ -46,6 +52,8 @@ public:
void visit (HIR::IfExpr &expr) override;
void visit (HIR::IfExprConseqElse &expr) override;
void visit (HIR::BlockExpr &expr) override;
+ void visit (HIR::AnonConst &expr) override;
+ void visit (HIR::ConstBlock &expr) override;
void visit (HIR::UnsafeBlockExpr &expr) override;
void visit (HIR::ArrayIndexExpr &expr) override;
void visit (HIR::ArrayExpr &expr) override;
@@ -71,6 +79,7 @@ public:
void visit (HIR::ClosureExpr &expr) override;
void visit (HIR::InlineAsm &expr) override;
void visit (HIR::LlvmInlineAsm &expr) override;
+ void visit (HIR::OffsetOf &expr) override;
// TODO
void visit (HIR::ErrorPropagationExpr &) override {}
@@ -107,7 +116,8 @@ protected:
TyTy::BaseType **result);
HIR::PathIdentSegment resolve_possible_fn_trait_call_method_name (
- TyTy::BaseType &receiver, TyTy::TypeBoundPredicate *associated_predicate);
+ const TyTy::BaseType &receiver,
+ TyTy::TypeBoundPredicate *associated_predicate);
private:
TypeCheckExpr ();
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
index bc7f6dc..c8544a1 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
@@ -28,9 +28,6 @@
#include "rust-tyty.h"
#include "rust-immutable-name-resolution-context.h"
-// for flag_name_resolution_2_0
-#include "options.h"
-
namespace Rust {
namespace Resolver {
@@ -73,7 +70,9 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function)
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (function.has_generics ())
{
- resolve_generic_params (function.get_generic_params (), substitutions,
+ resolve_generic_params (HIR::Item::ItemKind::Function,
+ function.get_locus (),
+ function.get_generic_params (), substitutions,
true /*is_foreign*/, parent.get_abi ());
}
@@ -203,7 +202,9 @@ TypeCheckImplItem::visit (HIR::Function &function)
auto binder_pin = context->push_lifetime_binder ();
if (function.has_generics ())
- resolve_generic_params (function.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Function,
+ function.get_locus (),
+ function.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : function.get_where_clause ().get_items ())
@@ -266,7 +267,8 @@ TypeCheckImplItem::visit (HIR::Function &function)
self_type = self->clone ();
break;
- case HIR::SelfParam::IMM_REF: {
+ case HIR::SelfParam::IMM_REF:
+ {
tl::optional<TyTy::Region> region;
if (self_param.has_lifetime ())
{
@@ -290,7 +292,8 @@ TypeCheckImplItem::visit (HIR::Function &function)
}
break;
- case HIR::SelfParam::MUT_REF: {
+ case HIR::SelfParam::MUT_REF:
+ {
tl::optional<TyTy::Region> region;
if (self_param.has_lifetime ())
{
@@ -336,25 +339,13 @@ TypeCheckImplItem::visit (HIR::Function &function)
TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty));
}
- tl::optional<CanonicalPath> canonical_path;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path = nr_ctx.values.to_canonical_path (
- function.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = mappings.lookup_canonical_path (
- function.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path.has_value ());
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, function.get_locus ()};
+ RustIdent ident{canonical_path, function.get_locus ()};
auto fnType = new TyTy::FnType (
function.get_mappings ().get_hirid (),
function.get_mappings ().get_defid (),
@@ -410,7 +401,8 @@ TypeCheckImplItem::visit (HIR::TypeAlias &alias)
auto binder_pin = context->push_lifetime_binder ();
if (alias.has_generics ())
- resolve_generic_params (alias.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::TypeAlias, alias.get_locus (),
+ alias.get_generic_params (), substitutions);
TyTy::BaseType *actual_type
= TypeCheckType::Resolve (alias.get_type_aliased ());
@@ -494,10 +486,9 @@ TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant)
rich_location r (line_table, constant.get_locus ());
r.add_range (resolved_trait_item.get_locus ());
- rust_error_at (
- r, "constant %qs has an incompatible type for trait %qs",
- constant.get_identifier ().as_string ().c_str (),
- trait_reference.get_name ().c_str ());
+ rust_error_at (r, "constant %qs has an incompatible type for trait %qs",
+ constant.get_identifier ().as_string ().c_str (),
+ trait_reference.get_name ().c_str ());
}
}
@@ -545,10 +536,9 @@ TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type)
rich_location r (line_table, type.get_locus ());
r.add_range (resolved_trait_item.get_locus ());
- rust_error_at (
- r, "type alias %qs has an incompatible type for trait %qs",
- type.get_new_type_name ().as_string ().c_str (),
- trait_reference.get_name ().c_str ());
+ rust_error_at (r, "type alias %qs has an incompatible type for trait %qs",
+ type.get_new_type_name ().as_string ().c_str (),
+ trait_reference.get_name ().c_str ());
}
// its actually a projection, since we need a way to actually bind the
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index aaa04af..3ba607b 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc
@@ -20,6 +20,7 @@
#include "optional.h"
#include "rust-canonical-path.h"
#include "rust-diagnostics.h"
+#include "rust-hir-item.h"
#include "rust-hir-type-check-enumitem.h"
#include "rust-hir-type-check-implitem.h"
#include "rust-hir-type-check-type.h"
@@ -33,9 +34,6 @@
#include "rust-type-util.h"
#include "rust-tyty-variance-analysis.h"
-// for flag_name_resolution_2_0
-#include "options.h"
-
namespace Rust {
namespace Resolver {
@@ -121,8 +119,8 @@ TypeCheckItem::ResolveImplBlockSelfWithInference (
}
else
{
- TyTy::ParamType *param = p.get_param_ty ();
- TyTy::BaseType *resolved = param->destructure ();
+ auto param = p.get_param_ty ();
+ auto resolved = param->destructure ();
args.push_back (TyTy::SubstitutionArg (&p, resolved));
}
}
@@ -170,7 +168,9 @@ TypeCheckItem::visit (HIR::TupleStruct &struct_decl)
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (struct_decl.has_generics ())
- resolve_generic_params (struct_decl.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Struct,
+ struct_decl.get_locus (),
+ struct_decl.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
@@ -195,25 +195,11 @@ TypeCheckItem::visit (HIR::TupleStruct &struct_decl)
// get the path
- auto path = CanonicalPath::create_empty ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- // FIXME: HACK: ARTHUR: Disgusting
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- path = nr_ctx.values
- .to_canonical_path (struct_decl.get_mappings ().get_nodeid ())
- .value ();
- }
- else
- {
- path
- = mappings
- .lookup_canonical_path (struct_decl.get_mappings ().get_nodeid ())
- .value ();
- }
+ CanonicalPath path
+ = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ());
RustIdent ident{path, struct_decl.get_locus ()};
@@ -255,7 +241,9 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl)
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (struct_decl.has_generics ())
- resolve_generic_params (struct_decl.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Struct,
+ struct_decl.get_locus (),
+ struct_decl.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
@@ -276,27 +264,11 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl)
context->insert_type (field.get_mappings (), ty_field->get_field_type ());
}
- auto path = CanonicalPath::create_empty ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- // FIXME: HACK: ARTHUR: Disgusting
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- auto canonical_path = nr_ctx.types.to_canonical_path (
- struct_decl.get_mappings ().get_nodeid ());
-
- if (!canonical_path.has_value ())
- rust_unreachable ();
- path = canonical_path.value ();
- }
- else
- {
- path
- = mappings
- .lookup_canonical_path (struct_decl.get_mappings ().get_nodeid ())
- .value ();
- }
+ CanonicalPath path
+ = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ());
RustIdent ident{path, struct_decl.get_locus ()};
@@ -337,7 +309,8 @@ TypeCheckItem::visit (HIR::Enum &enum_decl)
auto lifetime_pin = context->push_clean_lifetime_resolver ();
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (enum_decl.has_generics ())
- resolve_generic_params (enum_decl.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Enum, enum_decl.get_locus (),
+ enum_decl.get_generic_params (), substitutions);
// Process #[repr(X)] attribute, if any
const AST::AttrVec &attrs = enum_decl.get_outer_attrs ();
@@ -367,26 +340,14 @@ TypeCheckItem::visit (HIR::Enum &enum_decl)
}
}
- // get the path
- tl::optional<CanonicalPath> canonical_path;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path = nr_ctx.types.to_canonical_path (
- enum_decl.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = mappings.lookup_canonical_path (
- enum_decl.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path.has_value ());
+ // get the path
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (enum_decl.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, enum_decl.get_locus ()};
+ RustIdent ident{canonical_path, enum_decl.get_locus ()};
// multi variant ADT
auto *type
@@ -409,7 +370,8 @@ TypeCheckItem::visit (HIR::Union &union_decl)
auto lifetime_pin = context->push_clean_lifetime_resolver ();
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (union_decl.has_generics ())
- resolve_generic_params (union_decl.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Union, union_decl.get_locus (),
+ union_decl.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : union_decl.get_where_clause ().get_items ())
@@ -431,26 +393,14 @@ TypeCheckItem::visit (HIR::Union &union_decl)
ty_variant->get_field_type ());
}
- // get the path
- tl::optional<CanonicalPath> canonical_path;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path = nr_ctx.types.to_canonical_path (
- union_decl.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = mappings.lookup_canonical_path (
- union_decl.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path.has_value ());
+ // get the path
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (union_decl.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, union_decl.get_locus ()};
+ RustIdent ident{canonical_path, union_decl.get_locus ()};
// there is only a single variant
std::vector<TyTy::VariantDef *> variants;
@@ -569,8 +519,9 @@ TypeCheckItem::visit (HIR::Function &function)
auto lifetime_pin = context->push_clean_lifetime_resolver ();
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (function.has_generics ())
- resolve_generic_params (function.get_generic_params (),
- substitutions); // TODO resolve constraints
+ resolve_generic_params (HIR::Item::ItemKind::Function,
+ function.get_locus (),
+ function.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : function.get_where_clause ().get_items ())
@@ -607,24 +558,11 @@ TypeCheckItem::visit (HIR::Function &function)
TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty));
}
- auto path = CanonicalPath::create_empty ();
-
- // FIXME: HACK: ARTHUR: Disgusting
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- auto canonical_path = nr_ctx.values.to_canonical_path (
- function.get_mappings ().get_nodeid ());
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- path = canonical_path.value ();
- }
- else
- {
- path = mappings
- .lookup_canonical_path (function.get_mappings ().get_nodeid ())
- .value ();
- }
+ CanonicalPath path
+ = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ());
RustIdent ident{path, function.get_locus ()};
@@ -745,13 +683,33 @@ TypeCheckItem::visit (HIR::ExternBlock &extern_block)
}
}
+void
+TypeCheckItem::visit (HIR::ExternCrate &extern_crate)
+{
+ if (extern_crate.references_self ())
+ return;
+
+ auto &mappings = Analysis::Mappings::get ();
+ CrateNum num
+ = mappings.lookup_crate_name (extern_crate.get_referenced_crate ())
+ .value ();
+ HIR::Crate &crate = mappings.get_hir_crate (num);
+
+ CrateNum saved_crate_num = mappings.get_current_crate ();
+ mappings.set_current_crate (num);
+ for (auto &item : crate.get_items ())
+ TypeCheckItem::Resolve (*item);
+ mappings.set_current_crate (saved_crate_num);
+}
+
std::pair<std::vector<TyTy::SubstitutionParamMapping>, TyTy::RegionConstraints>
TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
bool &failure_flag)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (impl_block.has_generics ())
- resolve_generic_params (impl_block.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Impl, impl_block.get_locus (),
+ impl_block.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : impl_block.get_where_clause ().get_items ())
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index 56832e7..414694b 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -51,9 +51,9 @@ public:
void visit (HIR::ImplBlock &impl_block) override;
void visit (HIR::ExternBlock &extern_block) override;
void visit (HIR::Trait &trait_block) override;
+ void visit (HIR::ExternCrate &extern_crate) override;
// nothing to do
- void visit (HIR::ExternCrate &) override {}
void visit (HIR::UseDeclaration &) override {}
protected:
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 5662da5..cc5c412 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -157,20 +157,11 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
bool fully_resolved = expr.get_segments ().size () <= 1;
if (fully_resolved)
{
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
- Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
+ auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
- nr_ctx.map_usage (Resolver2_0::Usage (
- expr.get_mappings ().get_nodeid ()),
- Resolver2_0::Definition (root_resolved_node_id));
- }
- else
- {
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- root_resolved_node_id);
- }
+ nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
+ Resolver2_0::Definition (root_resolved_node_id));
return;
}
@@ -264,24 +255,16 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
bool is_root = *offset == 0;
NodeId ast_node_id = seg.get_mappings ().get_nodeid ();
- // then lookup the reference_node_id
- NodeId ref_node_id = UNKNOWN_NODEID;
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (flag_name_resolution_2_0)
+ // lookup the reference_node_id
+ NodeId ref_node_id;
+ if (auto res = nr_ctx.lookup (ast_node_id))
{
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- // assign the ref_node_id if we've found something
- nr_ctx.lookup (ast_node_id).map ([&ref_node_id] (NodeId resolved) {
- ref_node_id = resolved;
- });
+ ref_node_id = *res;
}
- else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
- resolver->lookup_resolved_type (ast_node_id, &ref_node_id);
-
- // ref_node_id is the NodeId that the segments refers to.
- if (ref_node_id == UNKNOWN_NODEID)
+ else
{
if (root_tyty != nullptr && *offset > 0)
{
@@ -561,33 +544,12 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
}
rust_assert (resolved_node_id != UNKNOWN_NODEID);
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
- Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
- nr_ctx.map_usage (Resolver2_0::Usage (expr_mappings.get_nodeid ()),
- Resolver2_0::Definition (resolved_node_id));
- }
- // name scope first
- else if (resolver->get_name_scope ().decl_was_declared_here (
- resolved_node_id))
- {
- resolver->insert_resolved_name (expr_mappings.get_nodeid (),
- resolved_node_id);
- }
- // check the type scope
- else if (resolver->get_type_scope ().decl_was_declared_here (
- resolved_node_id))
- {
- resolver->insert_resolved_type (expr_mappings.get_nodeid (),
- resolved_node_id);
- }
- else
- {
- resolver->insert_resolved_misc (expr_mappings.get_nodeid (),
- resolved_node_id);
- }
+ auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
+
+ nr_ctx.map_usage (Resolver2_0::Usage (expr_mappings.get_nodeid ()),
+ Resolver2_0::Definition (resolved_node_id));
infered = tyseg;
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index bd13f7a..be926fc 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -22,9 +22,6 @@
#include "rust-type-util.h"
#include "rust-immutable-name-resolution-context.h"
-// for flag_name_resolution_2_0
-#include "options.h"
-
namespace Rust {
namespace Resolver {
@@ -54,23 +51,13 @@ TypeCheckPattern::visit (HIR::PathInExpression &pattern)
NodeId ref_node_id = UNKNOWN_NODEID;
bool maybe_item = false;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (auto id = nr_ctx.lookup (pattern.get_mappings ().get_nodeid ()))
- {
- ref_node_id = *id;
- maybe_item = true;
- }
- }
- else
+ if (auto id = nr_ctx.lookup (pattern.get_mappings ().get_nodeid ()))
{
- maybe_item |= resolver->lookup_resolved_name (
- pattern.get_mappings ().get_nodeid (), &ref_node_id);
- maybe_item |= resolver->lookup_resolved_type (
- pattern.get_mappings ().get_nodeid (), &ref_node_id);
+ ref_node_id = *id;
+ maybe_item = true;
}
bool path_is_const_item = false;
@@ -213,13 +200,15 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
auto &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case HIR::TupleStructItems::RANGED: {
+ case HIR::TupleStructItems::RANGED:
+ {
// TODO
rust_unreachable ();
}
break;
- case HIR::TupleStructItems::MULTIPLE: {
+ case HIR::TupleStructItems::MULTIPLE:
+ {
HIR::TupleStructItemsNoRange &items_no_range
= static_cast<HIR::TupleStructItemsNoRange &> (items);
@@ -333,13 +322,15 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
{
switch (field->get_item_type ())
{
- case HIR::StructPatternField::ItemType::TUPLE_PAT: {
+ case HIR::StructPatternField::ItemType::TUPLE_PAT:
+ {
// TODO
rust_unreachable ();
}
break;
- case HIR::StructPatternField::ItemType::IDENT_PAT: {
+ case HIR::StructPatternField::ItemType::IDENT_PAT:
+ {
HIR::StructPatternFieldIdentPat &ident
= static_cast<HIR::StructPatternFieldIdentPat &> (*field);
@@ -358,7 +349,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
}
break;
- case HIR::StructPatternField::ItemType::IDENT: {
+ case HIR::StructPatternField::ItemType::IDENT:
+ {
HIR::StructPatternFieldIdent &ident
= static_cast<HIR::StructPatternFieldIdent &> (*field);
@@ -397,7 +389,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
case HIR::StructPatternField::ItemType::IDENT:
case HIR::StructPatternField::ItemType::IDENT_PAT:
break;
- default: {
+ default:
+ {
auto first_elem
= struct_pattern_elems.get_struct_pattern_fields ()
.at (0)
@@ -457,25 +450,27 @@ void
TypeCheckPattern::visit (HIR::TuplePattern &pattern)
{
std::unique_ptr<HIR::TuplePatternItems> items;
+
+ // Check whether parent is tuple
+ auto resolved_parent = parent->destructure ();
+ if (resolved_parent->get_kind () != TyTy::TUPLE)
+ {
+ rust_error_at (pattern.get_locus (), "expected %s, found tuple",
+ parent->as_string ().c_str ());
+ return;
+ }
+ TyTy::TupleType &par = *static_cast<TyTy::TupleType *> (resolved_parent);
+
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::ItemType::MULTIPLE: {
+ case HIR::TuplePatternItems::ItemType::MULTIPLE:
+ {
auto &ref = static_cast<HIR::TuplePatternItemsMultiple &> (
pattern.get_items ());
- auto resolved_parent = parent->destructure ();
- if (resolved_parent->get_kind () != TyTy::TUPLE)
- {
- rust_error_at (pattern.get_locus (), "expected %s, found tuple",
- parent->as_string ().c_str ());
- break;
- }
-
const auto &patterns = ref.get_patterns ();
size_t nitems_to_resolve = patterns.size ();
- TyTy::TupleType &par
- = *static_cast<TyTy::TupleType *> (resolved_parent);
if (patterns.size () != par.get_fields ().size ())
{
emit_pattern_size_error (pattern, par.get_fields ().size (),
@@ -498,12 +493,55 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern)
}
break;
- case HIR::TuplePatternItems::ItemType::RANGED: {
- // HIR::TuplePatternItemsRanged &ref
- // = *static_cast<HIR::TuplePatternItemsRanged *> (
- // pattern.get_items ().get ());
- // TODO
- rust_unreachable ();
+ case HIR::TuplePatternItems::ItemType::RANGED:
+ {
+ HIR::TuplePatternItemsRanged &ref
+ = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
+
+ const auto &lower = ref.get_lower_patterns ();
+ const auto &upper = ref.get_upper_patterns ();
+ size_t min_size_required = lower.size () + upper.size ();
+
+ // Ensure that size of lower and upper patterns <= parent size
+ if (min_size_required > par.get_fields ().size ())
+ {
+ emit_pattern_size_error (pattern, par.get_fields ().size (),
+ min_size_required);
+ // TODO attempt to continue to do typechecking even after wrong size
+ break;
+ }
+
+ // Resolve lower patterns
+ std::vector<TyTy::TyVar> pattern_elems;
+ for (size_t i = 0; i < lower.size (); i++)
+ {
+ auto &p = lower[i];
+ TyTy::BaseType *par_type = par.get_field (i);
+
+ TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
+ pattern_elems.push_back (TyTy::TyVar (elem->get_ref ()));
+ }
+
+ // Pad pattern_elems until needing to resolve upper patterns
+ size_t rest_end = par.get_fields ().size () - upper.size ();
+ for (size_t i = lower.size (); i < rest_end; i++)
+ {
+ TyTy::BaseType *par_type = par.get_field (i);
+ pattern_elems.push_back (TyTy::TyVar (par_type->get_ref ()));
+ }
+
+ // Resolve upper patterns
+ for (size_t i = 0; i < upper.size (); i++)
+ {
+ auto &p = upper[i];
+ TyTy::BaseType *par_type = par.get_field (rest_end + i);
+
+ TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
+ pattern_elems.push_back (TyTy::TyVar (elem->get_ref ()));
+ }
+
+ infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (),
+ pattern.get_locus (), pattern_elems);
}
break;
}
@@ -512,8 +550,18 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern)
void
TypeCheckPattern::visit (HIR::LiteralPattern &pattern)
{
- infered = resolve_literal (pattern.get_mappings (), pattern.get_literal (),
- pattern.get_locus ());
+ TyTy::BaseType *resolved
+ = resolve_literal (pattern.get_mappings (), pattern.get_literal (),
+ pattern.get_locus ());
+ if (resolved->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ infered = resolved;
+ return;
+ }
+
+ infered = unify_site (pattern.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (parent),
+ TyTy::TyWithLocation (resolved), pattern.get_locus ());
}
void
@@ -538,6 +586,11 @@ TypeCheckPattern::visit (HIR::RangePattern &pattern)
void
TypeCheckPattern::visit (HIR::IdentifierPattern &pattern)
{
+ if (pattern.has_subpattern ())
+ {
+ TypeCheckPattern::Resolve (pattern.get_subpattern (), parent);
+ }
+
if (!pattern.get_is_ref ())
{
infered = parent;
@@ -580,8 +633,72 @@ TypeCheckPattern::visit (HIR::ReferencePattern &pattern)
void
TypeCheckPattern::visit (HIR::SlicePattern &pattern)
{
- rust_sorry_at (pattern.get_locus (),
- "type checking qualified path patterns not supported");
+ auto resolved_parent = parent->destructure ();
+ TyTy::BaseType *parent_element_ty = nullptr;
+ switch (resolved_parent->get_kind ())
+ {
+ case TyTy::ARRAY:
+ {
+ auto &array_ty_ty = static_cast<TyTy::ArrayType &> (*parent);
+ parent_element_ty = array_ty_ty.get_element_type ();
+ auto capacity = array_ty_ty.get_capacity ();
+ tree cap = capacity->get_value ();
+ if (error_operand_p (cap))
+ {
+ rust_error_at (parent->get_locus (),
+ "capacity of array %qs is not known at compile time",
+ array_ty_ty.get_name ().c_str ());
+ break;
+ }
+ auto cap_wi = wi::to_wide (cap).to_uhwi ();
+ if (cap_wi != pattern.get_items ().size ())
+ {
+ rust_error_at (pattern.get_locus (), ErrorCode::E0527,
+ "pattern requires %lu elements but array has %lu",
+ (unsigned long) pattern.get_items ().size (),
+ (unsigned long) cap_wi);
+ break;
+ }
+ break;
+ }
+ case TyTy::SLICE:
+ {
+ auto &slice_ty_ty = static_cast<TyTy::SliceType &> (*parent);
+ parent_element_ty = slice_ty_ty.get_element_type ();
+ break;
+ }
+ case TyTy::REF:
+ {
+ auto &ref_ty_ty = static_cast<TyTy::ReferenceType &> (*parent);
+ const TyTy::SliceType *slice = nullptr;
+ if (!ref_ty_ty.is_dyn_slice_type (&slice))
+ {
+ rust_error_at (pattern.get_locus (), "expected %s, found slice",
+ parent->as_string ().c_str ());
+ return;
+ }
+ parent_element_ty = slice->get_element_type ();
+ break;
+ }
+ default:
+ {
+ rust_error_at (pattern.get_locus (), "expected %s, found slice",
+ parent->as_string ().c_str ());
+ return;
+ }
+ }
+
+ rust_assert (parent_element_ty != nullptr);
+ // infered inherits array/slice typing from parent
+ infered = parent->clone ();
+ infered->set_ref (pattern.get_mappings ().get_hirid ());
+
+ // Type check every item in the SlicePattern against parent's element ty
+ // TODO update this after adding support for RestPattern in SlicePattern
+ for (const auto &item : pattern.get_items ())
+ {
+ TypeCheckPattern::Resolve (*item, parent_element_ty);
+ }
}
void
@@ -608,7 +725,8 @@ TypeCheckPattern::typecheck_range_pattern_bound (
TyTy::BaseType *resolved_bound = nullptr;
switch (bound.get_bound_type ())
{
- case HIR::RangePatternBound::RangePatternBoundType::LITERAL: {
+ case HIR::RangePatternBound::RangePatternBoundType::LITERAL:
+ {
auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound);
HIR::Literal lit = ref.get_literal ();
@@ -617,14 +735,16 @@ TypeCheckPattern::typecheck_range_pattern_bound (
}
break;
- case HIR::RangePatternBound::RangePatternBoundType::PATH: {
+ case HIR::RangePatternBound::RangePatternBoundType::PATH:
+ {
auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound);
resolved_bound = TypeCheckExpr::Resolve (ref.get_path ());
}
break;
- case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ case HIR::RangePatternBound::RangePatternBoundType::QUALPATH:
+ {
auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound);
resolved_bound = TypeCheckExpr::Resolve (ref.get_qualified_path ());
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
index 4e53856..87141af 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
@@ -60,6 +60,12 @@ void
TypeCheckStmt::visit (HIR::ConstantItem &constant)
{
TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
+ if (!constant.has_expr ())
+ {
+ infered = type;
+ return;
+ }
+
TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
infered = coercion_site (
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
index df1636a..4ef8348 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
@@ -329,8 +329,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
repeat_location.add_range (prev_field_locus);
rust_error_at (repeat_location, ErrorCode::E0062,
- "field %qs specified more than once",
- field_name.c_str ());
+ "field %qs specified more than once", field_name.c_str ());
return false;
}
@@ -363,7 +362,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
if (!ok)
{
rust_error_at (field.get_locus (), "unknown field");
- return true;
+ return false;
}
auto it = adtFieldIndexToField.find (field_index);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index 6919093..78037bd 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -29,6 +29,7 @@
#include "rust-substitution-mapper.h"
#include "rust-type-util.h"
#include "rust-system.h"
+#include "rust-compile-base.h"
namespace Rust {
namespace Resolver {
@@ -335,19 +336,13 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
seg->get_lang_item ());
else
{
- // FIXME: HACK: ARTHUR: Remove this
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ()
- .resolver ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- // assign the ref_node_id if we've found something
- nr_ctx.lookup (ast_node_id)
- .map (
- [&ref_node_id] (NodeId resolved) { ref_node_id = resolved; });
- }
- else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
- resolver->lookup_resolved_type (ast_node_id, &ref_node_id);
+ // assign the ref_node_id if we've found something
+ nr_ctx.lookup (ast_node_id).map ([&ref_node_id] (NodeId resolved) {
+ ref_node_id = resolved;
+ });
}
// ref_node_id is the NodeId that the segments refers to.
@@ -549,8 +544,7 @@ TypeCheckType::resolve_segments (
bool selfResolveOk = false;
if (first_segment && tySegIsBigSelf
- && context->block_context ().is_in_context ()
- && context->block_context ().peek ().is_impl_block ())
+ && context->block_context ().is_in_context ())
{
TypeCheckBlockContextItem ctx = context->block_context ().peek ();
TyTy::BaseType *lookup = nullptr;
@@ -695,6 +689,7 @@ TypeCheckType::visit (HIR::ParenthesisedType &type)
void
TypeCheckType::visit (HIR::ArrayType &type)
{
+ auto element_type = TypeCheckType::Resolve (type.get_element_type ());
auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr ());
if (capacity_type->get_kind () == TyTy::TypeKind::ERROR)
return;
@@ -704,16 +699,38 @@ TypeCheckType::visit (HIR::ArrayType &type)
rust_assert (ok);
context->insert_type (type.get_size_expr ().get_mappings (), expected_ty);
- unify_site (type.get_size_expr ().get_mappings ().get_hirid (),
- TyTy::TyWithLocation (expected_ty),
- TyTy::TyWithLocation (capacity_type,
- type.get_size_expr ().get_locus ()),
- type.get_size_expr ().get_locus ());
+ TyTy::ConstType *const_type = nullptr;
+ if (capacity_type->get_kind () == TyTy::TypeKind::CONST)
+ {
+ const_type = static_cast<TyTy::ConstType *> (capacity_type);
- TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ());
- translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (),
- type.get_locus (), type.get_size_expr (),
- TyTy::TyVar (base->get_ref ()));
+ unify_site (type.get_size_expr ().get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (expected_ty),
+ TyTy::TyWithLocation (const_type->get_ty (),
+ type.get_size_expr ().get_locus ()),
+ type.get_size_expr ().get_locus ());
+ }
+ else
+ {
+ HirId size_id = type.get_size_expr ().get_mappings ().get_hirid ();
+ unify_site (size_id, TyTy::TyWithLocation (expected_ty),
+ TyTy::TyWithLocation (capacity_type,
+ type.get_size_expr ().get_locus ()),
+ type.get_size_expr ().get_locus ());
+
+ auto ctx = Compile::Context::get ();
+ tree capacity_expr = Compile::HIRCompileBase::query_compile_const_expr (
+ ctx, capacity_type, type.get_size_expr ());
+
+ const_type = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "",
+ expected_ty, capacity_expr, {},
+ type.get_size_expr ().get_locus (),
+ size_id, size_id);
+ }
+
+ translated
+ = new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (),
+ const_type, TyTy::TyVar (element_type->get_ref ()));
}
void
@@ -850,10 +867,9 @@ TypeResolveGenericParam::visit (HIR::TypeParam &param)
if (param.has_type ())
TypeCheckType::Resolve (param.get_type ());
- resolved
- = new TyTy::ParamType (param.get_type_representation ().as_string (),
- param.get_locus (),
- param.get_mappings ().get_hirid (), param, {});
+ resolved = new TyTy::ParamType (param.get_type_representation ().as_string (),
+ param.get_locus (),
+ param.get_mappings ().get_hirid (), {});
if (resolve_trait_bounds)
apply_trait_bounds (param, resolved);
@@ -872,7 +888,7 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam &param,
HirId implicit_id = mappings.get_next_hir_id ();
TyTy::ParamType *p
= new TyTy::ParamType (param.get_type_representation ().as_string (),
- param.get_locus (), implicit_id, param,
+ param.get_locus (), implicit_id,
{} /*empty specified bounds*/);
context->insert_implicit_type (implicit_id, p);
@@ -908,7 +924,8 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam &param,
{
switch (bound->get_bound_type ())
{
- case HIR::TypeParamBound::BoundType::TRAITBOUND: {
+ case HIR::TypeParamBound::BoundType::TRAITBOUND:
+ {
HIR::TraitBound &b = static_cast<HIR::TraitBound &> (*bound);
TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
@@ -920,7 +937,8 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam &param,
{
switch (predicate.get_polarity ())
{
- case BoundPolarity::AntiBound: {
+ case BoundPolarity::AntiBound:
+ {
bool found = predicates.find (predicate.get_id ())
!= predicates.end ();
if (found)
@@ -937,7 +955,8 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam &param,
}
break;
- default: {
+ default:
+ {
if (predicates.find (predicate.get_id ())
== predicates.end ())
{
@@ -1033,7 +1052,8 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item)
{
switch (bound->get_bound_type ())
{
- case HIR::TypeParamBound::BoundType::TRAITBOUND: {
+ case HIR::TypeParamBound::BoundType::TRAITBOUND:
+ {
auto *b = static_cast<HIR::TraitBound *> (bound.get ());
TyTy::TypeBoundPredicate predicate
@@ -1042,7 +1062,8 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item)
specified_bounds.push_back (std::move (predicate));
}
break;
- case HIR::TypeParamBound::BoundType::LIFETIME: {
+ case HIR::TypeParamBound::BoundType::LIFETIME:
+ {
if (auto param = binding->try_as<TyTy::ParamType> ())
{
auto *b = static_cast<HIR::Lifetime *> (bound.get ());
@@ -1071,23 +1092,15 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item)
// then lookup the reference_node_id
NodeId ref_node_id = UNKNOWN_NODEID;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (auto id = nr_ctx.lookup (ast_node_id))
- ref_node_id = *id;
- }
- else
- {
- NodeId id = UNKNOWN_NODEID;
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (resolver->lookup_resolved_type (ast_node_id, &id))
- ref_node_id = id;
+ if (auto id = nr_ctx.lookup (ast_node_id))
+ {
+ ref_node_id = *id;
}
-
- if (ref_node_id == UNKNOWN_NODEID)
+ else
{
// FIXME
rust_error_at (UNDEF_LOCATION,
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index fbaf323..aba4ab5 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -26,11 +26,7 @@
#include "rust-hir-type-check-struct-field.h"
#include "rust-immutable-name-resolution-context.h"
-// for flag_name_resolution_2_0
-#include "options.h"
-
-extern bool
-saw_errors (void);
+extern bool saw_errors (void);
namespace Rust {
namespace Resolver {
@@ -165,7 +161,9 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
HIR::TraitFunctionDecl &function = fn.get_decl ();
if (function.has_generics ())
{
- TypeCheckBase::ResolveGenericParams (function.get_generic_params (),
+ TypeCheckBase::ResolveGenericParams (HIR::Item::ItemKind::Function,
+ fn.get_locus (),
+ function.get_generic_params (),
substitutions, false /*is_foreign*/,
ABI::RUST);
}
@@ -231,7 +229,8 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
break;
case HIR::SelfParam::IMM_REF:
- case HIR::SelfParam::MUT_REF: {
+ case HIR::SelfParam::MUT_REF:
+ {
auto mutability
= self_param.get_self_kind () == HIR::SelfParam::IMM_REF
? Mutability::Imm
@@ -275,26 +274,13 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty));
}
- auto &mappings = Analysis::Mappings::get ();
-
- tl::optional<CanonicalPath> canonical_path;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.values.to_canonical_path (fn.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path
- = mappings.lookup_canonical_path (fn.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path);
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (fn.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, fn.get_locus ()};
+ RustIdent ident{canonical_path, fn.get_locus ()};
auto resolved = new TyTy::FnType (
fn.get_mappings ().get_hirid (), fn.get_mappings ().get_defid (),
function.get_function_name ().as_string (), ident,
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index 18a65fe..e5a6e9e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -20,6 +20,7 @@
#define RUST_HIR_TYPE_CHECK
#include "rust-hir-map.h"
+#include "rust-mapping-common.h"
#include "rust-tyty.h"
#include "rust-hir-trait-reference.h"
#include "rust-stacked-contexts.h"
@@ -157,6 +158,39 @@ public:
WARN_UNUSED_RESULT Lifetime next () { return Lifetime (interner_index++); }
};
+struct DeferredOpOverload
+{
+ HirId expr_id;
+ LangItem::Kind lang_item_type;
+ HIR::PathIdentSegment specified_segment;
+ TyTy::TypeBoundPredicate predicate;
+ HIR::OperatorExprMeta op;
+
+ DeferredOpOverload (HirId expr_id, LangItem::Kind lang_item_type,
+ HIR::PathIdentSegment specified_segment,
+ TyTy::TypeBoundPredicate &predicate,
+ HIR::OperatorExprMeta op)
+ : expr_id (expr_id), lang_item_type (lang_item_type),
+ specified_segment (specified_segment), predicate (predicate), op (op)
+ {}
+
+ DeferredOpOverload (const struct DeferredOpOverload &other)
+ : expr_id (other.expr_id), lang_item_type (other.lang_item_type),
+ specified_segment (other.specified_segment), predicate (other.predicate),
+ op (other.op)
+ {}
+
+ DeferredOpOverload &operator= (struct DeferredOpOverload const &other)
+ {
+ expr_id = other.expr_id;
+ lang_item_type = other.lang_item_type;
+ specified_segment = other.specified_segment;
+ op = other.op;
+
+ return *this;
+ }
+};
+
class TypeCheckContext
{
public:
@@ -215,10 +249,10 @@ public:
bool lookup_associated_type_mapping (HirId id, HirId *mapping);
void insert_associated_impl_mapping (HirId trait_id,
- const TyTy::BaseType *impl_type,
+ TyTy::BaseType *impl_type,
HirId impl_id);
bool lookup_associated_impl_mapping_for_self (HirId trait_id,
- const TyTy::BaseType *self,
+ TyTy::BaseType *self,
HirId *mapping);
void insert_autoderef_mappings (HirId id,
@@ -237,6 +271,13 @@ public:
void insert_operator_overload (HirId id, TyTy::FnType *call_site);
bool lookup_operator_overload (HirId id, TyTy::FnType **call);
+ void insert_deferred_operator_overload (DeferredOpOverload deferred);
+ bool lookup_deferred_operator_overload (HirId id,
+ DeferredOpOverload *deferred);
+
+ void iterate_deferred_operator_overloads (
+ std::function<bool (HirId, DeferredOpOverload &)> cb);
+
void insert_unconstrained_check_marker (HirId id, bool status);
bool have_checked_for_unconstrained (HirId id, bool *result);
@@ -263,13 +304,16 @@ public:
WARN_UNUSED_RESULT std::vector<TyTy::Region>
regions_from_generic_args (const HIR::GenericArgs &args) const;
- void compute_inference_variables (bool error);
+ void compute_inference_variables (bool emit_error);
TyTy::VarianceAnalysis::CrateCtx &get_variance_analysis_ctx ();
private:
TypeCheckContext ();
+ bool compute_infer_var (HirId id, TyTy::BaseType *ty, bool emit_error);
+ bool compute_ambigious_op_overload (HirId id, DeferredOpOverload &op);
+
std::map<NodeId, HirId> node_id_refs;
std::map<HirId, TyTy::BaseType *> resolved;
std::vector<std::unique_ptr<TyTy::BaseType>> builtins;
@@ -281,7 +325,7 @@ private:
std::map<HirId, AssociatedImplTrait> associated_impl_traits;
// trait-id -> list of < self-tyty:impl-id>
- std::map<HirId, std::vector<std::pair<const TyTy::BaseType *, HirId>>>
+ std::map<HirId, std::vector<std::pair<TyTy::BaseType *, HirId>>>
associated_traits_to_impls;
std::map<HirId, HirId> associated_type_mappings;
@@ -306,6 +350,9 @@ private:
std::set<HirId> querys_in_progress;
std::set<DefId> trait_queries_in_progress;
+ // deferred operator overload
+ std::map<HirId, DeferredOpOverload> deferred_operator_overloads;
+
// variance analysis
TyTy::VarianceAnalysis::CrateCtx variance_analysis_ctx;
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc
index f0bd1f8..c5b823e 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.cc
+++ b/gcc/rust/typecheck/rust-substitution-mapper.cc
@@ -268,6 +268,12 @@ SubstMapperInternal::visit (TyTy::ParamType &type)
}
void
+SubstMapperInternal::visit (TyTy::ConstType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
SubstMapperInternal::visit (TyTy::PlaceholderType &type)
{
rust_assert (type.can_resolve ());
@@ -374,7 +380,7 @@ SubstMapperInternal::visit (TyTy::DynamicObjectType &type)
void
SubstMapperInternal::visit (TyTy::OpaqueType &type)
{
- resolved = type.handle_substitions (mappings);
+ resolved = type.clone ();
}
// SubstMapperFromExisting
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index 32ab71c..2389d83 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -61,6 +61,7 @@ public:
void visit (TyTy::ReferenceType &) override { rust_unreachable (); }
void visit (TyTy::PointerType &) override { rust_unreachable (); }
void visit (TyTy::ParamType &) override { rust_unreachable (); }
+ void visit (TyTy::ConstType &) override { rust_unreachable (); }
void visit (TyTy::StrType &) override { rust_unreachable (); }
void visit (TyTy::NeverType &) override { rust_unreachable (); }
void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); }
@@ -92,6 +93,7 @@ public:
void visit (TyTy::ReferenceType &type) override;
void visit (TyTy::PointerType &type) override;
void visit (TyTy::ParamType &type) override;
+ void visit (TyTy::ConstType &type) override;
void visit (TyTy::PlaceholderType &type) override;
void visit (TyTy::ProjectionType &type) override;
void visit (TyTy::ClosureType &type) override;
@@ -145,6 +147,7 @@ public:
void visit (TyTy::ReferenceType &) override { rust_unreachable (); }
void visit (TyTy::PointerType &) override { rust_unreachable (); }
void visit (TyTy::ParamType &) override { rust_unreachable (); }
+ void visit (TyTy::ConstType &) override { rust_unreachable (); }
void visit (TyTy::StrType &) override { rust_unreachable (); }
void visit (TyTy::NeverType &) override { rust_unreachable (); }
void visit (TyTy::PlaceholderType &) override { rust_unreachable (); }
@@ -185,12 +188,13 @@ public:
void visit (const TyTy::ReferenceType &) override {}
void visit (const TyTy::PointerType &) override {}
void visit (const TyTy::ParamType &) override {}
+ void visit (const TyTy::ConstType &) override {}
void visit (const TyTy::StrType &) override {}
void visit (const TyTy::NeverType &) override {}
void visit (const TyTy::PlaceholderType &) override {}
void visit (const TyTy::ProjectionType &) override {}
void visit (const TyTy::DynamicObjectType &) override {}
- void visit (const TyTy::OpaqueType &type) override {}
+ void visit (const TyTy::OpaqueType &) override {}
private:
GetUsedSubstArgs ();
diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc
index c6c5b4b..2d66166 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -24,6 +24,7 @@
#include "rust-hir-type-check.h"
#include "rust-hir-type-check-type.h"
#include "rust-casts.h"
+#include "rust-mapping-common.h"
#include "rust-unify.h"
#include "rust-coercion.h"
#include "rust-hir-type-bounds.h"
@@ -37,15 +38,14 @@ bool
query_type (HirId reference, TyTy::BaseType **result)
{
auto &mappings = Analysis::Mappings::get ();
- auto &resolver = *Resolver::get ();
TypeCheckContext *context = TypeCheckContext::get ();
- if (context->query_in_progress (reference))
- return false;
-
if (context->lookup_type (reference, result))
return true;
+ if (context->query_in_progress (reference))
+ return false;
+
context->insert_query (reference);
std::pair<HIR::Enum *, HIR::EnumItem *> enum_candidiate
@@ -103,18 +103,13 @@ query_type (HirId reference, TyTy::BaseType **result)
NodeId ref_node_id = UNKNOWN_NODEID;
NodeId ast_node_id = ty.get_mappings ().get_nodeid ();
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ()
- .resolver ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- // assign the ref_node_id if we've found something
- nr_ctx.lookup (ast_node_id)
- .map (
- [&ref_node_id] (NodeId resolved) { ref_node_id = resolved; });
- }
- else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
- resolver.lookup_resolved_type (ast_node_id, &ref_node_id);
+ // assign the ref_node_id if we've found something
+ nr_ctx.lookup (ast_node_id).map ([&ref_node_id] (NodeId resolved) {
+ ref_node_id = resolved;
+ });
if (ref_node_id != UNKNOWN_NODEID)
{
@@ -192,10 +187,12 @@ unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
TyTy::BaseType *expected = lhs.get_ty ();
TyTy::BaseType *expr = rhs.get_ty ();
- rust_debug (
- "unify_site_and commit %s infer %s id={%u} expected={%s} expr={%s}",
- commit_if_ok ? "true" : "false", implicit_infer_vars ? "true" : "false", id,
- expected->debug_str ().c_str (), expr->debug_str ().c_str ());
+ rust_debug_loc (
+ unify_locus,
+ "begin unify_site_and commit %s infer %s id={%u} expected={%s} expr={%s}",
+ commit_if_ok ? "true" : "false", implicit_infer_vars ? "true" : "false",
+ id == UNKNOWN_HIRID ? 0 : id, expected->debug_str ().c_str (),
+ expr->debug_str ().c_str ());
std::vector<UnifyRules::CommitSite> commits;
std::vector<UnifyRules::InferenceSite> infers;
@@ -203,6 +200,15 @@ unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
= UnifyRules::Resolve (lhs, rhs, unify_locus, false /*commit inline*/,
emit_errors, implicit_infer_vars, commits, infers);
bool ok = result->get_kind () != TyTy::TypeKind::ERROR;
+
+ rust_debug_loc (unify_locus,
+ "unify_site_and done ok=%s commit %s infer %s id={%u} "
+ "expected={%s} expr={%s}",
+ ok ? "true" : "false", commit_if_ok ? "true" : "false",
+ implicit_infer_vars ? "true" : "false",
+ id == UNKNOWN_HIRID ? 0 : id, expected->debug_str ().c_str (),
+ expr->debug_str ().c_str ());
+
if (ok && commit_if_ok)
{
for (auto &c : commits)
diff --git a/gcc/rust/typecheck/rust-type-util.h b/gcc/rust/typecheck/rust-type-util.h
index 03874a4..dd97f1e 100644
--- a/gcc/rust/typecheck/rust-type-util.h
+++ b/gcc/rust/typecheck/rust-type-util.h
@@ -25,33 +25,30 @@
namespace Rust {
namespace Resolver {
-bool
-query_type (HirId reference, TyTy::BaseType **result);
+bool query_type (HirId reference, TyTy::BaseType **result);
-bool
-types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- location_t unify_locus, bool emit_errors);
+bool types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+ location_t unify_locus, bool emit_errors);
-TyTy::BaseType *
-unify_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- location_t unify_locus);
+TyTy::BaseType *unify_site (HirId id, TyTy::TyWithLocation lhs,
+ TyTy::TyWithLocation rhs, location_t unify_locus);
-TyTy::BaseType *
-unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- location_t unify_locus, bool emit_errors, bool commit_if_ok,
- bool implicit_infer_vars, bool cleanup);
+TyTy::BaseType *unify_site_and (HirId id, TyTy::TyWithLocation lhs,
+ TyTy::TyWithLocation rhs,
+ location_t unify_locus, bool emit_errors,
+ bool commit_if_ok, bool implicit_infer_vars,
+ bool cleanup);
-TyTy::BaseType *
-coercion_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- location_t coercion_locus);
+TyTy::BaseType *coercion_site (HirId id, TyTy::TyWithLocation lhs,
+ TyTy::TyWithLocation rhs,
+ location_t coercion_locus);
-TyTy::BaseType *
-try_coercion (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- location_t coercion_locus);
+TyTy::BaseType *try_coercion (HirId id, TyTy::TyWithLocation lhs,
+ TyTy::TyWithLocation rhs,
+ location_t coercion_locus);
-TyTy::BaseType *
-cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to,
- location_t cast_locus);
+TyTy::BaseType *cast_site (HirId id, TyTy::TyWithLocation from,
+ TyTy::TyWithLocation to, location_t cast_locus);
AssociatedImplTrait *
lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound,
diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc
index 9112b99..c74a920 100644
--- a/gcc/rust/typecheck/rust-typecheck-context.cc
+++ b/gcc/rust/typecheck/rust-typecheck-context.cc
@@ -18,6 +18,7 @@
#include "rust-hir-type-check.h"
#include "rust-type-util.h"
+#include "rust-hir-type-check-expr.h"
namespace Rust {
namespace Resolver {
@@ -299,8 +300,9 @@ TypeCheckContext::lookup_associated_type_mapping (HirId id, HirId *mapping)
}
void
-TypeCheckContext::insert_associated_impl_mapping (
- HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id)
+TypeCheckContext::insert_associated_impl_mapping (HirId trait_id,
+ TyTy::BaseType *impl_type,
+ HirId impl_id)
{
auto it = associated_traits_to_impls.find (trait_id);
if (it == associated_traits_to_impls.end ())
@@ -312,8 +314,9 @@ TypeCheckContext::insert_associated_impl_mapping (
}
bool
-TypeCheckContext::lookup_associated_impl_mapping_for_self (
- HirId trait_id, const TyTy::BaseType *self, HirId *mapping)
+TypeCheckContext::lookup_associated_impl_mapping_for_self (HirId trait_id,
+ TyTy::BaseType *self,
+ HirId *mapping)
{
auto it = associated_traits_to_impls.find (trait_id);
if (it == associated_traits_to_impls.end ())
@@ -321,7 +324,9 @@ TypeCheckContext::lookup_associated_impl_mapping_for_self (
for (auto &item : it->second)
{
- if (item.first->can_eq (self, false))
+ if (types_compatable (TyTy::TyWithLocation (item.first),
+ TyTy::TyWithLocation (self), UNKNOWN_LOCATION,
+ false))
{
*mapping = item.second;
return true;
@@ -409,6 +414,38 @@ TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call)
}
void
+TypeCheckContext::insert_deferred_operator_overload (
+ DeferredOpOverload deferred)
+{
+ HirId expr_id = deferred.expr_id;
+ deferred_operator_overloads.emplace (std::make_pair (expr_id, deferred));
+}
+
+bool
+TypeCheckContext::lookup_deferred_operator_overload (
+ HirId id, DeferredOpOverload *deferred)
+{
+ auto it = deferred_operator_overloads.find (id);
+ if (it == deferred_operator_overloads.end ())
+ return false;
+
+ *deferred = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::iterate_deferred_operator_overloads (
+ std::function<bool (HirId, DeferredOpOverload &)> cb)
+{
+ for (auto it = deferred_operator_overloads.begin ();
+ it != deferred_operator_overloads.end (); it++)
+ {
+ if (!cb (it->first, it->second))
+ return;
+ }
+}
+
+void
TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status)
{
unconstrained[id] = status;
@@ -574,44 +611,77 @@ TypeCheckContext::regions_from_generic_args (const HIR::GenericArgs &args) const
return regions;
}
+bool
+TypeCheckContext::compute_ambigious_op_overload (HirId id,
+ DeferredOpOverload &op)
+{
+ rust_debug ("attempting resolution of op overload: %s",
+ op.predicate.as_string ().c_str ());
+
+ TyTy::BaseType *lhs = nullptr;
+ bool ok = lookup_type (op.op.get_lvalue_mappings ().get_hirid (), &lhs);
+ rust_assert (ok);
+
+ TyTy::BaseType *rhs = nullptr;
+ if (op.op.has_rvalue_mappings ())
+ {
+ bool ok = lookup_type (op.op.get_rvalue_mappings ().get_hirid (), &rhs);
+ rust_assert (ok);
+ }
+
+ TypeCheckExpr::ResolveOpOverload (op.lang_item_type, op.op, lhs, rhs,
+ op.specified_segment);
+
+ return true;
+}
+
void
-TypeCheckContext::compute_inference_variables (bool error)
+TypeCheckContext::compute_inference_variables (bool emit_error)
{
- auto &mappings = Analysis::Mappings::get ();
+ iterate_deferred_operator_overloads (
+ [&] (HirId id, DeferredOpOverload &op) mutable -> bool {
+ return compute_ambigious_op_overload (id, op);
+ });
- // default inference variables if possible
iterate ([&] (HirId id, TyTy::BaseType *ty) mutable -> bool {
- // nothing to do
- if (ty->get_kind () != TyTy::TypeKind::INFER)
- return true;
+ return compute_infer_var (id, ty, emit_error);
+ });
+}
- TyTy::InferType *infer_var = static_cast<TyTy::InferType *> (ty);
- TyTy::BaseType *default_type;
-
- rust_debug_loc (mappings.lookup_location (id),
- "trying to default infer-var: %s",
- infer_var->as_string ().c_str ());
- bool ok = infer_var->default_type (&default_type);
- if (!ok)
- {
- if (error)
- rust_error_at (mappings.lookup_location (id), ErrorCode::E0282,
- "type annotations needed");
- return true;
- }
-
- auto result
- = unify_site (id, TyTy::TyWithLocation (ty),
- TyTy::TyWithLocation (default_type), UNDEF_LOCATION);
- rust_assert (result);
- rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
- result->set_ref (id);
- insert_type (Analysis::NodeMapping (mappings.get_current_crate (), 0, id,
- UNKNOWN_LOCAL_DEFID),
- result);
+bool
+TypeCheckContext::compute_infer_var (HirId id, TyTy::BaseType *ty,
+ bool emit_error)
+{
+ auto &mappings = Analysis::Mappings::get ();
+ // nothing to do
+ if (ty->get_kind () != TyTy::TypeKind::INFER)
return true;
- });
+
+ TyTy::InferType *infer_var = static_cast<TyTy::InferType *> (ty);
+ TyTy::BaseType *default_type;
+
+ rust_debug_loc (mappings.lookup_location (id),
+ "trying to default infer-var: %s",
+ infer_var->as_string ().c_str ());
+ bool ok = infer_var->default_type (&default_type);
+ if (!ok)
+ {
+ if (emit_error)
+ rust_error_at (mappings.lookup_location (id), ErrorCode::E0282,
+ "type annotations needed");
+ return true;
+ }
+
+ auto result
+ = unify_site (id, TyTy::TyWithLocation (ty),
+ TyTy::TyWithLocation (default_type), UNDEF_LOCATION);
+ rust_assert (result);
+ rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
+ result->set_ref (id);
+ insert_implicit_type (id, result);
+
+ return true;
}
TyTy::VarianceAnalysis::CrateCtx &
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index e028a0a..6cf9b04 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -61,6 +61,39 @@ TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver,
return false;
}
+bool
+TypeBoundsProbe::process_impl_block (
+ HirId id, HIR::ImplBlock *impl,
+ std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
+ &possible_trait_paths)
+{
+ // we are filtering for trait-impl-blocks
+ if (!impl->has_trait_ref ())
+ return true;
+
+ // can be recursive trait resolution
+ HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ());
+ if (t == nullptr)
+ return true;
+ // DefId trait_id = t->get_mappings ().get_defid ();
+ // if (context->trait_query_in_progress (trait_id))
+ // return true;
+
+ HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
+ TyTy::BaseType *impl_type = nullptr;
+ if (!query_type (impl_ty_id, &impl_type))
+ return true;
+
+ if (!receiver->can_eq (impl_type, false))
+ {
+ if (!impl_type->can_eq (receiver, false))
+ return true;
+ }
+
+ possible_trait_paths.push_back ({&impl->get_trait_ref (), impl});
+ return true;
+}
+
void
TypeBoundsProbe::scan ()
{
@@ -68,31 +101,7 @@ TypeBoundsProbe::scan ()
possible_trait_paths;
mappings.iterate_impl_blocks (
[&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
- // we are filtering for trait-impl-blocks
- if (!impl->has_trait_ref ())
- return true;
-
- // can be recursive trait resolution
- HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ());
- if (t == nullptr)
- return true;
- DefId trait_id = t->get_mappings ().get_defid ();
- if (context->trait_query_in_progress (trait_id))
- return true;
-
- HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
- TyTy::BaseType *impl_type = nullptr;
- if (!query_type (impl_ty_id, &impl_type))
- return true;
-
- if (!receiver->can_eq (impl_type, false))
- {
- if (!impl_type->can_eq (receiver, false))
- return true;
- }
-
- possible_trait_paths.push_back ({&impl->get_trait_ref (), impl});
- return true;
+ return process_impl_block (id, impl, possible_trait_paths);
});
for (auto &path : possible_trait_paths)
@@ -105,7 +114,7 @@ TypeBoundsProbe::scan ()
}
// marker traits...
- assemble_sized_builtin ();
+ assemble_marker_builtins ();
// add auto trait bounds
for (auto *auto_trait : mappings.get_auto_traits ())
@@ -113,7 +122,7 @@ TypeBoundsProbe::scan ()
}
void
-TypeBoundsProbe::assemble_sized_builtin ()
+TypeBoundsProbe::assemble_marker_builtins ()
{
const TyTy::BaseType *raw = receiver->destructure ();
@@ -132,7 +141,6 @@ TypeBoundsProbe::assemble_sized_builtin ()
case TyTy::POINTER:
case TyTy::PARAM:
case TyTy::FNDEF:
- case TyTy::FNPTR:
case TyTy::BOOL:
case TyTy::CHAR:
case TyTy::INT:
@@ -140,7 +148,6 @@ TypeBoundsProbe::assemble_sized_builtin ()
case TyTy::FLOAT:
case TyTy::USIZE:
case TyTy::ISIZE:
- case TyTy::CLOSURE:
case TyTy::INFER:
case TyTy::NEVER:
case TyTy::PLACEHOLDER:
@@ -149,6 +156,14 @@ TypeBoundsProbe::assemble_sized_builtin ()
assemble_builtin_candidate (LangItem::Kind::SIZED);
break;
+ case TyTy::FNPTR:
+ case TyTy::CLOSURE:
+ assemble_builtin_candidate (LangItem::Kind::SIZED);
+ assemble_builtin_candidate (LangItem::Kind::FN_ONCE);
+ assemble_builtin_candidate (LangItem::Kind::FN);
+ assemble_builtin_candidate (LangItem::Kind::FN_MUT);
+ break;
+
// FIXME str and slice need to be moved and test cases updated
case TyTy::SLICE:
case TyTy::STR:
@@ -158,6 +173,7 @@ TypeBoundsProbe::assemble_sized_builtin ()
assemble_builtin_candidate (LangItem::Kind::SIZED);
break;
+ case TyTy::CONST:
case TyTy::DYNAMIC:
case TyTy::ERROR:
break;
@@ -206,7 +222,7 @@ TyTy::TypeBoundPredicate
TypeCheckBase::get_predicate_from_bound (
HIR::TypePath &type_path,
tl::optional<std::reference_wrapper<HIR::Type>> associated_self,
- BoundPolarity polarity, bool is_qualified_type_path)
+ BoundPolarity polarity, bool is_qualified_type_path, bool is_super_trait)
{
TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error ();
bool already_resolved
@@ -226,7 +242,8 @@ TypeCheckBase::get_predicate_from_bound (
auto &final_seg = type_path.get_final_segment ();
switch (final_seg.get_type ())
{
- case HIR::TypePathSegment::SegmentType::GENERIC: {
+ case HIR::TypePathSegment::SegmentType::GENERIC:
+ {
auto &final_generic_seg
= static_cast<HIR::TypePathSegmentGeneric &> (final_seg);
if (final_generic_seg.has_generic_args ())
@@ -251,7 +268,8 @@ TypeCheckBase::get_predicate_from_bound (
}
break;
- case HIR::TypePathSegment::SegmentType::FUNCTION: {
+ case HIR::TypePathSegment::SegmentType::FUNCTION:
+ {
auto &final_function_seg
= static_cast<HIR::TypePathSegmentFunction &> (final_seg);
auto &fn = final_function_seg.get_function_path ();
@@ -327,7 +345,8 @@ TypeCheckBase::get_predicate_from_bound (
if (!args.is_empty () || predicate.requires_generic_args ())
{
// this is applying generic arguments to a trait reference
- predicate.apply_generic_arguments (&args, associated_self.has_value ());
+ predicate.apply_generic_arguments (&args, associated_self.has_value (),
+ is_super_trait);
}
context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (),
@@ -508,7 +527,8 @@ TypeBoundPredicate::is_object_safe (bool emit_error, location_t locus) const
void
TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
- bool has_associated_self)
+ bool has_associated_self,
+ bool is_super_trait)
{
rust_assert (!substitutions.empty ());
if (has_associated_self)
@@ -529,23 +549,26 @@ TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
Resolver::TypeCheckContext::get ()->regions_from_generic_args (
*generic_args));
- apply_argument_mappings (args);
+ apply_argument_mappings (args, is_super_trait);
}
void
TypeBoundPredicate::apply_argument_mappings (
- SubstitutionArgumentMappings &arguments)
+ SubstitutionArgumentMappings &arguments, bool is_super_trait)
{
used_arguments = arguments;
error_flag |= used_arguments.is_error ();
auto &subst_mappings = used_arguments;
+
+ bool substs_need_bounds_check = !is_super_trait;
for (auto &sub : get_substs ())
{
SubstitutionArg arg = SubstitutionArg::error ();
bool ok
= subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
if (ok && arg.get_tyty () != nullptr)
- sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ());
+ sub.fill_param_ty (subst_mappings, subst_mappings.get_locus (),
+ substs_need_bounds_check);
}
// associated argument mappings
@@ -566,7 +589,7 @@ TypeBoundPredicate::apply_argument_mappings (
auto adjusted
= super_trait.adjust_mappings_for_this (used_arguments,
true /*trait mode*/);
- super_trait.apply_argument_mappings (adjusted);
+ super_trait.apply_argument_mappings (adjusted, is_super_trait);
}
}
@@ -699,7 +722,7 @@ TypeBoundPredicate::handle_substitions (
if (sub.get_param_ty () == nullptr)
continue;
- ParamType *p = sub.get_param_ty ();
+ auto p = sub.get_param_ty ();
BaseType *r = p->resolve ();
BaseType *s = Resolver::SubstMapperInternal::Resolve (r, subst_mappings);
@@ -746,16 +769,34 @@ size_t
TypeBoundPredicate::get_num_associated_bindings () const
{
size_t count = 0;
+
+ get_trait_hierachy ([&count] (const Resolver::TraitReference &ref) {
+ for (const auto &trait_item : ref.get_trait_items ())
+ {
+ bool is_associated_type
+ = trait_item.get_trait_item_type ()
+ == Resolver::TraitItemReference::TraitItemType::TYPE;
+ if (is_associated_type)
+ count++;
+ }
+ });
+
+ return count;
+}
+
+void
+TypeBoundPredicate::get_trait_hierachy (
+ std::function<void (const Resolver::TraitReference &)> callback) const
+{
auto trait_ref = get ();
- for (const auto &trait_item : trait_ref->get_trait_items ())
+ callback (*trait_ref);
+
+ for (auto &super : super_traits)
{
- bool is_associated_type
- = trait_item.get_trait_item_type ()
- == Resolver::TraitItemReference::TraitItemType::TYPE;
- if (is_associated_type)
- count++;
+ const auto &super_trait_ref = *super.get ();
+ callback (super_trait_ref);
+ super.get_trait_hierachy (callback);
}
- return count;
}
TypeBoundPredicateItem
@@ -808,21 +849,19 @@ TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const
// then match the generics applied
for (size_t i = 0; i < get_num_substitutions (); i++)
{
- const SubstitutionParamMapping &a = substitutions.at (i);
- const SubstitutionParamMapping &b = other.substitutions.at (i);
+ SubstitutionParamMapping a = substitutions.at (i);
+ SubstitutionParamMapping b = other.substitutions.at (i);
- const ParamType *ap = a.get_param_ty ();
- const ParamType *bp = b.get_param_ty ();
+ auto ap = a.get_param_ty ();
+ auto bp = b.get_param_ty ();
- const BaseType *apd = ap->destructure ();
- const BaseType *bpd = bp->destructure ();
+ BaseType *apd = ap->destructure ();
+ BaseType *bpd = bp->destructure ();
- // FIXME use the unify_and infer inteface or try coerce
- if (!apd->can_eq (bpd, false /*emit_errors*/))
- {
- if (!bpd->can_eq (apd, false /*emit_errors*/))
- return false;
- }
+ if (!Resolver::types_compatable (TyTy::TyWithLocation (apd),
+ TyTy::TyWithLocation (bpd),
+ UNKNOWN_LOCATION, false))
+ return false;
}
return true;
diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc
index 2e0830e..63bb1ff 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -171,7 +171,8 @@ TypeCheckCallExpr::visit (FnType &type)
{
case TyTy::TypeKind::ERROR:
return;
- case TyTy::TypeKind::INT: {
+ case TyTy::TypeKind::INT:
+ {
auto &int_ty
= static_cast<TyTy::IntType &> (*argument_expr_tyty);
if ((int_ty.get_int_kind () == TyTy::IntType::IntKind::I8)
@@ -186,7 +187,8 @@ TypeCheckCallExpr::visit (FnType &type)
}
break;
}
- case TyTy::TypeKind::UINT: {
+ case TyTy::TypeKind::UINT:
+ {
auto &uint_ty
= static_cast<TyTy::UintType &> (*argument_expr_tyty);
if ((uint_ty.get_uint_kind () == TyTy::UintType::UintKind::U8)
@@ -202,7 +204,8 @@ TypeCheckCallExpr::visit (FnType &type)
}
break;
}
- case TyTy::TypeKind::FLOAT: {
+ case TyTy::TypeKind::FLOAT:
+ {
if (static_cast<TyTy::FloatType &> (*argument_expr_tyty)
.get_float_kind ()
== TyTy::FloatType::FloatKind::F32)
@@ -216,14 +219,16 @@ TypeCheckCallExpr::visit (FnType &type)
}
break;
}
- case TyTy::TypeKind::BOOL: {
+ case TyTy::TypeKind::BOOL:
+ {
rich_location richloc (line_table, arg_locus);
richloc.add_fixit_replace ("cast the value to c_int: as c_int");
rust_error_at (arg_locus, ErrorCode::E0617,
"expected %<c_int%> variadic argument");
return;
}
- case TyTy::TypeKind::FNDEF: {
+ case TyTy::TypeKind::FNDEF:
+ {
rust_error_at (
arg_locus, ErrorCode::E0617,
"unexpected function definition type as variadic "
@@ -246,7 +251,7 @@ TypeCheckCallExpr::visit (FnType &type)
}
type.monomorphize ();
- resolved = type.get_return_type ()->clone ();
+ resolved = type.get_return_type ()->monomorphized_clone ();
}
void
diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h
index c42fdcd..9e4aab5 100644
--- a/gcc/rust/typecheck/rust-tyty-call.h
+++ b/gcc/rust/typecheck/rust-tyty-call.h
@@ -62,6 +62,7 @@ public:
void visit (DynamicObjectType &) override { rust_unreachable (); }
void visit (ClosureType &type) override { rust_unreachable (); }
void visit (OpaqueType &type) override { rust_unreachable (); }
+ void visit (ConstType &type) override { rust_unreachable (); }
// tuple-structs
void visit (ADTType &type) override;
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index c897c13..c22dfdd 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -447,6 +447,22 @@ public:
}
}
+ virtual void visit (const ConstType &type) override
+ {
+ ok = false;
+ if (emit_error_flag)
+ {
+ location_t ref_locus = mappings.lookup_location (type.get_ref ());
+ location_t base_locus
+ = mappings.lookup_location (get_base ()->get_ref ());
+ rich_location r (line_table, ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "expected [%s] got [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+ }
+
protected:
BaseCmp (const BaseType *base, bool emit_errors)
: mappings (Analysis::Mappings::get ()),
@@ -621,7 +637,8 @@ public:
ok = true;
return;
- case InferType::InferTypeKind::INTEGRAL: {
+ case InferType::InferTypeKind::INTEGRAL:
+ {
if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
{
ok = true;
@@ -635,7 +652,8 @@ public:
}
break;
- case InferType::InferTypeKind::FLOAT: {
+ case InferType::InferTypeKind::FLOAT:
+ {
if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
{
ok = true;
@@ -1604,6 +1622,23 @@ private:
const OpaqueType *base;
};
+class ConstCmp : public BaseCmp
+{
+ using Rust::TyTy::BaseCmp::visit;
+
+public:
+ ConstCmp (const ConstType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
+ {}
+
+ // TODO
+
+private:
+ const BaseType *get_base () const override { return base; }
+
+ const ConstType *base;
+};
+
} // namespace TyTy
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index bdb6474..817910b 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -18,18 +18,22 @@
#include "rust-tyty-subst.h"
+#include "rust-hir-generic-param.h"
#include "rust-system.h"
#include "rust-tyty.h"
#include "rust-hir-type-check.h"
#include "rust-substitution-mapper.h"
#include "rust-hir-type-check-type.h"
+#include "rust-hir-type-check-expr.h"
+#include "rust-compile-base.h"
#include "rust-type-util.h"
+#include "tree.h"
namespace Rust {
namespace TyTy {
-SubstitutionParamMapping::SubstitutionParamMapping (HIR::TypeParam &generic,
- ParamType *param)
+SubstitutionParamMapping::SubstitutionParamMapping (HIR::GenericParam &generic,
+ BaseGeneric *param)
: generic (generic), param (param)
{}
@@ -54,30 +58,42 @@ SubstitutionParamMapping::clone () const
static_cast<ParamType *> (param->clone ()));
}
-ParamType *
+BaseGeneric *
SubstitutionParamMapping::get_param_ty ()
{
return param;
}
-const ParamType *
+const BaseGeneric *
SubstitutionParamMapping::get_param_ty () const
{
return param;
}
-HIR::TypeParam &
+HIR::GenericParam &
SubstitutionParamMapping::get_generic_param ()
{
return generic;
}
+const HIR::GenericParam &
+SubstitutionParamMapping::get_generic_param () const
+{
+ return generic;
+}
+
bool
SubstitutionParamMapping::needs_substitution () const
{
return !(get_param_ty ()->is_concrete ());
}
+Identifier
+SubstitutionParamMapping::get_type_representation () const
+{
+ return param->get_symbol ();
+}
+
location_t
SubstitutionParamMapping::get_param_locus () const
{
@@ -87,13 +103,35 @@ SubstitutionParamMapping::get_param_locus () const
bool
SubstitutionParamMapping::param_has_default_ty () const
{
- return generic.has_type ();
+ if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
+ {
+ const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
+ return type_param.has_type ();
+ }
+
+ rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST);
+ const auto &const_param
+ = static_cast<const HIR::ConstGenericParam &> (generic);
+ return const_param.has_default_expression ();
}
BaseType *
SubstitutionParamMapping::get_default_ty () const
{
- TyVar var (generic.get_type_mappings ().get_hirid ());
+ if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
+ {
+ const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
+ TyVar var (type_param.get_type_mappings ().get_hirid ());
+ return var.get_tyty ();
+ }
+
+ rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST);
+ const auto &const_param
+ = static_cast<const HIR::ConstGenericParam &> (generic);
+ rust_assert (const_param.has_default_expression ());
+
+ const auto &expr = const_param.get_default_expression ();
+ TyVar var (expr.get_mappings ().get_hirid ());
return var.get_tyty ();
}
@@ -109,7 +147,8 @@ SubstitutionParamMapping::need_substitution () const
bool
SubstitutionParamMapping::fill_param_ty (
- SubstitutionArgumentMappings &subst_mappings, location_t locus)
+ SubstitutionArgumentMappings &subst_mappings, location_t locus,
+ bool needs_bounds_check)
{
SubstitutionArg arg = SubstitutionArg::error ();
bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
@@ -124,17 +163,21 @@ SubstitutionParamMapping::fill_param_ty (
if (type.get_kind () == TypeKind::PARAM)
{
- // delete param;
- param = static_cast<ParamType *> (type.clone ());
+ param = static_cast<BaseGeneric *> (type.clone ());
}
- else
+ else if (type.get_kind () == TyTy::TypeKind::CONST)
{
+ param = static_cast<BaseGeneric *> (type.clone ());
+ }
+ else if (param->get_kind () == TypeKind::PARAM)
+ {
+ auto &p = *static_cast<TyTy::ParamType *> (param);
+
// 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 (needs_bounds_check && !p.is_implicit_self_trait ())
{
if (!param->bounds_compatible (type, locus, true))
return false;
@@ -145,7 +188,7 @@ SubstitutionParamMapping::fill_param_ty (
bound.handle_substitions (subst_mappings);
param->set_ty_ref (type.get_ref ());
- subst_mappings.on_param_subst (*param, arg);
+ subst_mappings.on_param_subst (p, arg);
}
return true;
@@ -191,12 +234,6 @@ SubstitutionArg::operator= (const SubstitutionArg &other)
}
BaseType *
-SubstitutionArg::get_tyty ()
-{
- return argument;
-}
-
-const BaseType *
SubstitutionArg::get_tyty () const
{
return argument;
@@ -208,7 +245,7 @@ SubstitutionArg::get_param_mapping () const
return param;
}
-const ParamType *
+const BaseGeneric *
SubstitutionArg::get_param_ty () const
{
return original_param;
@@ -313,11 +350,11 @@ SubstitutionArgumentMappings::is_error () const
bool
SubstitutionArgumentMappings::get_argument_for_symbol (
- const ParamType *param_to_find, SubstitutionArg *argument) const
+ const BaseGeneric *param_to_find, SubstitutionArg *argument) const
{
for (const auto &mapping : mappings)
{
- const ParamType *p = mapping.get_param_ty ();
+ const auto *p = mapping.get_param_ty ();
if (p->get_symbol () == param_to_find->get_symbol ())
{
*argument = mapping;
@@ -618,7 +655,6 @@ SubstitutionRef::get_mappings_from_generic_args (
if (args.get_binding_args ().size () > get_num_associated_bindings ())
{
rich_location r (line_table, args.get_locus ());
-
rust_error_at (r,
"generic item takes at most %lu type binding "
"arguments but %lu were supplied",
@@ -666,11 +702,17 @@ SubstitutionRef::get_mappings_from_generic_args (
// for inherited arguments
size_t offs = used_arguments.size ();
- if (args.get_type_args ().size () + offs > substitutions.size ())
+ size_t total_arguments
+ = args.get_type_args ().size () + args.get_const_args ().size () + offs;
+ if (total_arguments > substitutions.size ())
{
rich_location r (line_table, args.get_locus ());
if (!substitutions.empty ())
- r.add_range (substitutions.front ().get_param_locus ());
+ {
+ const auto &subst = substitutions.front ();
+ const auto &generic = subst.get_generic_param ();
+ r.add_range (generic.get_locus ());
+ }
rust_error_at (
r,
@@ -680,10 +722,15 @@ SubstitutionRef::get_mappings_from_generic_args (
return SubstitutionArgumentMappings::error ();
}
- if (args.get_type_args ().size () + offs < min_required_substitutions ())
+ if (total_arguments < min_required_substitutions ())
{
rich_location r (line_table, args.get_locus ());
- r.add_range (substitutions.front ().get_param_locus ());
+ if (!substitutions.empty ())
+ {
+ const auto &subst = substitutions.front ();
+ const auto &generic = subst.get_generic_param ();
+ r.add_range (generic.get_locus ());
+ }
rust_error_at (
r, ErrorCode::E0107,
@@ -702,7 +749,91 @@ SubstitutionRef::get_mappings_from_generic_args (
return SubstitutionArgumentMappings::error ();
}
- SubstitutionArg subst_arg (&substitutions.at (offs), resolved);
+ const auto &param_mapping = substitutions.at (offs);
+ const auto &generic = param_mapping.get_generic_param ();
+ if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
+ {
+ const auto &type_param
+ = static_cast<const HIR::TypeParam &> (generic);
+ if (type_param.from_impl_trait ())
+ {
+ rich_location r (line_table, arg->get_locus ());
+ r.add_fixit_remove (arg->get_locus ());
+ rust_error_at (r, ErrorCode::E0632,
+ "cannot provide explicit generic arguments when "
+ "%<impl Trait%> is used in argument position");
+ return SubstitutionArgumentMappings::error ();
+ }
+ }
+ else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
+ {
+ if (!resolved->is<ConstType> ())
+ {
+ rich_location r (line_table, arg->get_locus ());
+ r.add_fixit_remove (arg->get_locus ());
+ rust_error_at (r, ErrorCode::E0747,
+ "type provided when a constant was expected");
+ return SubstitutionArgumentMappings::error ();
+ }
+ }
+
+ SubstitutionArg subst_arg (&param_mapping, resolved);
+ offs++;
+ mappings.push_back (std::move (subst_arg));
+ }
+
+ for (auto &arg : args.get_const_args ())
+ {
+ auto &expr = *arg.get_expression ().get ();
+ BaseType *expr_type = Resolver::TypeCheckExpr::Resolve (expr);
+ if (expr_type == nullptr || expr_type->is<ErrorType> ())
+ return SubstitutionArgumentMappings::error ();
+
+ // validate this param is really a const generic
+ const auto &param_mapping = substitutions.at (offs);
+ const auto &generic = param_mapping.get_generic_param ();
+ if (generic.get_kind () != HIR::GenericParam::GenericKind::CONST)
+ {
+ rich_location r (line_table, arg.get_locus ());
+ r.add_fixit_remove (expr.get_locus ());
+ rust_error_at (r, "invalid position for a const generic argument");
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ // get the const generic specified type
+ const auto base_generic = param_mapping.get_param_ty ();
+ rust_assert (base_generic->is<ConstType> ());
+ const auto const_param
+ = static_cast<const TyTy::ConstType *> (base_generic);
+ auto specified_type = const_param->get_ty ();
+
+ // validate this const generic is of the correct type
+ auto coereced_type
+ = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (specified_type),
+ TyTy::TyWithLocation (expr_type,
+ expr.get_locus ()),
+ arg.get_locus ());
+ if (coereced_type->is<ErrorType> ())
+ return SubstitutionArgumentMappings::error ();
+
+ // const fold it
+ auto ctx = Compile::Context::get ();
+ tree folded
+ = Compile::HIRCompileBase::query_compile_const_expr (ctx, coereced_type,
+ expr);
+
+ if (folded == error_mark_node)
+ return SubstitutionArgumentMappings::error ();
+
+ // create const type
+ auto const_value
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "",
+ coereced_type, folded, {}, expr.get_locus (),
+ expr.get_mappings ().get_hirid (),
+ expr.get_mappings ().get_hirid (), {});
+
+ SubstitutionArg subst_arg (&param_mapping, const_value);
offs++;
mappings.push_back (std::move (subst_arg));
}
@@ -754,6 +885,7 @@ SubstitutionRef::infer_substitions (location_t locus)
{
if (p.needs_substitution ())
{
+ const HIR::GenericParam &generic = p.get_generic_param ();
const std::string &symbol = p.get_param_ty ()->get_symbol ();
auto it = argument_mappings.find (symbol);
bool have_mapping = it != argument_mappings.end ();
@@ -762,12 +894,24 @@ SubstitutionRef::infer_substitions (location_t locus)
{
args.push_back (SubstitutionArg (&p, it->second));
}
- else
+ else if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
{
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 if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
+ {
+ const auto const_param = p.get_param_ty ();
+ rust_assert (const_param->is<TyTy::ConstType> ());
+ const auto &const_type
+ = *static_cast<const TyTy::ConstType *> (const_param);
+
+ TyVar infer_var
+ = TyVar::get_implicit_const_infer_var (const_type, locus);
+ args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
+ argument_mappings[symbol] = infer_var.get_tyty ();
+ }
}
else
{
@@ -905,7 +1049,7 @@ SubstitutionRef::prepare_higher_ranked_bounds ()
{
for (const auto &subst : get_substs ())
{
- const TyTy::ParamType *pty = subst.get_param_ty ();
+ const auto pty = subst.get_param_ty ();
for (const auto &bound : pty->get_specified_bounds ())
{
const auto ref = bound.get ();
@@ -919,8 +1063,7 @@ SubstitutionRef::monomorphize ()
{
for (const auto &subst : get_substs ())
{
- const TyTy::ParamType *pty = subst.get_param_ty ();
-
+ const auto pty = subst.get_param_ty ();
if (!pty->can_resolve ())
continue;
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h
index e6ed1fc..c1bc96a 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -24,12 +24,14 @@
#include "rust-hir-full-decls.h"
#include "rust-tyty-bounds.h"
#include "rust-tyty-region.h"
+#include "rust-ast.h"
#include "optional.h"
namespace Rust {
namespace TyTy {
class ParamType;
+class BaseGeneric;
struct RegionConstraints
{
@@ -44,22 +46,24 @@ class SubstitutionArgumentMappings;
class SubstitutionParamMapping
{
public:
- SubstitutionParamMapping (HIR::TypeParam &generic, ParamType *param);
+ SubstitutionParamMapping (HIR::GenericParam &generic, BaseGeneric *param);
SubstitutionParamMapping (const SubstitutionParamMapping &other);
std::string as_string () const;
bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
- location_t locus);
+ location_t locus, bool needs_bounds_check = true);
SubstitutionParamMapping clone () const;
- ParamType *get_param_ty ();
+ BaseGeneric *get_param_ty ();
+ const BaseGeneric *get_param_ty () const;
- const ParamType *get_param_ty () const;
+ HIR::GenericParam &get_generic_param ();
+ const HIR::GenericParam &get_generic_param () const;
- HIR::TypeParam &get_generic_param ();
+ Identifier get_type_representation () 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
@@ -76,8 +80,8 @@ public:
bool need_substitution () const;
private:
- HIR::TypeParam &generic;
- ParamType *param;
+ HIR::GenericParam &generic;
+ BaseGeneric *param;
};
/**
@@ -147,13 +151,11 @@ public:
SubstitutionArg &operator= (const SubstitutionArg &other);
- BaseType *get_tyty ();
-
- const BaseType *get_tyty () const;
+ BaseType *get_tyty () const;
const SubstitutionParamMapping *get_param_mapping () const;
- const ParamType *get_param_ty () const;
+ const BaseGeneric *get_param_ty () const;
static SubstitutionArg error ();
@@ -165,7 +167,7 @@ public:
private:
const SubstitutionParamMapping *param;
- const ParamType *original_param;
+ const BaseGeneric *original_param;
BaseType *argument;
};
@@ -205,7 +207,7 @@ public:
bool is_error () const;
- bool get_argument_for_symbol (const ParamType *param_to_find,
+ bool get_argument_for_symbol (const BaseGeneric *param_to_find,
SubstitutionArg *argument) const;
/** Return type parameter index for symbol */
diff --git a/gcc/rust/typecheck/rust-tyty-util.cc b/gcc/rust/typecheck/rust-tyty-util.cc
index ff210ce..4bc1723 100644
--- a/gcc/rust/typecheck/rust-tyty-util.cc
+++ b/gcc/rust/typecheck/rust-tyty-util.cc
@@ -17,6 +17,8 @@
// <http://www.gnu.org/licenses/>.
#include "rust-hir-type-check.h"
+#include "rust-mapping-common.h"
+#include "rust-system.h"
#include "rust-tyty.h"
namespace Rust {
@@ -47,14 +49,30 @@ TyVar::get_implicit_infer_var (location_t locus)
auto &mappings = Analysis::Mappings::get ();
auto context = Resolver::TypeCheckContext::get ();
- InferType *infer = new InferType (mappings.get_next_hir_id (),
- InferType::InferTypeKind::GENERAL,
- InferType::TypeHint::Default (), locus);
- context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (),
- UNKNOWN_NODEID,
- infer->get_ref (),
- UNKNOWN_LOCAL_DEFID),
- infer);
+ HirId next = mappings.get_next_hir_id ();
+ auto infer = new InferType (next, InferType::InferTypeKind::GENERAL,
+ InferType::TypeHint::Default (), locus);
+
+ context->insert_implicit_type (infer->get_ref (), infer);
+ mappings.insert_location (infer->get_ref (), locus);
+
+ return TyVar (infer->get_ref ());
+}
+
+TyVar
+TyVar::get_implicit_const_infer_var (const ConstType &const_type,
+ location_t locus)
+{
+ auto &mappings = Analysis::Mappings::get ();
+ auto context = Resolver::TypeCheckContext::get ();
+
+ HirId next = mappings.get_next_hir_id ();
+ auto infer
+ = new ConstType (ConstType::ConstKind::Infer, const_type.get_symbol (),
+ const_type.get_ty (), error_mark_node,
+ const_type.get_specified_bounds (), locus, next, next, {});
+
+ context->insert_implicit_type (infer->get_ref (), infer);
mappings.insert_location (infer->get_ref (), locus);
return TyVar (infer->get_ref ());
diff --git a/gcc/rust/typecheck/rust-tyty-util.h b/gcc/rust/typecheck/rust-tyty-util.h
index cbb3e8e..1c8fd72 100644
--- a/gcc/rust/typecheck/rust-tyty-util.h
+++ b/gcc/rust/typecheck/rust-tyty-util.h
@@ -25,6 +25,7 @@ namespace Rust {
namespace TyTy {
class BaseType;
+class ConstType;
// this is a placeholder for types that can change like inference variables
class TyVar
@@ -42,6 +43,9 @@ public:
static TyVar get_implicit_infer_var (location_t locus);
+ static TyVar get_implicit_const_infer_var (const TyTy::ConstType &const_type,
+ location_t locus);
+
static TyVar subst_covariant_var (TyTy::BaseType *orig,
TyTy::BaseType *subst);
diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
index d36afc8..deb76a7 100644
--- a/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
+++ b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
@@ -170,6 +170,8 @@ public:
}
void visit (OpaqueType &type) override {}
+
+ void visit (ConstType &type) override {}
};
/** Per crate context for generic type variance analysis. */
diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
index 38f9d52..7971ccf 100644
--- a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
+++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
@@ -199,9 +199,7 @@ GenericTyPerCrateCtx::debug_print_solutions ()
{
if (i > solution_index)
result += ", ";
- result += param.get_generic_param ()
- .get_type_representation ()
- .as_string ();
+ result += param.get_type_representation ().as_string ();
result += "=";
result += solutions[i].as_string ();
i++;
@@ -239,8 +237,7 @@ GenericTyVisitorCtx::process_type (ADTType &ty)
first_type = first_lifetime + ty.get_used_arguments ().get_regions ().size ();
for (auto &param : ty.get_substs ())
- param_names.push_back (
- param.get_generic_param ().get_type_representation ().as_string ());
+ param_names.push_back (param.get_type_representation ().as_string ());
for (const auto &variant : ty.get_variants ())
{
diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis.h b/gcc/rust/typecheck/rust-tyty-variance-analysis.h
index 9059a2f..282c6f3 100644
--- a/gcc/rust/typecheck/rust-tyty-variance-analysis.h
+++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.h
@@ -41,9 +41,10 @@ private:
std::unique_ptr<GenericTyPerCrateCtx> private_ctx;
};
-std::vector<size_t>
-query_field_regions (const ADTType *parent, size_t variant_index,
- size_t field_index, const FreeRegions &parent_regions);
+std::vector<size_t> query_field_regions (const ADTType *parent,
+ size_t variant_index,
+ size_t field_index,
+ const FreeRegions &parent_regions);
/** Variance semilattice */
class Variance
diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h
index 4f8e7856..7783075 100644
--- a/gcc/rust/typecheck/rust-tyty-visitor.h
+++ b/gcc/rust/typecheck/rust-tyty-visitor.h
@@ -45,6 +45,7 @@ public:
virtual void visit (ReferenceType &type) = 0;
virtual void visit (PointerType &type) = 0;
virtual void visit (ParamType &type) = 0;
+ virtual void visit (ConstType &type) = 0;
virtual void visit (StrType &type) = 0;
virtual void visit (NeverType &type) = 0;
virtual void visit (PlaceholderType &type) = 0;
@@ -75,6 +76,7 @@ public:
virtual void visit (const ReferenceType &type) = 0;
virtual void visit (const PointerType &type) = 0;
virtual void visit (const ParamType &type) = 0;
+ virtual void visit (const ConstType &type) = 0;
virtual void visit (const StrType &type) = 0;
virtual void visit (const NeverType &type) = 0;
virtual void visit (const PlaceholderType &type) = 0;
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index f0f4a07..db96773 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -19,6 +19,7 @@
#include "rust-tyty.h"
#include "optional.h"
+#include "rust-tyty-subst.h"
#include "rust-tyty-visitor.h"
#include "rust-hir-map.h"
#include "rust-location.h"
@@ -30,9 +31,14 @@
#include "rust-tyty-cmp.h"
#include "rust-type-util.h"
#include "rust-hir-type-bounds.h"
+#include "print-tree.h"
+#include "tree-pretty-print.h"
#include "options.h"
#include "rust-system.h"
+#include "tree.h"
+#include "fold-const.h"
+#include <string>
namespace Rust {
namespace TyTy {
@@ -114,6 +120,9 @@ TypeKindFormat::to_string (TypeKind kind)
case TypeKind::OPAQUE:
return "Opaque";
+ case TypeKind::CONST:
+ return "Const";
+
case TypeKind::ERROR:
return "ERROR";
}
@@ -223,6 +232,7 @@ BaseType::is_unit () const
case OPAQUE:
case STR:
case DYNAMIC:
+ case CONST:
case ERROR:
return false;
@@ -230,11 +240,13 @@ BaseType::is_unit () const
case NEVER:
return true;
- case TUPLE: {
+ case TUPLE:
+ {
return x->as<const TupleType> ()->num_fields () == 0;
}
- case ADT: {
+ case ADT:
+ {
auto adt = x->as<const ADTType> ();
if (adt->is_enum ())
return false;
@@ -438,11 +450,10 @@ BaseType::inherit_bounds (
}
}
-const BaseType *
-BaseType::get_root () const
+BaseType *
+BaseType::get_root ()
{
- // FIXME this needs to be it its own visitor class with a vector adjustments
- const TyTy::BaseType *root = this;
+ TyTy::BaseType *root = this;
if (const auto r = root->try_as<const ReferenceType> ())
{
@@ -546,17 +557,14 @@ BaseType::destructure () const
{
x = p->get ();
}
- // else if (auto p = x->try_as<const OpaqueType> ())
- // {
- // auto pr = p->resolve ();
-
- // rust_debug ("XXXXXX")
-
- // if (pr == x)
- // return pr;
+ else if (auto p = x->try_as<const OpaqueType> ())
+ {
+ auto pr = p->resolve ();
+ if (pr == x)
+ return pr;
- // x = pr;
- // }
+ x = pr;
+ }
else
{
return x;
@@ -575,7 +583,7 @@ BaseType::monomorphized_clone () const
{
TyVar elm = arr->get_var_element_type ().monomorphized_clone ();
return new ArrayType (arr->get_ref (), arr->get_ty_ref (), ident.locus,
- arr->get_capacity_expr (), elm,
+ arr->get_capacity (), elm,
arr->get_combined_refs ());
}
else if (auto slice = x->try_as<const SliceType> ())
@@ -824,7 +832,8 @@ BaseType::is_concrete () const
}
else if (auto arr = x->try_as<const ArrayType> ())
{
- return arr->get_element_type ()->is_concrete ();
+ return arr->get_element_type ()->is_concrete ()
+ && arr->get_capacity ()->is_concrete ();
}
else if (auto slice = x->try_as<const SliceType> ())
{
@@ -853,6 +862,10 @@ BaseType::is_concrete () const
return false;
return closure->get_result_type ().is_concrete ();
}
+ else if (auto const_type = x->try_as<const ConstType> ())
+ {
+ return const_type->get_value () != error_mark_node;
+ }
else if (x->is<InferType> () || x->is<BoolType> () || x->is<CharType> ()
|| x->is<IntType> () || x->is<UintType> () || x->is<FloatType> ()
|| x->is<USizeType> () || x->is<ISizeType> () || x->is<NeverType> ()
@@ -891,31 +904,36 @@ BaseType::has_substitutions_defined () const
case TUPLE:
case PARAM:
case PLACEHOLDER:
+ case CONST:
case OPAQUE:
return false;
- case PROJECTION: {
+ case PROJECTION:
+ {
const ProjectionType &p = *static_cast<const ProjectionType *> (x);
const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (p);
return ref.has_substitutions ();
}
break;
- case FNDEF: {
+ case FNDEF:
+ {
const FnType &fn = *static_cast<const FnType *> (x);
const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (fn);
return ref.has_substitutions ();
}
break;
- case ADT: {
+ case ADT:
+ {
const ADTType &adt = *static_cast<const ADTType *> (x);
const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (adt);
return ref.has_substitutions ();
}
break;
- case CLOSURE: {
+ case CLOSURE:
+ {
const ClosureType &closure = *static_cast<const ClosureType *> (x);
const SubstitutionRef &ref
= static_cast<const SubstitutionRef &> (closure);
@@ -953,31 +971,36 @@ BaseType::needs_generic_substitutions () const
case TUPLE:
case PARAM:
case PLACEHOLDER:
+ case CONST:
case OPAQUE:
return false;
- case PROJECTION: {
+ case PROJECTION:
+ {
const ProjectionType &p = *static_cast<const ProjectionType *> (x);
const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (p);
return ref.needs_substitution ();
}
break;
- case FNDEF: {
+ case FNDEF:
+ {
const FnType &fn = *static_cast<const FnType *> (x);
const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (fn);
return ref.needs_substitution ();
}
break;
- case ADT: {
+ case ADT:
+ {
const ADTType &adt = *static_cast<const ADTType *> (x);
const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (adt);
return ref.needs_substitution ();
}
break;
- case CLOSURE: {
+ case CLOSURE:
+ {
const ClosureType &closure = *static_cast<const ClosureType *> (x);
const SubstitutionRef &ref
= static_cast<const SubstitutionRef &> (closure);
@@ -996,28 +1019,32 @@ BaseType::get_subst_argument_mappings () const
const TyTy::BaseType *x = destructure ();
switch (x->get_kind ())
{
- case PROJECTION: {
+ case PROJECTION:
+ {
const auto &p = *static_cast<const ProjectionType *> (x);
const auto &ref = static_cast<const SubstitutionRef &> (p);
return ref.get_substitution_arguments ();
}
break;
- case FNDEF: {
+ case FNDEF:
+ {
const auto &fn = *static_cast<const FnType *> (x);
const auto &ref = static_cast<const SubstitutionRef &> (fn);
return ref.get_substitution_arguments ();
}
break;
- case ADT: {
+ case ADT:
+ {
const auto &adt = *static_cast<const ADTType *> (x);
const auto &ref = static_cast<const SubstitutionRef &> (adt);
return ref.get_substitution_arguments ();
}
break;
- case CLOSURE: {
+ case CLOSURE:
+ {
const auto &closure = *static_cast<const ClosureType *> (x);
const auto &ref = static_cast<const SubstitutionRef &> (closure);
return ref.get_substitution_arguments ();
@@ -1140,13 +1167,15 @@ InferType::default_type (BaseType **type) const
case GENERAL:
return false;
- case INTEGRAL: {
+ case INTEGRAL:
+ {
ok = context->lookup_builtin ("i32", type);
rust_assert (ok);
return ok;
}
- case FLOAT: {
+ case FLOAT:
+ {
ok = context->lookup_builtin ("f64", type);
rust_assert (ok);
return ok;
@@ -1269,7 +1298,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint)
default_hint.kind = hint.get_kind ();
break;
- case INT: {
+ case INT:
+ {
infer_kind = INTEGRAL;
default_hint.kind = hint.get_kind ();
default_hint.shint = TypeHint::SignedHint::SIGNED;
@@ -1294,7 +1324,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint)
}
break;
- case UINT: {
+ case UINT:
+ {
infer_kind = INTEGRAL;
default_hint.kind = hint.get_kind ();
default_hint.shint = TypeHint::SignedHint::UNSIGNED;
@@ -1319,7 +1350,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint)
}
break;
- case TypeKind::FLOAT: {
+ case TypeKind::FLOAT:
+ {
infer_kind = FLOAT;
default_hint.shint = TypeHint::SignedHint::SIGNED;
default_hint.kind = hint.get_kind ();
@@ -1800,11 +1832,9 @@ ADTType::is_equal (const BaseType &other) const
const SubstitutionParamMapping &a = substitutions.at (i);
const SubstitutionParamMapping &b = other2->substitutions.at (i);
- const ParamType *aa = a.get_param_ty ();
- const ParamType *bb = b.get_param_ty ();
- BaseType *aaa = aa->resolve ();
- BaseType *bbb = bb->resolve ();
- if (!aaa->is_equal (*bbb))
+ const auto &aa = a.get_param_ty ();
+ const auto &bb = b.get_param_ty ();
+ if (!aa->is_equal (*bb))
return false;
}
}
@@ -1992,7 +2022,7 @@ TupleType::get_name () const
std::string fields_buffer;
for (const TyVar &field : get_fields ())
{
- fields_buffer += field.get_tyty ()->as_string ();
+ fields_buffer += field.get_tyty ()->get_name ();
bool has_next = (i + 1) < get_fields ().size ();
fields_buffer += has_next ? ", " : "";
i++;
@@ -2129,9 +2159,8 @@ FnType::is_equal (const BaseType &other) const
const SubstitutionParamMapping &a = get_substs ().at (i);
const SubstitutionParamMapping &b = ofn.get_substs ().at (i);
- const ParamType *pa = a.get_param_ty ();
- const ParamType *pb = b.get_param_ty ();
-
+ const auto *pa = a.get_param_ty ();
+ const auto *pb = b.get_param_ty ();
if (!pa->is_equal (*pb))
return false;
}
@@ -2470,7 +2499,8 @@ ArrayType::accept_vis (TyConstVisitor &vis) const
std::string
ArrayType::as_string () const
{
- return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]";
+ return "[" + get_element_type ()->as_string () + "; " + capacity->as_string ()
+ + "]";
}
bool
@@ -2509,7 +2539,7 @@ ArrayType::get_var_element_type () const
BaseType *
ArrayType::clone () const
{
- return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity_expr,
+ return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity,
element_type, get_combined_refs ());
}
@@ -2526,6 +2556,13 @@ ArrayType::handle_substitions (SubstitutionArgumentMappings &mappings)
BaseType *concrete = Resolver::SubstMapperInternal::Resolve (base, mappings);
ref->element_type = TyVar::subst_covariant_var (base, concrete);
+ // handle capacity type
+ auto cap = ref->get_capacity ();
+ BaseType *concrete_cap
+ = Resolver::SubstMapperInternal::Resolve (cap, mappings);
+ rust_assert (concrete_cap->get_kind () == TyTy::TypeKind::CONST);
+ ref->capacity = static_cast<TyTy::ConstType *> (concrete_cap);
+
return ref;
}
@@ -3382,33 +3419,26 @@ PointerType::handle_substitions (SubstitutionArgumentMappings &mappings)
// PARAM Type
ParamType::ParamType (std::string symbol, location_t locus, HirId ref,
- HIR::GenericParam &param,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs)
- : BaseType (ref, ref, KIND,
- {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
- locus},
- specified_bounds, refs),
- is_trait_self (false), symbol (symbol), param (param)
+ : BaseGeneric (ref, ref, KIND,
+ {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+ locus},
+ specified_bounds, refs),
+ is_trait_self (false), symbol (symbol)
{}
ParamType::ParamType (bool is_trait_self, std::string symbol, location_t locus,
- HirId ref, HirId ty_ref, HIR::GenericParam &param,
+ HirId ref, HirId ty_ref,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs)
- : BaseType (ref, ty_ref, KIND,
- {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
- locus},
- specified_bounds, refs),
- is_trait_self (is_trait_self), symbol (symbol), param (param)
+ : BaseGeneric (ref, ty_ref, KIND,
+ {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+ locus},
+ specified_bounds, refs),
+ is_trait_self (is_trait_self), symbol (symbol)
{}
-HIR::GenericParam &
-ParamType::get_generic_param ()
-{
- return param;
-}
-
bool
ParamType::can_resolve () const
{
@@ -3459,7 +3489,7 @@ BaseType *
ParamType::clone () const
{
return new ParamType (is_trait_self, get_symbol (), ident.locus, get_ref (),
- get_ty_ref (), param, get_specified_bounds (),
+ get_ty_ref (), get_specified_bounds (),
get_combined_refs ());
}
@@ -3529,12 +3559,12 @@ ParamType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
ParamType *p = static_cast<ParamType *> (clone ());
subst_mappings.on_param_subst (*p, arg);
- // there are two cases one where we substitute directly to a new PARAM and
- // otherwise
- if (arg.get_tyty ()->get_kind () == TyTy::TypeKind::PARAM)
+ const BaseType *resolved = arg.get_tyty ();
+ if (resolved->get_kind () == TyTy::TypeKind::PARAM)
{
- p->set_ty_ref (arg.get_tyty ()->get_ref ());
- return p;
+ const ParamType &pp = *static_cast<const ParamType *> (resolved);
+ if (pp.can_resolve ())
+ resolved = pp.resolve ();
}
// this is the new subst that this needs to pass
@@ -3556,6 +3586,157 @@ ParamType::is_implicit_self_trait () const
return is_trait_self;
}
+// ConstType
+
+ConstType::ConstType (ConstKind kind, std::string symbol, TyTy::BaseType *ty,
+ tree value,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ location_t locus, HirId ref, HirId ty_ref,
+ std::set<HirId> refs)
+ : BaseGeneric (ref, ty_ref, KIND,
+ {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID,
+ symbol.empty () ? "<n/a>"
+ : symbol),
+ locus},
+ specified_bounds, refs),
+ const_kind (kind), ty (ty), value (value), symbol (symbol)
+{}
+
+void
+ConstType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstType::accept_vis (TyConstVisitor &vis) const
+{
+ vis.visit (*this);
+}
+
+void
+ConstType::set_value (tree v)
+{
+ value = v;
+ const_kind = ConstType::ConstKind::Value;
+}
+
+std::string
+ConstType::as_string () const
+{
+ return get_name ();
+}
+
+bool
+ConstType::can_eq (const BaseType *other, bool emit_errors) const
+{
+ ConstCmp r (this, emit_errors);
+ return r.can_eq (other);
+}
+
+BaseType *
+ConstType::clone () const
+{
+ return new ConstType (const_kind, symbol, ty, value, get_specified_bounds (),
+ ident.locus, ref, ty_ref, get_combined_refs ());
+}
+
+std::string
+ConstType::get_symbol () const
+{
+ return symbol;
+}
+
+bool
+ConstType::can_resolve () const
+{
+ return false;
+}
+
+BaseType *
+ConstType::resolve () const
+{
+ rust_unreachable ();
+ return nullptr;
+}
+
+static std::string
+generate_tree_str (tree value)
+{
+ char *buf = nullptr;
+ size_t size = 0;
+
+ FILE *stream = open_memstream (&buf, &size);
+ if (!stream)
+ return "<error>";
+
+ print_generic_stmt (stream, value, TDF_NONE);
+ fclose (stream);
+
+ std::string result = (buf ? std::string (buf, size) : "<error>");
+ free (buf);
+
+ if (!result.empty () && result.back () == '\n')
+ result.pop_back ();
+
+ return result;
+}
+
+std::string
+ConstType::get_name () const
+{
+ if (value == error_mark_node)
+ {
+ switch (get_const_kind ())
+ {
+ case Rust::TyTy::ConstType::Decl:
+ return "ConstType:<" + get_ty ()->get_name () + " " + get_symbol ()
+ + ">";
+
+ case Rust::TyTy::ConstType::Infer:
+ return "ConstType:<" + get_ty ()->get_name () + " ?" + ">";
+
+ default:
+ return "ConstType:<" + get_ty ()->get_name () + " - <error>" + ">";
+ }
+ }
+
+ return generate_tree_str (value);
+}
+
+bool
+ConstType::is_equal (const BaseType &other) const
+{
+ if (get_kind () != other.get_kind ())
+ {
+ return false;
+ }
+
+ const ConstType &rhs = static_cast<const ConstType &> (other);
+ if (!get_ty ()->is_equal (*rhs.get_ty ()))
+ return false;
+
+ tree lv = get_value ();
+ tree rv = rhs.get_value ();
+
+ return operand_equal_p (lv, rv, 0);
+}
+
+ConstType *
+ConstType::handle_substitions (SubstitutionArgumentMappings &mappings)
+{
+ SubstitutionArg arg = SubstitutionArg::error ();
+ bool found = mappings.get_argument_for_symbol (this, &arg);
+ if (found && !arg.is_error ())
+ {
+ TyTy::BaseType *subst = arg.get_tyty ();
+ rust_assert (subst->is<TyTy::ConstType> ());
+ return static_cast<TyTy::ConstType *> (subst);
+ }
+
+ return this;
+}
+
// OpaqueType
OpaqueType::OpaqueType (location_t locus, HirId ref,
@@ -3624,28 +3805,7 @@ BaseType *
OpaqueType::resolve () const
{
TyVar var (get_ty_ref ());
- BaseType *r = var.get_tyty ();
-
- while (r->get_kind () == TypeKind::OPAQUE)
- {
- OpaqueType *rr = static_cast<OpaqueType *> (r);
- if (!rr->can_resolve ())
- break;
-
- TyVar v (rr->get_ty_ref ());
- BaseType *n = v.get_tyty ();
-
- // fix infinite loop
- if (r == n)
- break;
-
- r = n;
- }
-
- if (r->get_kind () == TypeKind::OPAQUE && (r->get_ref () == r->get_ty_ref ()))
- return TyVar (r->get_ty_ref ()).get_tyty ();
-
- return r;
+ return var.get_tyty ();
}
bool
@@ -3655,41 +3815,9 @@ OpaqueType::is_equal (const BaseType &other) const
if (can_resolve () != other2.can_resolve ())
return false;
- if (can_resolve ())
- return resolve ()->can_eq (other2.resolve (), false);
-
return bounds_compatible (other, UNDEF_LOCATION, false);
}
-OpaqueType *
-OpaqueType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
-{
- // SubstitutionArg arg = SubstitutionArg::error ();
- // bool ok = subst_mappings.get_argument_for_symbol (this, &arg);
- // if (!ok || arg.is_error ())
- // return this;
-
- // OpaqueType *p = static_cast<OpaqueType *> (clone ());
- // subst_mappings.on_param_subst (*p, arg);
-
- // // there are two cases one where we substitute directly to a new PARAM and
- // // otherwise
- // if (arg.get_tyty ()->get_kind () == TyTy::TypeKind::PARAM)
- // {
- // p->set_ty_ref (arg.get_tyty ()->get_ref ());
- // return p;
- // }
-
- // // this is the new subst that this needs to pass
- // p->set_ref (mappings.get_next_hir_id ());
- // p->set_ty_ref (arg.get_tyty ()->get_ref ());
-
- // return p;
-
- rust_unreachable ();
- return nullptr;
-}
-
// StrType
StrType::StrType (HirId ref, std::set<HirId> refs)
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 1cada9a..49415ea 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -19,6 +19,7 @@
#ifndef RUST_TYTY
#define RUST_TYTY
+#include "optional.h"
#include "rust-hir-map.h"
#include "rust-common.h"
#include "rust-identifier.h"
@@ -29,6 +30,7 @@
#include "rust-tyty-region.h"
#include "rust-system.h"
#include "rust-hir.h"
+#include "tree.h"
namespace Rust {
@@ -56,6 +58,7 @@ enum TypeKind
REF,
POINTER,
PARAM,
+ CONST,
ARRAY,
SLICE,
FNDEF,
@@ -78,8 +81,7 @@ enum TypeKind
ERROR
};
-extern bool
-is_primitive_type_kind (TypeKind kind);
+extern bool is_primitive_type_kind (TypeKind kind);
class TypeKindFormat
{
@@ -165,8 +167,7 @@ public:
void debug () const;
- // FIXME this will eventually go away
- const BaseType *get_root () const;
+ BaseType *get_root ();
// This will get the monomorphized type from Params, Placeholders or
// Projections if available or error
@@ -268,8 +269,8 @@ public:
{}
WARN_UNUSED_RESULT virtual size_t get_num_params () const = 0;
- WARN_UNUSED_RESULT virtual BaseType *
- get_param_type_at (size_t index) const = 0;
+ WARN_UNUSED_RESULT virtual BaseType *get_param_type_at (size_t index) const
+ = 0;
WARN_UNUSED_RESULT virtual BaseType *get_return_type () const = 0;
};
@@ -365,18 +366,34 @@ public:
std::string get_name () const override final;
};
-class ParamType : public BaseType
+class BaseGeneric : public BaseType
+{
+public:
+ virtual std::string get_symbol () const = 0;
+
+ virtual bool can_resolve () const = 0;
+
+ virtual BaseType *resolve () const = 0;
+
+protected:
+ BaseGeneric (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs = std::set<HirId> ())
+ : BaseType (ref, ty_ref, kind, ident, specified_bounds, refs)
+ {}
+};
+
+class ParamType : public BaseGeneric
{
public:
static constexpr auto KIND = TypeKind::PARAM;
ParamType (std::string symbol, location_t locus, HirId ref,
- HIR::GenericParam &param,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs = std::set<HirId> ());
ParamType (bool is_trait_self, std::string symbol, location_t locus,
- HirId ref, HirId ty_ref, HIR::GenericParam &param,
+ HirId ref, HirId ty_ref,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs = std::set<HirId> ());
@@ -389,13 +406,11 @@ public:
BaseType *clone () const final override;
- std::string get_symbol () const;
-
- HIR::GenericParam &get_generic_param ();
+ std::string get_symbol () const override final;
- bool can_resolve () const;
+ bool can_resolve () const override final;
- BaseType *resolve () const;
+ BaseType *resolve () const override final;
std::string get_name () const override final;
@@ -409,7 +424,58 @@ public:
private:
bool is_trait_self;
std::string symbol;
- HIR::GenericParam &param;
+};
+
+class ConstType : public BaseGeneric
+{
+public:
+ static constexpr auto KIND = TypeKind::CONST;
+
+ enum ConstKind
+ {
+ Decl,
+ Value,
+ Infer,
+ Error
+ };
+
+ ConstType (ConstKind kind, std::string symbol, TyTy::BaseType *ty, tree value,
+ std::vector<TypeBoundPredicate> specified_bounds, location_t locus,
+ 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;
+
+ ConstKind get_const_kind () const { return const_kind; }
+ TyTy::BaseType *get_ty () const { return ty; }
+ tree get_value () const { return value; }
+
+ void set_value (tree value);
+
+ std::string as_string () const override;
+
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
+
+ BaseType *clone () const final override;
+
+ std::string get_symbol () const override final;
+
+ bool can_resolve () const override final;
+
+ BaseType *resolve () const override final;
+
+ std::string get_name () const override final;
+
+ bool is_equal (const BaseType &other) const override;
+
+ ConstType *handle_substitions (SubstitutionArgumentMappings &mappings);
+
+private:
+ ConstKind const_kind;
+ TyTy::BaseType *ty;
+ tree value;
+ std::string symbol;
};
class OpaqueType : public BaseType
@@ -441,8 +507,6 @@ public:
std::string get_name () const override final;
bool is_equal (const BaseType &other) const override;
-
- OpaqueType *handle_substitions (SubstitutionArgumentMappings &mappings);
};
class StructFieldType
@@ -541,14 +605,15 @@ public:
std::string get_name () const;
- // check that this predicate is object-safe see:
+ // check that this is object-safe see:
// https://doc.rust-lang.org/reference/items/traits.html#object-safety
bool is_object_safe (bool emit_error, location_t locus) const;
void apply_generic_arguments (HIR::GenericArgs *generic_args,
- bool has_associated_self);
+ bool has_associated_self, bool is_super_trait);
- void apply_argument_mappings (SubstitutionArgumentMappings &arguments);
+ void apply_argument_mappings (SubstitutionArgumentMappings &arguments,
+ bool is_super_trait);
bool contains_item (const std::string &search) const;
@@ -596,6 +661,9 @@ private:
TypeBoundPredicate (mark_is_error);
+ void get_trait_hierachy (
+ std::function<void (const Resolver::TraitReference &)> callback) const;
+
DefId reference;
location_t locus;
bool error_flag;
@@ -1156,19 +1224,18 @@ class ArrayType : public BaseType
public:
static constexpr auto KIND = TypeKind::ARRAY;
- ArrayType (HirId ref, location_t locus, HIR::Expr &capacity_expr, TyVar base,
+ ArrayType (HirId ref, location_t locus, ConstType *capacity, TyVar base,
std::set<HirId> refs = std::set<HirId> ())
: BaseType (ref, ref, TypeKind::ARRAY,
{Resolver::CanonicalPath::create_empty (), locus}, refs),
- element_type (base), capacity_expr (capacity_expr)
+ element_type (base), capacity (capacity)
{}
- ArrayType (HirId ref, HirId ty_ref, location_t locus,
- HIR::Expr &capacity_expr, TyVar base,
- std::set<HirId> refs = std::set<HirId> ())
+ ArrayType (HirId ref, HirId ty_ref, location_t locus, ConstType *capacity,
+ TyVar base, std::set<HirId> refs = std::set<HirId> ())
: BaseType (ref, ty_ref, TypeKind::ARRAY,
{Resolver::CanonicalPath::create_empty (), locus}, refs),
- element_type (base), capacity_expr (capacity_expr)
+ element_type (base), capacity (capacity)
{}
void accept_vis (TyVisitor &vis) override;
@@ -1187,15 +1254,13 @@ public:
BaseType *clone () const final override;
- HIR::Expr &get_capacity_expr () const { return capacity_expr; }
+ ConstType *get_capacity () const { return capacity; }
ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings);
private:
TyVar element_type;
- // FIXME: I dont think this should be in tyty - tyty should already be const
- // evaluated
- HIR::Expr &capacity_expr;
+ ConstType *capacity;
};
class SliceType : public BaseType
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 294b677..30ead5b 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -17,6 +17,9 @@
// <http://www.gnu.org/licenses/>.
#include "rust-unify.h"
+#include "fold-const.h"
+#include "rust-tyty.h"
+#include "tree.h"
namespace Rust {
namespace Resolver {
@@ -53,6 +56,22 @@ UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
}
TyTy::BaseType *
+UnifyRules::resolve_subtype (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs)
+{
+ TyTy::BaseType *result
+ = UnifyRules::Resolve (lhs, rhs, locus, commit_flag, emit_error, infer_flag,
+ commits, infers);
+
+ // If the recursive call resulted in an error and would have emitted an error
+ // message, disable error emission for the current level to avoid duplicate
+ // errors
+ if (result->get_kind () == TyTy::TypeKind::ERROR && emit_error)
+ emit_error = false;
+
+ return result;
+}
+
+TyTy::BaseType *
UnifyRules::get_base ()
{
return lhs.get_ty ()->destructure ();
@@ -69,7 +88,6 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other,
TyTy::BaseType *resolved)
{
TypeCheckContext &context = *TypeCheckContext::get ();
- Analysis::Mappings &mappings = Analysis::Mappings::get ();
TyTy::BaseType *b = base->destructure ();
TyTy::BaseType *o = other->destructure ();
@@ -102,13 +120,8 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other,
continue;
// if any of the types are inference variables lets fix them
- if (ref_tyty->get_kind () == TyTy::TypeKind::INFER)
- {
- auto node = Analysis::NodeMapping (mappings.get_current_crate (),
- UNKNOWN_NODEID, ref,
- UNKNOWN_LOCAL_DEFID);
- context.insert_type (node, resolved->clone ());
- }
+ if (ref_tyty->is<TyTy::InferType> ())
+ context.insert_implicit_type (ref, resolved);
}
}
}
@@ -315,6 +328,9 @@ UnifyRules::go ()
case TyTy::OPAQUE:
return expect_opaque (static_cast<TyTy::OpaqueType *> (ltype), rtype);
+ case TyTy::CONST:
+ return expect_const (static_cast<TyTy::ConstType *> (ltype), rtype);
+
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -328,30 +344,33 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ 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: {
+ 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 ();
+ return rtype;
}
break;
- case TyTy::InferType::InferTypeKind::FLOAT: {
+ case TyTy::InferType::InferTypeKind::FLOAT:
+ {
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT
|| r->get_infer_kind ()
== TyTy::InferType::InferTypeKind::GENERAL;
if (is_valid)
- return rtype->clone ();
+ return rtype;
}
break;
}
@@ -361,7 +380,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
case TyTy::INT:
case TyTy::UINT:
case TyTy::USIZE:
- case TyTy::ISIZE: {
+ case TyTy::ISIZE:
+ {
bool is_valid = (ltype->get_infer_kind ()
== TyTy::InferType::InferTypeKind::GENERAL)
|| (ltype->get_infer_kind ()
@@ -369,12 +389,13 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
if (is_valid)
{
ltype->apply_primitive_type_hint (*rtype);
- return rtype->clone ();
+ return rtype;
}
}
break;
- case TyTy::FLOAT: {
+ case TyTy::FLOAT:
+ {
bool is_valid = (ltype->get_infer_kind ()
== TyTy::InferType::InferTypeKind::GENERAL)
|| (ltype->get_infer_kind ()
@@ -382,7 +403,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
if (is_valid)
{
ltype->apply_primitive_type_hint (*rtype);
- return rtype->clone ();
+ return rtype;
}
}
break;
@@ -404,7 +425,9 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
case TyTy::PROJECTION:
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
- case TyTy::OPAQUE: {
+ case TyTy::CONST:
+ case TyTy::OPAQUE:
+ {
bool is_valid = (ltype->get_infer_kind ()
== TyTy::InferType::InferTypeKind::GENERAL);
if (is_valid)
@@ -424,7 +447,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -433,7 +457,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::ADT: {
+ case TyTy::ADT:
+ {
TyTy::ADTType &type = *static_cast<TyTy::ADTType *> (rtype);
if (ltype->get_adt_kind () != type.get_adt_kind ())
{
@@ -469,11 +494,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
TyTy::BaseType *other_field_ty = other_field->get_field_type ();
TyTy::BaseType *unified_ty
- = UnifyRules::Resolve (TyTy::TyWithLocation (this_field_ty),
- TyTy::TyWithLocation (other_field_ty),
- locus, commit_flag,
- false /* emit_error */, infer_flag,
- commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (this_field_ty),
+ TyTy::TyWithLocation (other_field_ty));
if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -495,11 +517,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
auto pa = a.get_param_ty ();
auto pb = b.get_param_ty ();
- auto res
- = UnifyRules::Resolve (TyTy::TyWithLocation (pa),
- TyTy::TyWithLocation (pb), locus,
- commit_flag, false /* emit_error */,
- infer_flag, commits, infers);
+ auto res = resolve_subtype (TyTy::TyWithLocation (pa),
+ TyTy::TyWithLocation (pb));
if (res->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -533,6 +552,7 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -544,7 +564,8 @@ UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -578,6 +599,7 @@ UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -589,7 +611,8 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -598,16 +621,15 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::REF: {
+ 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 */,
- infer_flag, commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (base_type),
+ TyTy::TyWithLocation (other_base_type));
if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -649,6 +671,7 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -660,7 +683,8 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -669,16 +693,15 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::POINTER: {
+ 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 */,
- infer_flag, commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (base_type),
+ TyTy::TyWithLocation (other_base_type));
if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -720,6 +743,7 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -731,7 +755,8 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -740,7 +765,8 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::PARAM: {
+ case TyTy::PARAM:
+ {
TyTy::ParamType &type = *static_cast<TyTy::ParamType *> (rtype);
// bool symbol_matches
// = ltype->get_symbol ().compare (type.get_symbol ()) == 0;
@@ -782,6 +808,7 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -793,7 +820,8 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -802,21 +830,32 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::ARRAY: {
+ 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*/, infer_flag, commits, infers);
-
- 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 ()));
- }
+ TyTy::BaseType *element_unify
+ = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()),
+ TyTy::TyWithLocation (type.get_element_type ()));
+
+ if (element_unify->get_kind () == TyTy::TypeKind::ERROR)
+ return new TyTy::ErrorType (0);
+
+ bool save_emit_error = emit_error;
+ emit_error = false;
+ TyTy::BaseType *capacity_unify
+ = resolve_subtype (TyTy::TyWithLocation (ltype->get_capacity ()),
+ TyTy::TyWithLocation (type.get_capacity ()));
+ emit_error = save_emit_error;
+
+ if (capacity_unify->get_kind () != TyTy::TypeKind::CONST)
+ return new TyTy::ErrorType (0);
+
+ TyTy::ConstType *capacity_type_unify
+ = static_cast<TyTy::ConstType *> (capacity_unify);
+ return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (),
+ type.get_ident ().locus,
+ capacity_type_unify,
+ TyTy::TyVar (element_unify->get_ref ()));
}
break;
@@ -842,6 +881,7 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -853,7 +893,8 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -862,12 +903,12 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::SLICE: {
+ 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*/, infer_flag, commits, infers);
+ TyTy::BaseType *element_unify
+ = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()),
+ TyTy::TyWithLocation (type.get_element_type ()));
if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
{
@@ -901,6 +942,7 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -912,7 +954,8 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -921,7 +964,8 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::FNDEF: {
+ case TyTy::FNDEF:
+ {
TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype);
if (ltype->num_params () != type.num_params ())
{
@@ -933,21 +977,17 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype)
auto a = ltype->param_at (i).get_type ();
auto b = type.param_at (i).get_type ();
- auto unified_param
- = UnifyRules::Resolve (TyTy::TyWithLocation (a),
- TyTy::TyWithLocation (b), locus,
- commit_flag, false /* emit_errors */,
- infer_flag, commits, infers);
+ auto unified_param = resolve_subtype (TyTy::TyWithLocation (a),
+ TyTy::TyWithLocation (b));
if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
}
}
- auto unified_return = UnifyRules::Resolve (
- TyTy::TyWithLocation (ltype->get_return_type ()),
- TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag,
- false /* emit_errors */, infer_flag, commits, infers);
+ auto unified_return
+ = resolve_subtype (TyTy::TyWithLocation (ltype->get_return_type ()),
+ TyTy::TyWithLocation (type.get_return_type ()));
if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -992,6 +1032,7 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1003,7 +1044,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1012,7 +1054,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::FNPTR: {
+ case TyTy::FNPTR:
+ {
TyTy::FnPtr &type = *static_cast<TyTy::FnPtr *> (rtype);
if (ltype->num_params () != type.num_params ())
{
@@ -1024,21 +1067,17 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
auto a = ltype->get_param_type_at (i);
auto b = type.get_param_type_at (i);
- auto unified_param
- = UnifyRules::Resolve (TyTy::TyWithLocation (a),
- TyTy::TyWithLocation (b), locus,
- commit_flag, false /* emit_errors */,
- infer_flag, commits, infers);
+ auto unified_param = resolve_subtype (TyTy::TyWithLocation (a),
+ TyTy::TyWithLocation (b));
if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
}
}
- auto unified_return = UnifyRules::Resolve (
- TyTy::TyWithLocation (ltype->get_return_type ()),
- TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag,
- false /* emit_errors */, infer_flag, commits, infers);
+ auto unified_return
+ = resolve_subtype (TyTy::TyWithLocation (ltype->get_return_type ()),
+ TyTy::TyWithLocation (type.get_return_type ()));
if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -1048,16 +1087,15 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::FNDEF: {
+ 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*/, infer_flag,
- commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (this_ret_type),
+ TyTy::TyWithLocation (other_ret_type));
if (unified_result->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -1074,10 +1112,45 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
auto other_param = type.param_at (i).get_type ();
auto unified_param
- = UnifyRules::Resolve (TyTy::TyWithLocation (this_param),
- TyTy::TyWithLocation (other_param), locus,
- commit_flag, false /* emit_errors */,
- infer_flag, commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (this_param),
+ TyTy::TyWithLocation (other_param));
+ if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+ }
+
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::CLOSURE:
+ {
+ TyTy::ClosureType &type = *static_cast<TyTy::ClosureType *> (rtype);
+ auto this_ret_type = ltype->get_return_type ();
+ auto other_ret_type = type.get_return_type ();
+
+ auto unified_result
+ = resolve_subtype (TyTy::TyWithLocation (this_ret_type),
+ TyTy::TyWithLocation (other_ret_type));
+ if (unified_result->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ if (ltype->num_params () != type.get_num_params ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ for (size_t i = 0; i < ltype->num_params (); i++)
+ {
+ auto this_param = ltype->get_param_type_at (i);
+ auto other_param = type.get_param_type_at (i);
+
+ auto unified_param
+ = resolve_subtype (TyTy::TyWithLocation (this_param),
+ TyTy::TyWithLocation (other_param));
if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -1107,8 +1180,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
case TyTy::PLACEHOLDER:
case TyTy::PROJECTION:
case TyTy::DYNAMIC:
- case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1120,7 +1193,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1129,7 +1203,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::TUPLE: {
+ case TyTy::TUPLE:
+ {
TyTy::TupleType &type = *static_cast<TyTy::TupleType *> (rtype);
if (ltype->num_fields () != type.num_fields ())
{
@@ -1143,10 +1218,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype)
TyTy::BaseType *fo = type.get_field (i);
TyTy::BaseType *unified_ty
- = UnifyRules::Resolve (TyTy::TyWithLocation (bo),
- TyTy::TyWithLocation (fo), locus,
- commit_flag, false /* emit_errors */,
- infer_flag, commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (bo),
+ TyTy::TyWithLocation (fo));
if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
return new TyTy::ErrorType (0);
@@ -1180,6 +1253,7 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1191,7 +1265,8 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1228,6 +1303,7 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1239,7 +1315,8 @@ UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1276,6 +1353,7 @@ UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1287,7 +1365,8 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
@@ -1300,7 +1379,8 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::INT: {
+ 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)
@@ -1331,6 +1411,7 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1342,7 +1423,8 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
@@ -1355,7 +1437,8 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::UINT: {
+ 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)
@@ -1386,6 +1469,7 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1397,7 +1481,8 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
@@ -1410,7 +1495,8 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::FLOAT: {
+ 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)
@@ -1441,6 +1527,7 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1452,7 +1539,8 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT;
@@ -1489,6 +1577,7 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1500,7 +1589,8 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT;
@@ -1537,6 +1627,7 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1548,7 +1639,8 @@ UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1569,7 +1661,8 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype,
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1607,6 +1700,7 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype,
return rtype->clone ();
gcc_fallthrough ();
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1619,7 +1713,8 @@ UnifyRules::expect_projection (TyTy::ProjectionType *ltype,
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1655,6 +1750,7 @@ UnifyRules::expect_projection (TyTy::ProjectionType *ltype,
case TyTy::NEVER:
case TyTy::PLACEHOLDER:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1666,7 +1762,8 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1675,7 +1772,8 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::DYNAMIC: {
+ case TyTy::DYNAMIC:
+ {
TyTy::DynamicObjectType &type
= *static_cast<TyTy::DynamicObjectType *> (rtype);
if (ltype->num_specified_bounds () != type.num_specified_bounds ())
@@ -1714,6 +1812,7 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype)
case TyTy::PLACEHOLDER:
case TyTy::PROJECTION:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1725,7 +1824,8 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1734,26 +1834,25 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::CLOSURE: {
+ 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 */, infer_flag, commits, infers);
+ TyTy::BaseType *args_res
+ = resolve_subtype (TyTy::TyWithLocation (&ltype->get_parameters ()),
+ TyTy::TyWithLocation (&type.get_parameters ()));
if (args_res->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
}
- TyTy::BaseType *res = UnifyRules::Resolve (
- TyTy::TyWithLocation (&ltype->get_result_type ()),
- TyTy::TyWithLocation (&type.get_result_type ()), locus, commit_flag,
- false /* emit_error */, infer_flag, commits, infers);
+ TyTy::BaseType *res
+ = resolve_subtype (TyTy::TyWithLocation (&ltype->get_result_type ()),
+ TyTy::TyWithLocation (&type.get_result_type ()));
if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -1785,6 +1884,7 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype)
case TyTy::PROJECTION:
case TyTy::DYNAMIC:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1794,58 +1894,113 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype)
TyTy::BaseType *
UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype)
{
- switch (rtype->get_kind ())
+ if (rtype->is<TyTy::OpaqueType> ())
{
- 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;
+ TyTy::OpaqueType *ro = rtype->as<TyTy::OpaqueType> ();
+ if (!ltype->is_equal (*ro))
+ return new TyTy::ErrorType (0);
- case TyTy::OPAQUE: {
- auto &type = *static_cast<TyTy::OpaqueType *> (rtype);
- if (ltype->num_specified_bounds () != type.num_specified_bounds ())
- {
- return new TyTy::ErrorType (0);
- }
+ if (ltype->can_resolve () && ro->can_resolve ())
+ {
+ auto lr = ltype->resolve ();
+ auto rr = ro->resolve ();
- if (!ltype->bounds_compatible (type, locus, true))
- {
+ auto res = resolve_subtype (TyTy::TyWithLocation (lr),
+ TyTy::TyWithLocation (rr));
+ if (res->get_kind () == TyTy::TypeKind::ERROR)
return new TyTy::ErrorType (0);
- }
+ }
+ else if (ltype->can_resolve ())
+ {
+ auto lr = ltype->resolve ();
+ ro->set_ty_ref (lr->get_ref ());
+ }
+ else if (ro->can_resolve ())
+ {
+ auto rr = ro->resolve ();
+ ltype->set_ty_ref (rr->get_ref ());
+ }
+ }
+ else if (ltype->can_resolve ())
+ {
+ auto underly = ltype->resolve ();
+ auto res = resolve_subtype (TyTy::TyWithLocation (underly),
+ TyTy::TyWithLocation (rtype));
+ if (res->get_kind () == TyTy::TypeKind::ERROR)
+ return new TyTy::ErrorType (0);
+ }
+ else
+ {
+ ltype->set_ty_ref (rtype->get_ref ());
+ }
- return ltype->clone ();
- }
- break;
+ return ltype;
+}
+
+TyTy::BaseType *
+UnifyRules::expect_const (TyTy::ConstType *ltype, TyTy::BaseType *rtype)
+{
+ if (rtype->get_kind () != TyTy::TypeKind::CONST)
+ return new TyTy::ErrorType (0);
+
+ TyTy::ConstType &lhs = *ltype;
+ TyTy::ConstType &rhs = *static_cast<TyTy::ConstType *> (rtype);
+
+ auto res = resolve_subtype (TyTy::TyWithLocation (lhs.get_ty ()),
+ TyTy::TyWithLocation (rhs.get_ty ()));
+ if (res->get_kind () == TyTy::TypeKind::ERROR)
+ return new TyTy::ErrorType (0);
+
+ tree lv = lhs.get_value ();
+ tree rv = rhs.get_value ();
+
+ if (error_operand_p (lv) && error_operand_p (rv))
+ {
+ // this is only allowed for some silly senarios like:
+ // gcc/testsuite/rust/compile/issue-const_generics_5.rs
+ if (lhs.get_const_kind () == rhs.get_const_kind ())
+ {
+ return new TyTy::ConstType (lhs.get_const_kind (), lhs.get_symbol (),
+ res, error_mark_node,
+ lhs.get_specified_bounds (),
+ lhs.get_locus (), lhs.get_ref (),
+ lhs.get_ty_ref (),
+ lhs.get_combined_refs ());
+ }
- case TyTy::CLOSURE:
- case TyTy::SLICE:
- case TyTy::PARAM:
- case TyTy::POINTER:
- case TyTy::STR:
- case TyTy::ADT:
- case TyTy::REF:
- case TyTy::ARRAY:
- case TyTy::FNDEF:
- case TyTy::FNPTR:
- case TyTy::TUPLE:
- case TyTy::BOOL:
- case TyTy::CHAR:
- case TyTy::INT:
- case TyTy::UINT:
- case TyTy::FLOAT:
- case TyTy::USIZE:
- case TyTy::ISIZE:
- case TyTy::NEVER:
- case TyTy::PLACEHOLDER:
- case TyTy::PROJECTION:
- case TyTy::DYNAMIC:
- case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
+
+ bool equal = operand_equal_p (lv, rv, 0);
+ if (equal)
+ {
+ return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value,
+ lhs.get_symbol (), res, lv,
+ lhs.get_specified_bounds (), lhs.get_locus (),
+ lhs.get_ref (), lhs.get_ty_ref (),
+ lhs.get_combined_refs ());
+ }
+
+ if (lhs.get_const_kind () == TyTy::ConstType::Infer && !error_operand_p (rv))
+ {
+ lhs.set_value (rv);
+ return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value,
+ lhs.get_symbol (), res, rv,
+ lhs.get_specified_bounds (), lhs.get_locus (),
+ lhs.get_ref (), lhs.get_ty_ref (),
+ lhs.get_combined_refs ());
+ }
+ else if (rhs.get_const_kind () == TyTy::ConstType::Infer
+ && !error_operand_p (lv))
+ {
+ rhs.set_value (lv);
+ return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value,
+ rhs.get_symbol (), res, lv,
+ rhs.get_specified_bounds (), rhs.get_locus (),
+ rhs.get_ref (), rhs.get_ty_ref (),
+ rhs.get_combined_refs ());
+ }
+
return new TyTy::ErrorType (0);
}
diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h
index 5ff3b7c..b8c9cbc 100644
--- a/gcc/rust/typecheck/rust-unify.h
+++ b/gcc/rust/typecheck/rust-unify.h
@@ -84,6 +84,7 @@ protected:
TyTy::BaseType *rtype);
TyTy::BaseType *expect_opaque (TyTy::OpaqueType *ltype,
TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_const (TyTy::ConstType *ltype, TyTy::BaseType *rtype);
private:
UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
@@ -91,6 +92,9 @@ private:
std::vector<CommitSite> &commits,
std::vector<InferenceSite> &infers);
+ TyTy::BaseType *resolve_subtype (TyTy::TyWithLocation lhs,
+ TyTy::TyWithLocation rhs);
+
void emit_type_mismatch () const;
void emit_abi_mismatch (const TyTy::FnType &expected,
const TyTy::FnType &got) const;
diff --git a/gcc/rust/util/optional.h b/gcc/rust/util/optional.h
index 2c59459..9d2cd97 100644
--- a/gcc/rust/util/optional.h
+++ b/gcc/rust/util/optional.h
@@ -1364,7 +1364,7 @@ public:
this->m_has_value = false;
}
}
-}; // namespace tl
+};
/// Compares two optional objects
template <class T, class U>
@@ -2110,7 +2110,7 @@ public:
private:
T *m_value;
-}; // namespace tl
+};
@@ -2128,4 +2128,4 @@ template <class T> struct hash<tl::optional<T>> {
};
} // namespace std
-#endif \ No newline at end of file
+#endif
diff --git a/gcc/rust/util/rust-abi.h b/gcc/rust/util/rust-abi.h
index a0180ed..357a5db 100644
--- a/gcc/rust/util/rust-abi.h
+++ b/gcc/rust/util/rust-abi.h
@@ -34,11 +34,9 @@ enum ABI
SYSV64
};
-extern Rust::ABI
-get_abi_from_string (const std::string &abi);
+extern Rust::ABI get_abi_from_string (const std::string &abi);
-extern std::string
-get_string_from_abi (Rust::ABI abi);
+extern std::string get_string_from_abi (Rust::ABI abi);
} // namespace Rust
diff --git a/gcc/rust/util/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h
index 47e6a17..367044a 100644
--- a/gcc/rust/util/rust-attribute-values.h
+++ b/gcc/rust/util/rust-attribute-values.h
@@ -85,6 +85,13 @@ public:
static constexpr auto &NON_EXHAUSTIVE = "non_exhaustive";
static constexpr auto &RUSTFMT = "rustfmt";
+
+ static constexpr auto &TEST = "test";
+
+ static constexpr auto &SIMD_TEST = "simd_test";
+
+ static constexpr auto &RUSTC_ARGS_REQUIRED_CONST
+ = "rustc_args_required_const";
};
} // namespace Values
} // namespace Rust
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index c77e99c..c846c2d 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -88,6 +88,9 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::RUSTC_LAYOUT_SCALAR_VALID_RANGE_START, CODE_GENERATION},
+ // TODO: be careful about calling functions marked with this?
+ {Attrs::RUSTC_ARGS_REQUIRED_CONST, CODE_GENERATION},
+
{Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
{Attrs::RUSTC_DIAGNOSTIC_ITEM, STATIC_ANALYSIS},
@@ -95,7 +98,10 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::FUNDAMENTAL, TYPE_CHECK},
{Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
- {Attrs::RUSTFMT, EXTERNAL}};
+ {Attrs::RUSTFMT, EXTERNAL},
+
+ {Attrs::TEST, CODE_GENERATION},
+ {Attrs::SIMD_TEST, CODE_GENERATION}};
BuiltinAttributeMappings *
BuiltinAttributeMappings::get ()
@@ -221,7 +227,8 @@ check_doc_attribute (const AST::Attribute &attribute)
break;
// FIXME: Handle them as well
- case AST::AttrInput::TOKEN_TREE: {
+ case AST::AttrInput::TOKEN_TREE:
+ {
// FIXME: This doesn't check for #[doc(alias(...))]
const auto &option = static_cast<const AST::DelimTokenTree &> (
attribute.get_attr_input ());
@@ -388,7 +395,7 @@ AttributeChecker::visit (AST::MetaItemLitExpr &)
{}
void
-AttributeChecker::visit (AST::MetaItemPathLit &)
+AttributeChecker::visit (AST::MetaItemPathExpr &)
{}
void
diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h
index 7c7a1fc..db8fe23 100644
--- a/gcc/rust/util/rust-attributes.h
+++ b/gcc/rust/util/rust-attributes.h
@@ -130,7 +130,7 @@ private:
void visit (AST::AttrInputLiteral &attr_input) override;
void visit (AST::AttrInputMacro &attr_input) override;
void visit (AST::MetaItemLitExpr &meta_item) override;
- void visit (AST::MetaItemPathLit &meta_item) override;
+ void visit (AST::MetaItemPathExpr &meta_item) override;
void visit (AST::BorrowExpr &expr) override;
void visit (AST::DereferenceExpr &expr) override;
void visit (AST::ErrorPropagationExpr &expr) override;
diff --git a/gcc/rust/util/rust-base62.h b/gcc/rust/util/rust-base62.h
index e751c95..5fd7a37 100644
--- a/gcc/rust/util/rust-base62.h
+++ b/gcc/rust/util/rust-base62.h
@@ -26,8 +26,7 @@ namespace Rust {
/**
* Get the Base62 representation of an integer
*/
-std::string
-base62_integer (uint64_t value);
+std::string base62_integer (uint64_t value);
} // namespace Rust
diff --git a/gcc/rust/util/rust-canonical-path.h b/gcc/rust/util/rust-canonical-path.h
index 4d8f954..079ae76 100644
--- a/gcc/rust/util/rust-canonical-path.h
+++ b/gcc/rust/util/rust-canonical-path.h
@@ -57,10 +57,11 @@ public:
return *this;
}
- static CanonicalPath new_seg (NodeId id, const std::string &path)
+ static CanonicalPath new_seg (NodeId id, std::string path)
{
rust_assert (!path.empty ());
- return CanonicalPath ({std::pair<NodeId, std::string> (id, path)},
+ return CanonicalPath ({std::pair<NodeId, std::string> (id,
+ std::move (path))},
UNKNOWN_CRATENUM);
}
@@ -68,14 +69,18 @@ public:
trait_impl_projection_seg (NodeId id, const CanonicalPath &trait_seg,
const CanonicalPath &impl_type_seg)
{
- return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + " as "
+ // https://doc.rust-lang.org/reference/paths.html#canonical-paths
+ // should be "<X>"?
+ return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + " as "
+ trait_seg.get () + ">");
}
static CanonicalPath inherent_impl_seg (NodeId id,
const CanonicalPath &impl_type_seg)
{
- return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + ">");
+ // https://doc.rust-lang.org/reference/paths.html#canonical-paths
+ // should be "<X as Y>"?
+ return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + ">");
}
std::string get () const
diff --git a/gcc/rust/util/rust-dir-owner.h b/gcc/rust/util/rust-dir-owner.h
index dcb45d8..fb72bb1 100644
--- a/gcc/rust/util/rust-dir-owner.h
+++ b/gcc/rust/util/rust-dir-owner.h
@@ -26,8 +26,7 @@
namespace Rust {
// extracts the owned subdirectory name from a file name
-bool
-get_file_subdir (const std::string &filename, std::string &subdir);
+bool get_file_subdir (const std::string &filename, std::string &subdir);
} // namespace Rust
diff --git a/gcc/rust/util/rust-edition.h b/gcc/rust/util/rust-edition.h
index d034ea0..532fedb 100644
--- a/gcc/rust/util/rust-edition.h
+++ b/gcc/rust/util/rust-edition.h
@@ -33,8 +33,7 @@ enum class Edition
E2021
};
-Edition
-get_rust_edition ();
+Edition get_rust_edition ();
} // namespace Rust
diff --git a/gcc/rust/util/rust-ggc.cc b/gcc/rust/util/rust-ggc.cc
new file mode 100644
index 0000000..0722af2
--- /dev/null
+++ b/gcc/rust/util/rust-ggc.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-ggc.h"
+#include "stringpool.h"
+
+namespace Rust {
+
+namespace GGC {
+
+Ident::Ident (const char *str) : inner (get_identifier (str)) {}
+
+Ident::Ident (const std::string &str)
+ : inner (get_identifier_with_length (str.c_str (), str.length ()))
+{}
+
+bool
+Ident::operator== (const std::string &other) const
+{
+ // maybe_get_identifier_with_length doesn't seem to exist
+ return maybe_get_identifier (other.c_str ()) == inner;
+}
+
+} // namespace GGC
+
+} // namespace Rust
diff --git a/gcc/rust/util/rust-ggc.h b/gcc/rust/util/rust-ggc.h
new file mode 100644
index 0000000..da28ede
--- /dev/null
+++ b/gcc/rust/util/rust-ggc.h
@@ -0,0 +1,63 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_GGC_H
+#define RUST_GGC_H
+
+#include "rust-system.h"
+#include "tree.h"
+
+namespace Rust {
+
+namespace GGC {
+
+class Ident
+{
+ tree inner;
+
+public:
+ Ident (const char *str);
+ Ident (const std::string &str);
+
+ bool operator== (const Ident &other) const { return inner == other.inner; }
+ bool operator== (const std::string &other) const;
+
+ const char *c_str () const { return IDENTIFIER_POINTER (inner); }
+ size_t size () const { return IDENTIFIER_LENGTH (inner); }
+
+ bool empty () const { return !size (); }
+
+ std::string as_string () const
+ {
+ return std::string (c_str (), c_str () + size ());
+ }
+
+ tree as_tree () const { return inner; }
+};
+
+static inline bool
+operator== (const std::string &a, const Ident &b)
+{
+ return b == a;
+}
+
+} // namespace GGC
+
+} // namespace Rust
+
+#endif // RUST_GGC_H
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index eaa640c..4629e6a 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -1148,17 +1148,19 @@ Mappings::lookup_module_children (NodeId module)
}
void
-Mappings::insert_ast_module (AST::Module *module)
+Mappings::insert_glob_container (AST::Item *container)
{
- rust_assert (modules.find (module->get_node_id ()) == modules.end ());
- modules[module->get_node_id ()] = module;
+ rust_assert (glob_containers.find (container->get_node_id ())
+ == glob_containers.end ());
+
+ glob_containers[container->get_node_id ()] = container;
}
-tl::optional<AST::Module *>
-Mappings::lookup_ast_module (NodeId id)
+tl::optional<AST::Item *>
+Mappings::lookup_glob_container (NodeId id)
{
- auto it = modules.find (id);
- if (it == modules.end ())
+ auto it = glob_containers.find (id);
+ if (it == glob_containers.end ())
return tl::nullopt;
return {it->second};
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index b523a36..c8fafa4 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -321,8 +321,8 @@ public:
void insert_visibility (NodeId id, Privacy::ModuleVisibility visibility);
tl::optional<Privacy::ModuleVisibility &> lookup_visibility (NodeId id);
- void insert_ast_module (AST::Module *);
- tl::optional<AST::Module *> lookup_ast_module (NodeId id);
+ void insert_glob_container (AST::Item *);
+ tl::optional<AST::Item *> lookup_glob_container (NodeId id);
void insert_module_child (NodeId module, NodeId child);
tl::optional<std::vector<NodeId> &> lookup_module_children (NodeId module);
@@ -436,7 +436,7 @@ private:
std::map<NodeId, std::vector<NodeId>> module_child_map;
std::map<NodeId, std::vector<Resolver::CanonicalPath>> module_child_items;
std::map<NodeId, NodeId> child_to_parent_module_map;
- std::map<NodeId, AST::Module *> modules;
+ std::map<NodeId, AST::Item *> glob_containers;
// AST mappings
std::map<NodeId, AST::Item *> ast_item_mappings;
diff --git a/gcc/rust/util/rust-punycode.h b/gcc/rust/util/rust-punycode.h
index a939f05..75260ce 100644
--- a/gcc/rust/util/rust-punycode.h
+++ b/gcc/rust/util/rust-punycode.h
@@ -27,8 +27,7 @@ namespace Rust {
/* Encode a string as punycode. Returns a string if encoding is successful.
* Returns nullopt otherwise. Note that a returned string contains only ASCII
* characters and does not start with `xn--`. */
-tl::optional<std::string>
-encode_punycode (const Utf8String &src);
+tl::optional<std::string> encode_punycode (const Utf8String &src);
} // namespace Rust
@@ -36,8 +35,7 @@ encode_punycode (const Utf8String &src);
namespace selftest {
-void
-rust_punycode_encode_test ();
+void rust_punycode_encode_test ();
} // namespace selftest
diff --git a/gcc/rust/util/rust-token-converter.cc b/gcc/rust/util/rust-token-converter.cc
index fc34adb..52172f4 100644
--- a/gcc/rust/util/rust-token-converter.cc
+++ b/gcc/rust/util/rust-token-converter.cc
@@ -202,7 +202,8 @@ convert (const std::vector<const_TokenPtr> &tokens)
case PERCENT_EQ:
case SCOPE_RESOLUTION:
case NOT_EQUAL:
- case EQUAL_EQUAL: {
+ case EQUAL_EQUAL:
+ {
auto str = token->as_string ();
auto it = str.cbegin ();
for (; it != str.cend () - 1; it++)
@@ -260,9 +261,8 @@ convert (const std::vector<const_TokenPtr> &tokens)
return trees.back ();
}
-static void
-from_tokenstream (const ProcMacro::TokenStream &ts,
- std::vector<const_TokenPtr> &result);
+static void from_tokenstream (const ProcMacro::TokenStream &ts,
+ std::vector<const_TokenPtr> &result);
/**
* Append the token corresponding to a given Ident to a vector.
diff --git a/gcc/rust/util/rust-token-converter.h b/gcc/rust/util/rust-token-converter.h
index 5405d6e..6e4af50 100644
--- a/gcc/rust/util/rust-token-converter.h
+++ b/gcc/rust/util/rust-token-converter.h
@@ -23,14 +23,11 @@
namespace Rust {
-ProcMacro::TokenStream
-convert (const std::vector<const_TokenPtr> &tokens);
+ProcMacro::TokenStream convert (const std::vector<const_TokenPtr> &tokens);
-std::vector<const_TokenPtr>
-convert (const ProcMacro::TokenStream &ts);
+std::vector<const_TokenPtr> convert (const ProcMacro::TokenStream &ts);
-ProcMacro::Literal
-convert_literal (const_TokenPtr lit);
+ProcMacro::Literal convert_literal (const_TokenPtr lit);
} // namespace Rust
diff --git a/gcc/rust/util/rust-unicode.h b/gcc/rust/util/rust-unicode.h
index 6a6526d..6579b80 100644
--- a/gcc/rust/util/rust-unicode.h
+++ b/gcc/rust/util/rust-unicode.h
@@ -59,20 +59,15 @@ public:
Utf8String nfc_normalize () const;
};
-bool
-is_alphabetic (uint32_t codepoint);
+bool is_alphabetic (uint32_t codepoint);
-bool
-is_ascii_only (const std::string &str);
+bool is_ascii_only (const std::string &str);
-bool
-is_numeric (uint32_t codepoint);
+bool is_numeric (uint32_t codepoint);
-bool
-is_nfc_qc_no (uint32_t codepoint);
+bool is_nfc_qc_no (uint32_t codepoint);
-bool
-is_nfc_qc_maybe (uint32_t codepoint);
+bool is_nfc_qc_maybe (uint32_t codepoint);
enum class QuickCheckResult
{
@@ -81,8 +76,7 @@ enum class QuickCheckResult
MAYBE
};
-QuickCheckResult
-nfc_quick_check (const std::vector<Codepoint> &s);
+QuickCheckResult nfc_quick_check (const std::vector<Codepoint> &s);
} // namespace Rust
@@ -90,14 +84,11 @@ nfc_quick_check (const std::vector<Codepoint> &s);
namespace selftest {
-void
-rust_nfc_qc_test ();
+void rust_nfc_qc_test ();
-void
-rust_utf8_normalize_test ();
+void rust_utf8_normalize_test ();
-void
-rust_utf8_property_test ();
+void rust_utf8_property_test ();
} // namespace selftest
diff --git a/gcc/rust/util/rust-unwrap-segment.h b/gcc/rust/util/rust-unwrap-segment.h
index bebdc3a..af3a237 100644
--- a/gcc/rust/util/rust-unwrap-segment.h
+++ b/gcc/rust/util/rust-unwrap-segment.h
@@ -83,14 +83,11 @@ public:
/*
* Used to get the node id of a path segment object
*/
-NodeId
-unwrap_segment_node_id (const AST::TypePathSegment &seg);
+NodeId unwrap_segment_node_id (const AST::TypePathSegment &seg);
-NodeId
-unwrap_segment_node_id (const AST::SimplePathSegment &seg);
+NodeId unwrap_segment_node_id (const AST::SimplePathSegment &seg);
-NodeId
-unwrap_segment_node_id (const AST::PathExprSegment &seg);
+NodeId unwrap_segment_node_id (const AST::PathExprSegment &seg);
template <class T>
NodeId