aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/ChangeLog5000
-rw-r--r--gcc/rust/Make-lang.in33
-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.cc149
-rw-r--r--gcc/rust/ast/rust-ast-builder.h43
-rw-r--r--gcc/rust/ast/rust-ast-collector.cc506
-rw-r--r--gcc/rust/ast/rust-ast-collector.h18
-rw-r--r--gcc/rust/ast/rust-ast-dump.h6
-rw-r--r--gcc/rust/ast/rust-ast-formatting.h18
-rw-r--r--gcc/rust/ast/rust-ast-fragment.cc42
-rw-r--r--gcc/rust/ast/rust-ast-fragment.h6
-rw-r--r--gcc/rust/ast/rust-ast-full-decls.h17
-rw-r--r--gcc/rust/ast/rust-ast-pointer-visitor.cc1475
-rw-r--r--gcc/rust/ast/rust-ast-pointer-visitor.h234
-rw-r--r--gcc/rust/ast/rust-ast-visitor.cc160
-rw-r--r--gcc/rust/ast/rust-ast-visitor.h38
-rw-r--r--gcc/rust/ast/rust-ast.cc567
-rw-r--r--gcc/rust/ast/rust-ast.h241
-rw-r--r--gcc/rust/ast/rust-builtin-ast-nodes.h61
-rw-r--r--gcc/rust/ast/rust-collect-lang-items.cc38
-rw-r--r--gcc/rust/ast/rust-collect-lang-items.h3
-rw-r--r--gcc/rust/ast/rust-cond-compilation.h36
-rw-r--r--gcc/rust/ast/rust-desugar-apit.cc530
-rw-r--r--gcc/rust/ast/rust-desugar-apit.h42
-rw-r--r--gcc/rust/ast/rust-desugar-for-loops.cc75
-rw-r--r--gcc/rust/ast/rust-desugar-for-loops.h17
-rw-r--r--gcc/rust/ast/rust-desugar-question-mark.cc58
-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.h861
-rw-r--r--gcc/rust/ast/rust-expression-yeast.cc77
-rw-r--r--gcc/rust/ast/rust-expression-yeast.h49
-rw-r--r--gcc/rust/ast/rust-fmt.cc38
-rw-r--r--gcc/rust/ast/rust-fmt.h230
-rw-r--r--gcc/rust/ast/rust-item.h228
-rw-r--r--gcc/rust/ast/rust-macro.h53
-rw-r--r--gcc/rust/ast/rust-path.cc34
-rw-r--r--gcc/rust/ast/rust-path.h88
-rw-r--r--gcc/rust/ast/rust-pattern.cc80
-rw-r--r--gcc/rust/ast/rust-pattern.h429
-rw-r--r--gcc/rust/ast/rust-stmt.h6
-rw-r--r--gcc/rust/ast/rust-type.h208
-rw-r--r--gcc/rust/backend/rust-compile-asm.cc159
-rw-r--r--gcc/rust/backend/rust-compile-asm.h14
-rw-r--r--gcc/rust/backend/rust-compile-base.cc81
-rw-r--r--gcc/rust/backend/rust-compile-base.h11
-rw-r--r--gcc/rust/backend/rust-compile-block.cc1
-rw-r--r--gcc/rust/backend/rust-compile-block.h14
-rw-r--r--gcc/rust/backend/rust-compile-context.cc28
-rw-r--r--gcc/rust/backend/rust-compile-context.h30
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc252
-rw-r--r--gcc/rust/backend/rust-compile-expr.h4
-rw-r--r--gcc/rust/backend/rust-compile-extern.h52
-rw-r--r--gcc/rust/backend/rust-compile-implitem.cc44
-rw-r--r--gcc/rust/backend/rust-compile-implitem.h6
-rw-r--r--gcc/rust/backend/rust-compile-intrinsic.cc82
-rw-r--r--gcc/rust/backend/rust-compile-item.cc140
-rw-r--r--gcc/rust/backend/rust-compile-item.h12
-rw-r--r--gcc/rust/backend/rust-compile-pattern.cc860
-rw-r--r--gcc/rust/backend/rust-compile-pattern.h24
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc101
-rw-r--r--gcc/rust/backend/rust-compile-stmt.cc3
-rw-r--r--gcc/rust/backend/rust-compile-type.cc136
-rw-r--r--gcc/rust/backend/rust-compile-type.h4
-rw-r--r--gcc/rust/backend/rust-compile-var-decl.h71
-rw-r--r--gcc/rust/backend/rust-compile.cc16
-rw-r--r--gcc/rust/backend/rust-constexpr.cc879
-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.cc94
-rw-r--r--gcc/rust/backend/rust-tree.h189
-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.cc26
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h5
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h35
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h10
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc60
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h21
-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.h23
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-visitor.h2
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir.h40
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc2
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-function-collector.h15
-rw-r--r--gcc/rust/checks/errors/feature/contrib/.gitignore1
-rw-r--r--gcc/rust/checks/errors/feature/contrib/Makefile59
-rw-r--r--gcc/rust/checks/errors/feature/contrib/README3
-rw-r--r--gcc/rust/checks/errors/feature/contrib/copyright-stub.h19
-rwxr-xr-xgcc/rust/checks/errors/feature/contrib/fetch30
-rw-r--r--gcc/rust/checks/errors/feature/contrib/parse.y143
-rwxr-xr-xgcc/rust/checks/errors/feature/contrib/regen23
-rw-r--r--gcc/rust/checks/errors/feature/contrib/scan.l55
-rw-r--r--gcc/rust/checks/errors/feature/rust-feature-defs.h600
-rw-r--r--gcc/rust/checks/errors/feature/rust-feature-gate.cc (renamed from gcc/rust/checks/errors/rust-feature-gate.cc)151
-rw-r--r--gcc/rust/checks/errors/feature/rust-feature-gate.h (renamed from gcc/rust/checks/errors/rust-feature-gate.h)19
-rw-r--r--gcc/rust/checks/errors/feature/rust-feature.cc100
-rw-r--r--gcc/rust/checks/errors/feature/rust-feature.h85
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-check.cc12
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-ctx.h3
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc95
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-reporter.h12
-rw-r--r--gcc/rust/checks/errors/privacy/rust-reachability.cc6
-rw-r--r--gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc32
-rw-r--r--gcc/rust/checks/errors/privacy/rust-visibility-resolver.h6
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.cc47
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.h14
-rw-r--r--gcc/rust/checks/errors/rust-feature.cc94
-rw-r--r--gcc/rust/checks/errors/rust-feature.h88
-rw-r--r--gcc/rust/checks/errors/rust-hir-pattern-analysis.cc228
-rw-r--r--gcc/rust/checks/errors/rust-hir-pattern-analysis.h24
-rw-r--r--gcc/rust/checks/errors/rust-readonly-check.cc340
-rw-r--r--gcc/rust/checks/errors/rust-readonly-check.h59
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.cc50
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.h14
-rw-r--r--gcc/rust/checks/lints/rust-lint-marklive-base.h3
-rw-r--r--gcc/rust/checks/lints/rust-lint-unused-var.cc4
-rw-r--r--gcc/rust/expand/rust-cfg-strip.cc120
-rw-r--r--gcc/rust/expand/rust-cfg-strip.h25
-rw-r--r--gcc/rust/expand/rust-derive-clone.cc20
-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-debug.cc3
-rw-r--r--gcc/rust/expand/rust-derive-default.cc8
-rw-r--r--gcc/rust/expand/rust-derive-eq.cc26
-rw-r--r--gcc/rust/expand/rust-derive-eq.h10
-rw-r--r--gcc/rust/expand/rust-derive-hash.cc11
-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.cc155
-rw-r--r--gcc/rust/expand/rust-derive-partial-eq.h29
-rw-r--r--gcc/rust/expand/rust-derive.cc47
-rw-r--r--gcc/rust/expand/rust-derive.h20
-rw-r--r--gcc/rust/expand/rust-expand-format-args.cc6
-rw-r--r--gcc/rust/expand/rust-expand-visitor.cc236
-rw-r--r--gcc/rust/expand/rust-expand-visitor.h81
-rw-r--r--gcc/rust/expand/rust-macro-builtins-asm.cc321
-rw-r--r--gcc/rust/expand/rust-macro-builtins-asm.h48
-rw-r--r--gcc/rust/expand/rust-macro-builtins-format-args.cc78
-rw-r--r--gcc/rust/expand/rust-macro-builtins-helpers.cc7
-rw-r--r--gcc/rust/expand/rust-macro-builtins-helpers.h36
-rw-r--r--gcc/rust/expand/rust-macro-builtins-offset-of.cc78
-rw-r--r--gcc/rust/expand/rust-macro-builtins.cc17
-rw-r--r--gcc/rust/expand/rust-macro-builtins.h8
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc139
-rw-r--r--gcc/rust/expand/rust-macro-expand.h4
-rw-r--r--gcc/rust/expand/rust-macro-substitute-ctx.cc22
-rw-r--r--gcc/rust/expand/rust-macro-substitute-ctx.h6
-rw-r--r--gcc/rust/expand/rust-proc-macro.h6
-rw-r--r--gcc/rust/expand/rust-token-tree-desugar.cc72
-rw-r--r--gcc/rust/expand/rust-token-tree-desugar.h55
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.cc205
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h34
-rw-r--r--gcc/rust/hir/rust-ast-lower-block.h6
-rw-r--r--gcc/rust/hir/rust-ast-lower-enumitem.h9
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.cc230
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h8
-rw-r--r--gcc/rust/hir/rust-ast-lower-extern.h7
-rw-r--r--gcc/rust/hir/rust-ast-lower-implitem.cc93
-rw-r--r--gcc/rust/hir/rust-ast-lower-implitem.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.cc214
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h1
-rw-r--r--gcc/rust/hir/rust-ast-lower-pattern.cc130
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.cc64
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h13
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc69
-rw-r--r--gcc/rust/hir/rust-ast-lower.h8
-rw-r--r--gcc/rust/hir/rust-hir-dump.cc181
-rw-r--r--gcc/rust/hir/rust-hir-dump.h19
-rw-r--r--gcc/rust/hir/tree/rust-hir-bound.h12
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr-abstract.h6
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.cc148
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h331
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-decls.h15
-rw-r--r--gcc/rust/hir/tree/rust-hir-generic-param.h7
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.cc48
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h98
-rw-r--r--gcc/rust/hir/tree/rust-hir-path.h16
-rw-r--r--gcc/rust/hir/tree/rust-hir-pattern.h356
-rw-r--r--gcc/rust/hir/tree/rust-hir-type.cc2
-rw-r--r--gcc/rust/hir/tree/rust-hir-type.h9
-rw-r--r--gcc/rust/hir/tree/rust-hir-visibility.h2
-rw-r--r--gcc/rust/hir/tree/rust-hir-visitor.cc1202
-rw-r--r--gcc/rust/hir/tree/rust-hir-visitor.h344
-rw-r--r--gcc/rust/hir/tree/rust-hir.cc299
-rw-r--r--gcc/rust/lang.opt6
-rw-r--r--gcc/rust/lang.opt.urls2
-rw-r--r--gcc/rust/lex/rust-lex.cc60
-rw-r--r--gcc/rust/lex/rust-lex.h3
-rw-r--r--gcc/rust/lex/rust-token.cc34
-rw-r--r--gcc/rust/lex/rust-token.h97
-rw-r--r--gcc/rust/metadata/rust-export-metadata.cc16
-rw-r--r--gcc/rust/metadata/rust-export-metadata.h2
-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.h1250
-rw-r--r--gcc/rust/parse/rust-parse.cc46
-rw-r--r--gcc/rust/parse/rust-parse.h95
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.cc663
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.h224
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.cc785
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h102
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-implitem.h261
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.cc1250
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h162
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-path.cc558
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-path.h52
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.cc384
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.h146
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-stmt.cc81
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-stmt.h407
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc61
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h54
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-toplevel.h500
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.cc783
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h280
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc115
-rw-r--r--gcc/rust/resolve/rust-default-resolver.cc331
-rw-r--r--gcc/rust/resolve/rust-default-resolver.h18
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver-2.0.cc121
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver-2.0.h31
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver.cc589
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver.h196
-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.h44
-rw-r--r--gcc/rust/resolve/rust-forever-stack.hxx264
-rw-r--r--gcc/rust/resolve/rust-ice-finalizer.cc10
-rw-r--r--gcc/rust/resolve/rust-ice-finalizer.h6
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.cc453
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.h24
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.cc163
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.h437
-rw-r--r--gcc/rust/resolve/rust-resolve-builtins.cc125
-rw-r--r--gcc/rust/resolve/rust-resolve-builtins.h37
-rw-r--r--gcc/rust/resolve/rust-rib.h10
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc160
-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.cc59
-rw-r--r--gcc/rust/rust-diagnostics.h21
-rw-r--r--gcc/rust/rust-gcc.cc426
-rw-r--r--gcc/rust/rust-gcc.h24
-rw-r--r--gcc/rust/rust-lang.cc21
-rw-r--r--gcc/rust/rust-object-export.h13
-rw-r--r--gcc/rust/rust-session-manager.cc121
-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.cc10
-rw-r--r--gcc/rust/typecheck/rust-casts.cc78
-rw-r--r--gcc/rust/typecheck/rust-casts.h10
-rw-r--r--gcc/rust/typecheck/rust-coercion.cc170
-rw-r--r--gcc/rust/typecheck/rust-coercion.h12
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.cc223
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.h51
-rw-r--r--gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h40
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.cc35
-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.cc126
-rw-r--r--gcc/rust/typecheck/rust-hir-type-bounds.h12
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.cc304
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h15
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-enumitem.cc91
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc604
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h13
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.cc315
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.cc226
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc85
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-pattern.cc518
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.cc6
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct-field.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct.cc70
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.cc176
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h11
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc86
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h55
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.cc63
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h22
-rw-r--r--gcc/rust/typecheck/rust-type-util.cc87
-rw-r--r--gcc/rust/typecheck/rust-type-util.h42
-rw-r--r--gcc/rust/typecheck/rust-typecheck-context.cc157
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc211
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.h66
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.cc23
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.h8
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h1610
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.cc273
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.h29
-rw-r--r--gcc/rust/typecheck/rust-tyty-util.cc47
-rw-r--r--gcc/rust/typecheck/rust-tyty-util.h4
-rw-r--r--gcc/rust/typecheck/rust-tyty-variance-analysis-private.h9
-rw-r--r--gcc/rust/typecheck/rust-tyty-variance-analysis.cc13
-rw-r--r--gcc/rust/typecheck/rust-tyty-variance-analysis.h7
-rw-r--r--gcc/rust/typecheck/rust-tyty-visitor.h8
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc1064
-rw-r--r--gcc/rust/typecheck/rust-tyty.h558
-rw-r--r--gcc/rust/typecheck/rust-unify.cc1074
-rw-r--r--gcc/rust/typecheck/rust-unify.h23
-rw-r--r--gcc/rust/util/bi-map.h1
-rw-r--r--gcc/rust/util/expected.h4
-rw-r--r--gcc/rust/util/fnv-hash.h1
-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.h35
-rw-r--r--gcc/rust/util/rust-attributes.cc128
-rw-r--r--gcc/rust/util/rust-attributes.h28
-rw-r--r--gcc/rust/util/rust-base62.h3
-rw-r--r--gcc/rust/util/rust-canonical-path.h15
-rw-r--r--gcc/rust/util/rust-dir-owner.h3
-rw-r--r--gcc/rust/util/rust-dump.h2
-rw-r--r--gcc/rust/util/rust-edition.h3
-rw-r--r--gcc/rust/util/rust-ggc.cc44
-rw-r--r--gcc/rust/util/rust-ggc.h67
-rw-r--r--gcc/rust/util/rust-hir-map.cc32
-rw-r--r--gcc/rust/util/rust-hir-map.h15
-rw-r--r--gcc/rust/util/rust-inline-visitor.h1
-rw-r--r--gcc/rust/util/rust-lang-item.cc1
-rw-r--r--gcc/rust/util/rust-lang-item.h7
-rw-r--r--gcc/rust/util/rust-punycode.h6
-rw-r--r--gcc/rust/util/rust-stacked-contexts.h9
-rw-r--r--gcc/rust/util/rust-token-converter.cc12
-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.h29
341 files changed, 29025 insertions, 18025 deletions
diff --git a/gcc/rust/ChangeLog b/gcc/rust/ChangeLog
index 31c731b..ec156ac 100644
--- a/gcc/rust/ChangeLog
+++ b/gcc/rust/ChangeLog
@@ -1,3 +1,5001 @@
+2025-12-03 Marc Poulhiès <dkm@kataplop.net>
+
+ * lex/rust-lex.cc (rust_input_source_test): Reindent.
+
+2025-12-03 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-macro.h (MetaNameValueStr::get_name): New function.
+ (MetaNameValueStr::get_value): Likewise.
+ * checks/errors/feature/rust-feature-gate.cc
+ (FeatureGate::visit): Tweak unknown feature detection.
+ (FeatureGate::gate): Handle field rename.
+ (FeatureGate::note_stability_attribute): New function
+ definition.
+ * checks/errors/feature/rust-feature-gate.h
+ (FeatureGate::note_stability_attribute): New function
+ declaration.
+ (FeatureGate::Stability): New enum class.
+ (FeatureGate::valid_features): Rename field to...
+ (FeatureGate::valid_lang_features): ...here.
+ (FeatureGate::valid_lib_features): New field.
+ (FeatureGate::defined_lib_features): Likewise.
+ * checks/errors/feature/rust-feature.cc (Feature::as_name):
+ Improve implementation.
+
+2025-12-03 Raiki Tamura <tamaron1203@gmail.com>
+
+ * checks/errors/feature/rust-feature-gate.cc (FeatureGate::visit): Add check for lang_items.
+ * checks/errors/feature/rust-feature-gate.h: Likewise.
+
+2025-12-03 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_function): Return a nullptr on
+ error instead of a valid function.
+ (Parser::parse_let_stmt): Remove non leaf error.
+ (Parser::parse_if_expr): Likewise.
+ (Parser::parse_loop_expr): Likewise.
+ (Parser::parse_expr): Return error on null denotation error.
+
+2025-12-03 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_delim_token_tree):
+ Remove error message.
+ (Parser::parse_token_tree): Split error message.
+
+2025-12-03 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * backend/rust-constexpr.cc (eval_binary_expression): Set initial value
+ equality value to false.
+
+2025-12-03 Jonathan Wakely <jwakely@redhat.com>
+
+ * expand/rust-macro-expand.h: Fix typos in comment.
+
+2025-12-03 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_items): Remove item parsing
+ error.
+
+2025-12-03 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * expand/rust-expand-visitor.cc (builtin_derive_item): Collect derived nodes.
+ (derive_item): Collect derived nodes.
+ * util/rust-hir-map.cc (Mappings::add_derived_nodes): Add derived set to collect derived
+ nodes.
+ (Mappings::is_derived_node): Add derived set to collect derived nodes.
+ * util/rust-hir-map.h: Add derived set to collect derived nodes.
+
+2025-11-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
+
+ * lang.opt.urls: Regenerate.
+
+2025-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ * lex/rust-lex.cc (rust_input_source_test): Cast char8_t string
+ literals to (const char *) to make it compilable with C++20. Use
+ char16_t or char32_t character literals instead of ordinary
+ character literals or wide character literals in expected
+ initializers.
+
+2025-11-27 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * typecheck/rust-tyty-subst.h: Remove now useless inclusion.
+ * typecheck/rust-tyty.h (class TypeBoundPredicate): New, moved from rust-tyty-bounds.h
+ (class TypeBoundsMappings): Likewise.
+ * typecheck/rust-tyty-bounds.h: Removed.
+
+2025-11-25 Lúcio Boari Fleury <lucboari@gmail.com>
+
+ * parse/rust-parse-impl.h: Add early exit condition to parsing loop.
+
+2025-11-25 Philip Herron <herron.philip@googlemail.com>
+
+ * ast/rust-ast.cc (TraitItemType::as_string): add generic params
+ * ast/rust-ast.h: remove old comment
+ * ast/rust-item.h: add generic params to associated type
+ * ast/rust-type.h: remove old comment
+ * hir/rust-ast-lower-implitem.cc (ASTLowerTraitItem::visit): hir lowering for gat's
+ * hir/tree/rust-hir-item.cc (TraitItemType::TraitItemType): gat's on TraitItemType
+ (TraitItemType::operator=): preserve generic params
+ * hir/tree/rust-hir-item.h: likewise
+ * hir/tree/rust-hir.cc (TraitItemType::as_string): likewise
+ * parse/rust-parse-impl.h (Parser::parse_trait_type): hit the < and parse params
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItemWithTrait::visit): typecheck
+ * typecheck/rust-tyty.cc (BaseType::has_substitutions_defined): dont destructure
+
+2025-11-25 Lucas Ly Ba <lucas.ly-ba@outlook.com>
+
+ * expand/rust-derive.cc (DeriveVisitor::derive):
+ Add check and error.
+
+2025-11-25 Lucas Ly Ba <lucas.ly-ba@outlook.com>
+
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::handle_doc_item_attribute): Make error.
+
+2025-11-25 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-expr.cc (compile_float_literal): Add is_negative
+ check to compile negative float literals properly.
+ * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit(RangePattern)):
+ Minor optimization to E0579 checks to reduce memory copy.
+
+2025-11-25 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * checks/errors/feature/rust-feature-gate.cc
+ (FeatureGate::gate): Handle removal of Feature::create.
+ (FeatureGate::visit): Refer to AUTO_TRAITS as
+ OPTIN_BUILTIN_TRAITS.
+ * checks/errors/feature/rust-feature.cc (Feature::create):
+ Remove.
+ (Feature::feature_list): New static member variable.
+ (Feature::name_hash_map): Use "rust-feature-defs.h" to define.
+ (Feature::lookup): New member function definition.
+ * checks/errors/feature/rust-feature.h (Feature::State): Add
+ comments.
+ (Feature::Name): Use "rust-feature-defs.h" to define.
+ (Feature::as_string): Make const.
+ (Feature::name): Likewise.
+ (Feature::state): Likewise.
+ (Feature::issue): Likewise.
+ (Feature::description): Remove member function declaration.
+ (Feature::create): Remove static member function declaration.
+ (Feature::lookup): New member function declarations.
+ (Feature::Feature): Adjust arguments.
+ (Feature::m_rustc_since): Rename to...
+ (Feature::m_rust_since): ...here.
+ (Feature::m_description): Remove.
+ (Feature::m_reason): New member variable.
+ (Feature::feature_list): New static member variable.
+ * checks/errors/feature/rust-feature-defs.h: New file.
+ * checks/errors/feature/contrib/parse.y: New file.
+ * checks/errors/feature/contrib/scan.l: New file.
+ * checks/errors/feature/contrib/.gitignore: New file.
+ * checks/errors/feature/contrib/Makefile: New file.
+ * checks/errors/feature/contrib/fetch: New file.
+ * checks/errors/feature/contrib/regen: New file.
+ * checks/errors/feature/contrib/copyright-stub.h: New file.
+ * checks/errors/feature/contrib/README: New file.
+
+2025-11-25 Lucas Ly Ba <lucas.ly-ba@outlook.com>
+
+ * ast/rust-ast.cc (Attribute::check_cfg_predicate): Make error when attribute has no input.
+
+2025-11-25 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Implicitly
+ convert LocalVariable to pointer to Bvariable.
+ * rust-backend.h (local_variable): Return LocalVariable.
+ (parameter_variable): Likewise.
+ (static_chain_variable): Likewise.
+ (temporary_variable): Likewise.
+ * rust-gcc.cc (local_variable): Likewise.
+ (parameter_variable): Likewise.
+ (static_chain_variable): Likewise.
+ (temporary_variable): Likewise.
+ (LocalVariable::get_tree): New function.
+ (LocalVariable::error_variable): Likewise.
+ * rust-gcc.h (class LocalVariable): New class.
+
+2025-11-25 lenny.chiadmi-delage <lenny.chiadmi-delage@epita.fr>
+
+ * expand/rust-macro-expand.cc (transcribe_expression): Check if
+ parser didn't fail.
+ (transcribe_type): Likewise.
+ (transcribe_pattern): Likewise.
+
+2025-11-17 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItemWithTrait::visit): null guard
+ * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): default to anon
+
+2025-11-17 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-item.cc (CompileItem::visit): support the synthetic function consts
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::Resolve): likewise
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItem::visit): create the synth
+ * typecheck/rust-tyty.h: new flag for synthetic constant
+
+2025-11-17 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): fix mappings
+
+2025-11-17 Lucas Ly Ba <lucas.ly-ba@outlook.com>
+
+ * ast/rust-ast.cc (Attribute::is_derive):
+ Change is_derive method with its valid path.
+ * util/rust-attribute-values.h:
+ Delete redudant derive attribute.
+ * util/rust-attributes.cc (AttributeChecker::check_inner_attribute):
+ Helper method for check_inner_attributes
+ (AttributeChecker::check_inner_attributes):
+ Implement method for errors check.
+ * util/rust-attributes.h:
+ Add methods above in header.
+
+2025-11-17 Lucas Ly Ba <lucas.ly-ba@outlook.com>
+
+ * parse/rust-parse-impl.h(Parser<ManagedTokenSource>::parse_while_let_loop_expr):
+ Add check for missing pattern.
+
+2025-11-17 Lucas Ly Ba <lucas.ly-ba@outlook.com>
+
+ * ast/rust-ast.cc (MetaItemLitExpr::check_cfg_predicate): Make error.
+
+2025-11-17 Lucas Ly Ba <lucas.ly-ba@outlook.com>
+
+ * ast/rust-ast.cc (Attribute::check_cfg_predicate): add cfg path in condition
+
+2025-11-17 Lucas Ly Ba <lucas.ly-ba@outlook.com>
+
+ * ast/rust-ast.cc (Attribute::check_cfg_predicate):
+ Make error.
+
+2025-11-17 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-resolve-path.cc: handle const param values
+ * typecheck/rust-hir-type-check-item.cc: generate const infer vars when required
+ * typecheck/rust-type-util.cc (unify_site_and): handle a null param cleanup
+ * typecheck/rust-tyty-util.cc (TyVar::get_implicit_const_infer_var): helper interface
+ * typecheck/rust-tyty-util.h: update header prototypes
+ * typecheck/rust-tyty.cc (BaseType::is_concrete): correctly handle const types
+ (ConstParamType::get_name): emit the specified type
+ (ConstParamType::is_equal): fix recursion loop
+ * typecheck/rust-unify.cc (UnifyRules::go): const infer vars need cleanup too
+ * typecheck/rust-unify.h: support base generics
+
+2025-11-17 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-pattern.cc(compilePatternCheckExpr::visit(RangePattern)):
+ Add E0579 check to ensure that lower bound is always below upper bound.
+
+2025-11-17 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-pattern.cc (compile_range_pattern_bound): Set litexpr
+ to negative if has_minus is present in the RangePatternBoundLiteral param.
+
+2025-11-17 vishruth-thimmaiah <vishruththimmaiah@gmail.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_generic_params): Emit
+ an error when const generics with a default value is not
+ trailing.
+
+2025-11-17 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * parse/rust-parse-impl.h (parse_literal_or_range_pattern): Parse minus sign
+ properly for LiteralPattern.
+ * ast/rust-pattern.h (LiteralPattern): Add has_minus boolean for LiteralPattern.
+ * hir/tree/rust-hir-pattern.h (LiteralPattern): Ditto.
+ * ast/rust-pattern.cc (LiteralPattern::as_string): Update to include minus sign
+ if present.
+ * hir/tree/rust-hir.cc (LiteralPattern::as_string): Ditto.
+ * hir/rust-ast-lower-pattern.cc (visit(LiteralPattern)): Pass has_minus boolean
+ from AST to HIR.
+ * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit(LiteralPattern)):
+ Compile litexpr as negative if minus sign is present.
+
+2025-11-17 Lucas Ly Ba <lucas.ly-ba@outlook.fr>
+
+ * metadata/rust-export-metadata.cc (ExportContext::emit_macro):
+ Change method argument NodeId to AST::MacroRulesDefinition.
+ * metadata/rust-export-metadata.h:
+ Likewise.
+ * util/rust-hir-map.cc (Mappings::insert_exported_macro):
+ Insert AST::MacroRulesDefinition instead of NodeId.
+ * util/rust-hir-map.h:
+ Change methods declarations of exported macros.
+
+2025-11-12 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-fmt.h: Simplify diagnostic avoidance.
+
+2025-11-12 Arthur Cohen <arthur.cohen@embecosm.com>
+ Thomas Schwinge <tschwinge@gcc.gnu.org>
+
+ PR rust/122498
+ * ast/rust-fmt.h: Add -Warray-bounds pragma to avoid the issue during
+ bootstraps
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-pointer-visitor.cc (PointerVisitor::visit):
+ Handle the expression contained in an ErrorPropagationExpr.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (visit(TuplePattern)): Update HAS_REST
+ case to continue to attempt to resolve pattern items after emitting size error.
+
+2025-10-30 Ryo Yoshida <low.ryoshida@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): Emit
+ an error when the path refers to an enum itself rather than its variant.
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-base.cc (parse_repr_options): Changed TOKEN_TREE
+ assert into error, update malformed repr attribute error message to be inline
+ with other attribute error messages.
+
+2025-10-30 Lucas Ly Ba <lucas.ly-ba@outlook.fr>
+
+ * ast/rust-ast.cc (Attribute::is_derive):
+ Change string derive to its definition.
+ * util/rust-attribute-values.h:
+ Add attribute definition derive.
+ * util/rust-attributes.cc (AttributeChecker::visit):
+ Add method check_inner_attributes.
+ (AttributeChecker::check_inner_attributes):
+ Check if there is a bad inner attribute.
+ * util/rust-attributes.h:
+ Add method check_inner_attributes in .h.
+
+2025-10-30 lishin <lishin1008@gmail.com>
+
+ * typecheck/rust-tyty-util.cc (TyVar::TyVar): Add null check to avoid ICE.
+ (TyVar::get_tyty): Return nullptr when lookup fails.
+ (TyVar::clone): Handle null base type safely.
+ (TyVar::monomorphized_clone): Add fallback for error types.
+
+2025-10-30 Ryo Yoshida <low.ryoshida@gmail.com>
+
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): check
+ and properly emit an error when the tuple index is on a non-tuple-struct.
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::array_copied_expr): refactor to new classes
+ * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit): likewise
+ (CompilePatternBindings::visit): likewise
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): likewise
+ * backend/rust-compile-type.h: likewise
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): likewise
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): likewise
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise
+ * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): likewise
+ * typecheck/rust-substitution-mapper.h: likewise
+ * typecheck/rust-type-util.cc (unify_site_and): remove bad delete (alpine32)
+ * typecheck/rust-tyty-call.h: refactor to new classes
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::clone): likewise
+ (SubstitutionRef::infer_substitions): likewise
+ * typecheck/rust-tyty-util.cc (TyVar::get_implicit_const_infer_var): likewise
+ * typecheck/rust-tyty-util.h: likewise
+ * typecheck/rust-tyty-variance-analysis-private.h: likewise
+ * typecheck/rust-tyty-visitor.h: likewise
+ * typecheck/rust-tyty.cc (BaseType::destructure): likewise
+ (BaseType::monomorphized_clone): likewise
+ (BaseType::is_concrete): likewise
+ (VariantDef::clone): likewise
+ (VariantDef::monomorphized_clone): likewise
+ (ArrayType::as_string): likewise
+ (ArrayType::get_capacity): likewise
+ (ArrayType::handle_substitions): likewise
+ (generate_tree_str): likewise
+ (ConstType::ConstType): likewise
+ (ConstParamType::ConstParamType): likewise
+ (ConstType::accept_vis): likewise
+ (ConstParamType::const_kind): likewise
+ (ConstParamType::get_symbol): likewise
+ (ConstParamType::can_resolve): likewise
+ (ConstParamType::resolve): likewise
+ (ConstParamType::accept_vis): likewise
+ (ConstType::set_value): likewise
+ (ConstType::as_string): likewise
+ (ConstParamType::as_string): likewise
+ (ConstType::clone): likewise
+ (ConstParamType::clone): likewise
+ (ConstType::get_symbol): likewise
+ (ConstParamType::get_name): likewise
+ (ConstType::can_resolve): likewise
+ (ConstParamType::is_equal): likewise
+ (ConstType::resolve): likewise
+ (ConstValueType::ConstValueType): likewise
+ (ConstValueType::const_kind): likewise
+ (ConstValueType::accept_vis): likewise
+ (ConstValueType::as_string): likewise
+ (ConstValueType::clone): likewise
+ (ConstValueType::get_name): likewise
+ (ConstValueType::is_equal): likewise
+ (ConstValueType::get_value): likewise
+ (ConstInferType::ConstInferType): likewise
+ (ConstInferType::const_kind): likewise
+ (ConstInferType::accept_vis): likewise
+ (ConstType::get_name): likewise
+ (ConstInferType::as_string): likewise
+ (ConstInferType::clone): likewise
+ (ConstInferType::get_name): likewise
+ (ConstType::is_equal): likewise
+ (ConstInferType::is_equal): likewise
+ (ConstErrorType::ConstErrorType): likewise
+ (ConstErrorType::const_kind): likewise
+ (ConstType::handle_substitions): likewise
+ (ConstErrorType::accept_vis): likewise
+ (ConstErrorType::as_string): likewise
+ (ConstErrorType::clone): likewise
+ (ConstErrorType::get_name): likewise
+ (ConstErrorType::is_equal): likewise
+ * typecheck/rust-tyty.h (class BaseConstType): likewise
+ (class ConstType): likewise
+ (class ConstParamType): likewise
+ (class ConstValueType): likewise
+ (class ConstInferType): likewise
+ (class ConstErrorType): likewise
+ * typecheck/rust-unify.cc (UnifyRules::commit): likewise
+ (UnifyRules::go): likewise
+ (UnifyRules::expect_array): likewise
+ (UnifyRules::expect_const): likewise
+ * typecheck/rust-unify.h: likewise
+
+2025-10-30 0xllx0 <github+elle@weathered-steel.dev>
+
+ * ast/rust-ast.cc (Module::process_file_path): empty module early return
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * util/rust-attributes.cc (check_doc_attribute): Change message.
+ (AttributeChecker::visit): Add doc attribute checking on traits.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast.cc (AttrInputMetaItemContainer::separate_cfg_attrs):
+ Avoid malformed attributes.
+ * util/rust-attributes.cc (AttributeChecker::visit): Change location.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-expr.h: Force crash when retrieving locus.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast.h: Add missing override modifier.
+ * ast/rust-path.h: Likewise.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * util/rust-attributes.cc (AttributeChecker::check_attribute): Recurse
+ within attr input for additional attribute checking.
+ (AttributeChecker::visit): Remove empty definition in favor of default
+ ast visitor definition.
+ * util/rust-attributes.h: Remove now unused prototypes.
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (visit(TupleStructPattern)):
+ Update error for mismatched number of fields to use rich_location.
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-pattern.cc: Add compilation support for TupleStructItemsHasRest
+ in CompilePatternCheckExpr(TupleStructPattern) & CompilePatternBindings(TupleStructPattern)
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit(TupleStructPattern)):
+ Implement lowering of AST::TupleStructItemsHasRest to HIR.
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(TupleStructPattern)):
+ Add the respective type checking for AST::TupleStructItemsHasRest
+ * checks/errors/rust-hir-pattern-analysis.cc (lower_tuple_pattern):
+ Add respective pattern for HAS_REST case.
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (visit(StructPattern)): Add type check
+ support for StructPatterns matching against a TUPLE type ADT.
+ * backend/rust-compile-pattern.cc(CompilePatternBindings::visit(StructPattern)):
+ Update assert to allow TUPLE type ADTs.
+ * hir/tree/rust-hir.cc (StructPatternField::as_string()): Improve info dumped.
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * ast/rust-pattern.h (StructPatternElements): Rename has_struct_pattern_etc
+ to has_rest_pattern, and has_etc to has_rest to signify presense of rest
+ patterns more clearly.
+ * ast/rust-pattern.cc (StructPatternElements::as_string): Rename variables
+ accordingly.
+ * ast/rust-ast-collector.cc: Rename variables accordingly.
+ * expand/rust-cfg-strip.cc: Rename variables accordingly.
+ * parse/rust-parse-impl.h: Rename variable accordingly.
+ * hir/tree/rust-hir-pattern.h (StructPatternElements): Add a boolean to track
+ presense of rest pattern.
+ * hir/rust-ast-lower-pattern.cc (visit(StructPattern)): Add support for
+ lowering rest pattern to HIR.
+ * typecheck/rust-hir-type-check-pattern.cc (visit(StructPattern)): Remove
+ size check when rest pattern is present.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-extern.h: Add includes.
+ (CompileExternItem::visit): Use get_link_name.
+ (CompileExternItem::get_link_name): New static member function.
+ * util/rust-attribute-values.h (Attributes::LINK_NAME): New
+ static constexpr member variable.
+ * util/rust-attributes.cc (__definitions): New entry for
+ LINK_NAME.
+ * util/rust-ggc.cc: Include "rust-ast.h".
+ (Ident::Ident): Add overload for Rust::Identifier.
+ * util/rust-ggc.h (class Identifier): Forward declare.
+ (Ident::Ident): Add overload for Rust::Identifier.
+
+2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-expand-visitor.cc: Remove old visitors.
+ * expand/rust-expand-visitor.h: Likewise, plus inherit from PointerVisitor.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-expand.cc: Forward invocation tree locus to
+ substitution context.
+ * expand/rust-macro-substitute-ctx.cc: Use origin location for expanded
+ tokens.
+ * expand/rust-macro-substitute-ctx.h (class SubstituteCtx): Save
+ invocation location.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-expand.cc (transcribe_expression): Emit error
+ early.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-substitute-ctx.cc (is_builtin_metavariable): Add
+ function to check builtin metavars knowledge.
+ (SubstituteCtx::check_repetition_amount): Do not process missing
+ fragment.
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-resolve-path.cc: add error diag
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): add error diagnostic
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): check for error
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-expr.cc: remove old hack
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): handle fnptr
+ * typecheck/rust-tyty.cc (FnPtr::handle_substitions): new
+ * typecheck/rust-tyty.h: likewise
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-fmt.h (class FFIOpt): Adjust internal structure to
+ match a repr(C) rust enum.
+
+2025-10-30 Magnus-Mage <romescha123@gmail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Implement
+ FormatArgs visitor to reconstruct format_args! macro syntax.
+ * ast/rust-builtin-ast-nodes.h (FormatArguments): Add get_args(),
+ size(), and empty() accessor methods.
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): check for invalid capacity
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-constexpr.cc (eval_constant_expression): port over missing bits
+ (eval_store_expression): likewise
+ (eval_call_expression): likewise
+ (eval_binary_expression): likewise
+ (eval_bit_field_ref): likewise
+ (eval_check_shift_p): likewise
+ (fold_pointer_plus_expression): likewise
+ (maybe_fold_addr_pointer_plus): likewise
+ (fold_expr): likewise
+ (union_active_member): likewise
+ (fold_indirect_ref_1): likewise
+ (rs_fold_indirect_ref): likewise
+ (rs_eval_indirect_ref): likewise
+ (eval_logical_expression): likewise
+ (eval_vector_conditional_expression): likewise
+ (eval_bare_aggregate): likewise
+ (cxx_eval_trinary_expression): likewise
+ (eval_and_check_array_index): likewise
+ (eval_array_reference): likewise
+ (eval_component_reference): likewise
+ (rs_bind_parameters_in_call): likewise
+ (eval_builtin_function_call): likewise
+ (constexpr_fn_retval): likewise
+ (verify_constant): likewise
+ (get_array_or_vector_nelts): likewise
+ (eval_conditional_expression): likewise
+ (eval_switch_expr): likewise
+ (eval_unary_expression): likewise
+ (cxx_eval_outermost_constant_expr): likewise
+ (potential_constant_expression_1): likewise
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::compile_integer_literal): cleanup
+ * backend/rust-constexpr.cc (struct constexpr_global_ctx): port over c++ helpers
+ (decl_really_constant_value): likewise
+ (eval_constant_expression): likewise
+ (non_const_var_error): likewise
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_pattern): Ignore
+ inner patterns which fail to parse.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Remove
+ overload for TraitItemConst.
+ * ast/rust-ast-collector.h (TokenCollector::visit): Likewise.
+ * ast/rust-ast-pointer-visitor.cc (PointerVisitor::visit):
+ Likewise.
+ * ast/rust-ast-pointer-visitor.h (PointerVisitor::visit):
+ Likewise.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast-visitor.h (ASTVisitor::visit): Likewise.
+ (DefaultASTVisitor::visit): Likewise.
+ * expand/rust-cfg-strip.cc (CfgStrip::visit): Likewise.
+ * expand/rust-cfg-strip.h (CfgStrip::visit): Likewise.
+ * expand/rust-derive.h (DeriveVisitor::visit): Likewise.
+ * expand/rust-expand-visitor.cc (ExpandVisitor::visit):
+ Likewise.
+ * expand/rust-expand-visitor.h (ExpandVisitor::visit): Likewise.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise.
+ * hir/rust-ast-lower-base.h (ASTLoweringBase::visit): Likewise.
+ * util/rust-attributes.cc (AttributeChecker::visit): Likewise.
+ * util/rust-attributes.h (AttributeChecker::visit): Likewise.
+ * ast/rust-ast.cc (ConstantItem::as_string): Handle missing
+ expression.
+ (TraitItemConst::as_string): Remove function definition.
+ (TraitItemConst::accept_vis): Remove function definition.
+ * ast/rust-item.h (ConstantItem::mark_for_strip): Adjust
+ comment.
+ (ConstantItem::has_expr): Make const.
+ (class TraitItemConst): Remove definition.
+ * ast/rust-ast-full-decls.h (class TraitItemConst): Remove
+ declaration.
+ * hir/rust-ast-lower-implitem.cc (ASTLowerTraitItem::visit):
+ Handle ConstantItem instead of TraitItemConst.
+ * hir/rust-ast-lower-implitem.h (ASTLowerTraitItem::visit):
+ Likewise.
+ * parse/rust-parse-impl.h (Parser::parse_trait_const): Return
+ pointer to ConstantItem instead of TraitItemConst.
+ * parse/rust-parse.h (Parser::parse_trait_const): Likewise.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * Make-lang.in: Handle source files in checks/errors/feature.
+ * checks/errors/rust-feature-gate.cc: Move to...
+ * checks/errors/feature/rust-feature-gate.cc: ...here.
+ * checks/errors/rust-feature-gate.h: Move to...
+ * checks/errors/feature/rust-feature-gate.h: ...here.
+ * checks/errors/rust-feature.cc: Move to...
+ * checks/errors/feature/rust-feature.cc: ...here.
+ * checks/errors/rust-feature.h: Move to...
+ * checks/errors/feature/rust-feature.h: ...here.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * Make-lang.in (GRS_OBJS): Remove rust-early-name-resolver.o.
+ * expand/rust-macro-builtins-helpers.h: Remove inclusion of
+ rust-early-name-resolver.h.
+ * expand/rust-macro-builtins.cc: Likewise.
+ * expand/rust-macro-expand.cc: Likewise.
+ * expand/rust-macro-expand.h: Likewise.
+ * resolve/rust-early-name-resolver.cc: Removed.
+ * resolve/rust-early-name-resolver.h: Removed.
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/tree/rust-hir-item.h: add unsafe helper
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): pass in abi and unsafe
+ * typecheck/rust-tyty.cc (BaseType::monomorphized_clone): likewise
+ (FnPtr::as_string): emit more info
+ (FnPtr::clone): update ctor call
+ * typecheck/rust-tyty.h: new ctor params
+ * typecheck/rust-unify.cc (UnifyRules::expect_fnptr): check abi and unsafe
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-unify.cc (UnifyRules::expect_reference): remove clone
+ (UnifyRules::expect_pointer): likewise
+ (UnifyRules::expect_slice): likewise
+ (UnifyRules::expect_tuple): likewise
+ (UnifyRules::expect_int): likewise
+ (UnifyRules::expect_uint): likewise
+ (UnifyRules::expect_float): likewise
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * Make-lang.in (GRS_OBJS): Remove entries.
+ * rust-lang.cc: Remove inclusion of "rust-ast-resolve-item.h".
+ (run_rust_tests): Remove call to rust_simple_path_resolve_test.
+ * resolve/rust-ast-resolve-base.cc: Removed.
+ * resolve/rust-ast-resolve-base.h: Removed.
+ * resolve/rust-ast-resolve-expr.cc: Removed.
+ * resolve/rust-ast-resolve-expr.h: Removed.
+ * resolve/rust-ast-resolve-implitem.h: Removed.
+ * resolve/rust-ast-resolve-item.cc: Removed.
+ * resolve/rust-ast-resolve-item.h: Removed.
+ * resolve/rust-ast-resolve-path.cc: Removed.
+ * resolve/rust-ast-resolve-path.h: Removed.
+ * resolve/rust-ast-resolve-pattern.cc: Removed.
+ * resolve/rust-ast-resolve-pattern.h: Removed.
+ * resolve/rust-ast-resolve-stmt.cc: Removed.
+ * resolve/rust-ast-resolve-stmt.h: Removed.
+ * resolve/rust-ast-resolve-struct-expr-field.cc: Removed.
+ * resolve/rust-ast-resolve-struct-expr-field.h: Removed.
+ * resolve/rust-ast-resolve-toplevel.h: Removed.
+ * resolve/rust-ast-resolve-type.cc: Removed.
+ * resolve/rust-ast-resolve-type.h: Removed.
+ * resolve/rust-ast-resolve.cc: Removed.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Use
+ resolve_type_path_like in overloads for TypePath,
+ StructExprStruct, StructExprStructBase, and
+ StructExprStructFields.
+ (resolve_type_path_like): New static function based off
+ Late::visit overload for TypePath.
+ * util/rust-unwrap-segment.h (unwrap_segment_error_string): New
+ inline static function definitions.
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::visit): add guard
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-context.h: add assertions for context peeks
+ * backend/rust-compile-expr.cc (CompileExpr::visit): check for valid loop context
+ (CompileExpr::array_copied_expr): just reuse array tyty capacity value
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): catch error
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * checks/errors/rust-readonly-check.cc (collect_assignment_tuple): Implement
+ read-only checker for tuple patterns with rest pattern.
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-var-decl.h (CompileVarDecl::visit(TuplePattern)): Implement
+ variable declaration bindings for tuple patterns with rest pattern (i.e.
+ TuplePatternItemsHasRest).
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * util/rust-attribute-values.h
+ (Attributes::RUSTC_ALLOW_CONST_FN_UNSTABLE): New static
+ constexpr member variable.
+ * util/rust-attributes.cc (__definitions): Add entry for
+ RUSTC_ALLOW_CONST_FN_UNSTABLE.
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-unify.cc (UnifyRules::commit): commit hook update
+ (UnifyRules::go): insert implicit infer const types
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-unify.cc (UnifyRules::go): unwrap the const type
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-base.cc (walk_types_to_constrain): track the ref as well
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-subst.cc: const generic arguments dont have a value yet
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty.cc (VariantDef::clone): fix formatting
+ (VariantDef::monomorphized_clone): likewise
+ * typecheck/rust-tyty.h: likewise
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty.cc (InferType::can_eq): remove
+ (ErrorType::can_eq): likewise
+ (ADTType::can_eq): likewise
+ (TupleType::can_eq): likewise
+ (FnType::can_eq): likewise
+ (FnPtr::can_eq): likewise
+ (ClosureType::can_eq): likewise
+ (ArrayType::can_eq): likewise
+ (SliceType::can_eq): likewise
+ (BoolType::can_eq): likewise
+ (IntType::can_eq): likewise
+ (UintType::can_eq): likewise
+ (FloatType::can_eq): likewise
+ (USizeType::can_eq): likewise
+ (ISizeType::can_eq): likewise
+ (CharType::can_eq): likewise
+ (ReferenceType::can_eq): likewise
+ (PointerType::can_eq): likewise
+ (ParamType::can_eq): likewise
+ (ConstType::can_eq): likewise
+ (OpaqueType::can_eq): likewise
+ (StrType::can_eq): likewise
+ (NeverType::can_eq): likewise
+ (PlaceholderType::can_eq): likewise
+ (ProjectionType::can_eq): likewise
+ (DynamicObjectType::can_eq): likewise
+ * typecheck/rust-tyty.h: remove can_eq
+ * typecheck/rust-tyty-cmp.h: Removed.
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty.cc (ParamType::is_equal): uses types_compatable
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-unify.cc (unify_error_type_node): new static node
+ (UnifyRules::go): likewise
+ (UnifyRules::expect_inference_variable): likewise
+ (UnifyRules::expect_adt): likewise
+ (UnifyRules::expect_str): likewise
+ (UnifyRules::expect_reference): likewise
+ (UnifyRules::expect_pointer): likewise
+ (UnifyRules::expect_param): likewise
+ (UnifyRules::expect_array): likewise
+ (UnifyRules::expect_slice): likewise
+ (UnifyRules::expect_fndef): likewise
+ (UnifyRules::expect_fnptr): likewise
+ (UnifyRules::expect_tuple): likewise
+ (UnifyRules::expect_bool): likewise
+ (UnifyRules::expect_char): likewise
+ (UnifyRules::expect_int): likewise
+ (UnifyRules::expect_uint): likewise
+ (UnifyRules::expect_float): likewise
+ (UnifyRules::expect_isize): likewise
+ (UnifyRules::expect_usize): likewise
+ (UnifyRules::expect_never): likewise
+ (UnifyRules::expect_placeholder): likewise
+ (UnifyRules::expect_projection): likewise
+ (UnifyRules::expect_dyn): likewise
+ (UnifyRules::expect_closure): likewise
+ (UnifyRules::expect_opaque): likewise
+ (UnifyRules::expect_const): likewise
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-unify.cc (UnifyRules::Resolve): check for success
+ (UnifyRules::expect_inference_variable): dont clone
+ (UnifyRules::expect_adt): likewise
+ (UnifyRules::expect_str): likewise
+ (UnifyRules::expect_reference): likewise
+ (UnifyRules::expect_pointer): likewise
+ (UnifyRules::expect_param): likewise
+ (UnifyRules::expect_array): likewise
+ (UnifyRules::expect_slice): likewise
+ (UnifyRules::expect_fndef): likewise
+ (UnifyRules::expect_fnptr): likewise
+ (UnifyRules::expect_tuple): likewise
+ (UnifyRules::expect_bool): likewise
+ (UnifyRules::expect_char): likewise
+ (UnifyRules::expect_int): likewise
+ (UnifyRules::expect_uint): likewise
+ (UnifyRules::expect_float): likewise
+ (UnifyRules::expect_isize): likewise
+ (UnifyRules::expect_usize): likewise
+ (UnifyRules::expect_never): likewise
+ (UnifyRules::expect_placeholder): likewise
+ (UnifyRules::expect_projection): likewise
+ (UnifyRules::expect_dyn): likewise
+ (UnifyRules::expect_closure): likewise
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty.cc (BaseType::satisfies_bound): use types_compatable instead
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-type-util.cc (types_compatable): add check bounds flag
+ (unify_site_and): likewise
+ * typecheck/rust-type-util.h (types_compatable): likewise
+ (unify_site_and): likewise
+ * typecheck/rust-tyty-bounds.cc: likewise
+ * typecheck/rust-unify.cc (UnifyRules::UnifyRules): likewise
+ (UnifyRules::Resolve): likewise
+ (UnifyRules::resolve_subtype): likewise
+ (UnifyRules::go): likewise
+ * typecheck/rust-unify.h: likewise
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-path-probe.cc (PathProbeType::process_impl_item_candidate):
+ refactor to types_compatable
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-unify.cc (UnifyRules::expect_inference_variable): dont commit
+ (UnifyRules::expect_adt): likewise
+ (UnifyRules::expect_bool): likewise
+ (UnifyRules::expect_char): likewise
+ (UnifyRules::expect_int): likewise
+ (UnifyRules::expect_uint): likewise
+ (UnifyRules::expect_float): likewise
+ (UnifyRules::expect_isize): likewise
+ (UnifyRules::expect_usize): likewise
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.h: remove const
+ * backend/rust-compile-expr.cc: likewise
+ * backend/rust-compile.cc (HIRCompileBase::coerce_to_dyn_object): likewise
+ * typecheck/rust-hir-type-bounds.h: likewise
+ * typecheck/rust-type-util.cc (lookup_associated_impl_block): likewise
+ * typecheck/rust-type-util.h (lookup_associated_impl_block): likewise
+ * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::TypeBoundsProbe): likewise
+ (TypeBoundsProbe::Probe): likewise
+ * typecheck/rust-tyty-cmp.h: likewise
+ * typecheck/rust-tyty-subst.cc (SubstitutionRef::monomorphize): likewise
+ * typecheck/rust-tyty.cc (BaseType::satisfies_bound): likewise
+ (BaseType::bounds_compatible): likewise
+ (VariantDef::clone): likewise
+ (VariantDef::monomorphized_clone): likewise
+ (OpaqueType::is_equal): likewise
+ (DynamicObjectType::is_equal): likewise
+ * typecheck/rust-tyty.h: likewise
+
+2025-10-30 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-coercion.cc (TypeCoercionRules::select): respect try flag
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-early-name-resolver-2.0.cc (Early::finalize_rebind_import):
+ Replace assert with early break and remove early return.
+ (Early::visit): Check for unsuffixed lower self list.
+ * resolve/rust-early-name-resolver-2.0.h: Add visit function prototype.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-early-name-resolver-2.0.cc (Early::visit): Emit an error
+ on top level rebind self use declaration.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * Make-lang.in (GRS_OBJS): Add "rust-resolve-builtins.o".
+ * resolve/rust-late-name-resolver-2.0.cc: Include
+ "rust-resolve-builtins.h".
+ (next_node_id): Remove function.
+ (next_hir_id): Likewise.
+ (Late::setup_builtin_types): Likewise.
+ (Late::go): Use Builtins::setup_type_ctx instead of
+ Late::setup_builtin_types.
+ * resolve/rust-late-name-resolver-2.0.h
+ (Late::setup_builtin_types): Remove function.
+ * rust-session-manager.cc: Include "rust-resolve-builtins.h".
+ (Session::expansion): Call Builtins::setup_lang_prelude.
+ * resolve/rust-resolve-builtins.cc: New file.
+ * resolve/rust-resolve-builtins.h: New file.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h (Parser::left_denotation): Remove
+ usage of parse_tuple_index_expr_float.
+ (Parser::parse_closure_expr_pratt): Remove function.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * rust-session-manager.cc (Session::compile_crate): Move the AST dump
+ after parser error check.
+
+2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-expression-yeast.cc (ExpressionYeast::dispatch): Rename to...
+ (ExpressionYeast::reseat): ...this.
+ (ExpressionYeast::visit): Remove.
+ * ast/rust-expression-yeast.h: Inherit from PointerVisitor, override reseat instead
+ of declaring dispatch.
+
+2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in: Compile it.
+ * ast/rust-builtin-ast-nodes.h: Add missing methods for getting pointers.
+ * ast/rust-expr.h: Likewise.
+ * ast/rust-item.h: Likewise.
+ * ast/rust-path.h: Likewise.
+ * ast/rust-pattern.h: Likewise.
+ * ast/rust-type.h: Likewise.
+ * ast/rust-ast-pointer-visitor.cc: New file.
+ * ast/rust-ast-pointer-visitor.h: New file.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-expr.h (class TupleIndexExpr): Store strip information.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * checks/errors/borrowck/rust-bir-builder-internal.h: Remove
+ inclusion of "rust-name-resolver.h".
+ (BuilderContext::resolver): Change type to nr2.0 resolver.
+ (BuilderContext::BuilderContext): Change initialization of
+ resolver reference.
+ (AbstractBuilder::resolve_label): Assume name resolution 2.0 is
+ enabled.
+ (AbstractBuilder::resolve_variable): Likewise.
+ (AbstractBuilder::resolve_variable_or_fn): Likewise.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * checks/errors/rust-hir-pattern-analysis.cc: Remove inclusion
+ of "options.h".
+ (PatternChecker::PatternChecker): Change initialization of
+ resolver reference.
+ (PatternChecker::visit): Assume name resolution 2.0 is enabled.
+ * checks/errors/rust-hir-pattern-analysis.h: Include nr2.0
+ header instead of nr1.0 header.
+ (PatternChecker::resolver): Change type to nr2.0 resolver.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust-session-manager.cc: Remove inclusion of name resolution
+ 1.0 headers.
+ (Session::compile_crate): Assume name resolution 2.0 is enabled.
+ (Session::expansion): Likewise.
+ (Session::load_extern_crate): Likewise.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * checks/errors/privacy/rust-privacy-check.cc: Adjust includes.
+ (Resolver::resolve): Pass 2.0 name resolution context to
+ VisibilityResolver and PrivacyReporter.
+ * checks/errors/privacy/rust-privacy-reporter.cc
+ (PrivacyReporter::PrivacyReporter): Change type of resolver
+ parameter.
+ (is_child_module): Remove static function.
+ (PrivacyReporter::check_for_privacy_violation): Assume nr2.0 is
+ enabled and handle removal of is_child_module.
+ * checks/errors/privacy/rust-privacy-reporter.h: Adjust
+ includes.
+ (PrivacyReporter::PrivacyReporter): Change type of resolver
+ parameter.
+ (PrivacyReporter::resolver): Change member variable type.
+ * checks/errors/privacy/rust-visibility-resolver.cc: Adjust
+ includes.
+ (VisibilityResolver::VisibilityResolver): Change type of
+ resolver parameter.
+ (VisibilityResolver::resolve_module_path): Assume nr2.0 is
+ enabled.
+ * checks/errors/privacy/rust-visibility-resolver.h: Adjust
+ includes.
+ (VisibilityResolver::VisibilityResolver): Change type of
+ resolver parameter.
+ (VisibilityResolver::resolver): Change member variable type.
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * ast/rust-pattern.h:
+ - Add a new base abstract class `PatternItems` which are used by pattern items class
+ class derivatives for `TuplePattern`, `TupleStructPattern` & `SlicePattern`.
+ - Standardized the derived class names to have `HasRest` or `NoRest` as suffixes.
+ - Values for the common `ItemType` enum is updated to `HAS_REST` or `NO_REST`.
+ * ast/rust-pattern.cc: Renamed the classes accordingly.
+ * ast/rust-ast-collector.cc: Renamed the classes accordingly.
+ * ast/rust-ast-collector.h: Renamed the classes accordingly.
+ * ast/rust-ast-full-decls.h: Renamed the classes accordingly.
+ * ast/rust-ast-visitor.cc: Renamed the classes accordingly.
+ * ast/rust-ast-visitor.h: Renamed the classes accordingly.
+ * ast/rust-desugar-for-loops.cc: Renamed the classes accordingly.
+ * ast/rust-desugar-question-mark.cc: Renamed the classes accordingly.
+ * expand/rust-cfg-strip.cc: Renamed the classes accordingly.
+ * expand/rust-cfg-strip.h: Renamed the classes accordingly.
+ * expand/rust-derive-clone.cc: Renamed the classes accordingly.
+ * expand/rust-derive-cmp-common.cc: Renamed the classes accordingly.
+ * expand/rust-derive-hash.cc: Renamed the classes accordingly.
+ * expand/rust-derive-ord.cc: Renamed the classes accordingly.
+ * expand/rust-derive-partial-eq.cc: Renamed the classes accordingly.
+ * expand/rust-derive.h: Renamed the classes accordingly.
+ * expand/rust-expand-visitor.cc: Renamed the classes accordingly.
+ * expand/rust-expand-visitor.h: Renamed the classes accordingly.
+ * hir/rust-ast-lower-base.cc: Renamed the classes accordingly.
+ * hir/rust-ast-lower-base.h: Renamed the classes accordingly.
+ * hir/rust-ast-lower-pattern.cc: Renamed the classes accordingly.
+ * hir/tree/rust-hir-pattern.h: Renamed the classes accordingly.
+ * parse/rust-parse-impl.h: Renamed the classes accordingly.
+ * resolve/rust-ast-resolve-base.cc: Renamed the classes accordingly.
+ * resolve/rust-ast-resolve-base.h: Renamed the classes accordingly.
+ * resolve/rust-ast-resolve-pattern.cc: Renamed the classes accordingly.
+ * util/rust-attributes.cc: Renamed the classes accordingly.
+ * util/rust-attributes.h: Renamed the classes accordingly.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Use
+ should_have_str instead of has_str.
+ * ast/rust-ast.cc (Token::as_string): Likewise.
+ * expand/rust-macro-builtins-offset-of.cc
+ (MacroBuiltin::offset_of_handler): Likewise.
+ * lex/rust-lex.cc (Lexer::dump_and_skip): Likewise.
+ * ast/rust-ast.h (class Token): Remove dead code.
+ (Token::has_str): Remove function.
+ (Token::should_have_str): New function.
+ * lex/rust-token.cc (Token::get_str): Remove function
+ definition.
+ * lex/rust-token.h: Include "rust-diagnostics.h".
+ (Token::str): Change type from std::unique_ptr<std::string> to
+ std::string.
+ (Token::Token): Adjust initialization of str member variable and
+ the type of the parameter used to initialize it.
+ (Token::make_identifier): Accept std::string instead of rvalue
+ reference to std::string.
+ (Token::make_int): Likewise.
+ (Token::make_float): Likewise.
+ (Token::make_string): Likewise.
+ (Token::make_byte_string): Likewise.
+ (Token::make_raw_string): Likewise.
+ (Token::make_inner_doc_comment): Likewise.
+ (Token::make_outer_doc_comment): Likewise.
+ (Token::make_lifetime): Likewise.
+ (Token::get_str): Add definition to function declaration.
+ (Token::has_str): Remove member function.
+ (Token::should_have_str): Handle INNER_DOC_COMMENT and
+ OUTER_DOC_COMMENT.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-macro-builtins-format-args.cc
+ (format_args_parse_arguments): Split format expression parsing
+ into...
+ (format_args_parse_expr): ...a new function here, while handling
+ eager expansion.
+ (MacroBuiltin::format_args_handler): Use format_args_parse_expr.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_expr): Avoid skipping
+ or splitting tokens.
+ (Parser::null_denotation): Assume initial token was not skipped
+ and adjust function signature to match. Use
+ parse_path_in_expression instead of
+ parse_path_in_expression_pratt and handle SCOPE_RESOLUTION.
+ (Parser::parse_path_in_expression_pratt): Remove function.
+ * parse/rust-parse.h (null_denotation): Remove initial token
+ parameter.
+ (parse_path_in_expression_pratt): Remove function.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Use as
+ member function.
+ (TypeCoercionRules::coerce_borrowed_pointer): Likewise.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion):
+ Move nevertype coercion from here...
+ (TypeCoercionRules::coerce_never): ... to here.
+ * typecheck/rust-coercion.h: Add function prototype.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Adapt
+ call to new return type.
+ (TypeCoercionRules::coerce_unsized): Change error handling.
+ * typecheck/rust-coercion.h: Update function prototype and add new
+ CoerceUnsizedError error type.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Refactor
+ common return statement.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Remove
+ unused assignment.
+ * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_segments):
+ Likewise.
+ * typecheck/rust-tyty.cc (ParamType::handle_substitions): Likewise.
+ * typecheck/rust-unify.cc (UnifyRules::go): Likewise.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait):
+ Construct value in place.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-ast-resolve-stmt.cc (ResolveStmt::visit): Remove
+ unused copy.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::generate_closure_fntype):
+ Unwrap the optional.
+ * backend/rust-compile.cc: Change return type container. Adapt code to
+ new return type.
+ * typecheck/rust-hir-dot-operator.cc: Likewise.
+ * typecheck/rust-hir-path-probe.cc: Likewise.
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItemWithTrait::visit):
+ Likewise.
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit):
+ Likewise.
+ * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::contains_item):
+ Likewise.
+ (TypeBoundPredicate::lookup_associated_item): Likewise.
+ (TypeBoundPredicateItem::get_parent): Likewise.
+ (TypeBoundPredicate::lookup_associated_type): Likewise.
+ * typecheck/rust-tyty.cc (BaseType::satisfies_bound): Likewise.
+ * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::visit): Change
+ return type.
+ * typecheck/rust-tyty.h: Likewise.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * typecheck/rust-casts.cc (TypeCastRules::cast_rules): Authorize
+ cast from function pointer to integer like type.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * typecheck/rust-hir-type-check-base.cc (walk_type_to_constrain): Walk
+ through all kind of type to collect ty leaves.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-type.h: Prevent reconstruction on null pointers.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * util/rust-attribute-values.h (Attributes::SIMD_TEST): Remove
+ static constexpr member variable.
+ * util/rust-attributes.cc (__definitions): Remove entry for
+ SIMD_TEST.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_identifier_pattern):
+ Use parse_pattern_no_alt to parse identifier pattern
+ subpatterns.
+ (Parser::parse_ident_leading_pattern): Likewise.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-fmt.cc (Pieces::collect): Handle changes to ffi
+ interface.
+ (Pieces::~Pieces): Remove function definition.
+ (Pieces::Pieces): Likewise.
+ (Pieces::operator=): Likewise.
+ * ast/rust-fmt.h: Include "optional.h".
+ (rust_ffi_alloc): New extern "C" function declaration.
+ (rust_ffi_dealloc): Likewise.
+ (class FFIVec): New class.
+ (class FFIOpt): Likewise.
+ (RustHamster::RustHamster): New constructor accepting const
+ std::string reference.
+ (struct FormatSpec): Use FFIOpt.
+ (struct PieceSlice): Remove struct.
+ (struct RustString): Likewise.
+ (struct FormatArgsHandle): Likewise.
+ (collect_pieces): Change function signature.
+ (clone_pieces): Likewise.
+ (destroy_pieces): Remove extern "C" function declaration.
+ (Pieces::~Pieces): Remove function declaration.
+ (Pieces::operator=): Likewise.
+ (Pieces::get_pieces): Handle changes to class fields.
+ (Pieces::Pieces): Remove copy and move constructor declarations,
+ adjust signature of remaining constructor declaration.
+ (Pieces::pieces_vector): Remove member variable.
+ (Pieces::handle): Likewise.
+ (Pieces::data): Add member variable.
+ * expand/rust-macro-builtins-asm.cc (expand_inline_asm_strings):
+ Use references to avoid copying.
+
+2025-10-30 lishin <lishin1008@gmail.com>
+
+ * backend/rust-compile-pattern.cc (CompilePatternLet::visit):
+ Handle tuple destructuring containing by-ref.
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * hir/tree/rust-hir-pattern.h: Add SlicePatternItems base class and
+ SlicePatternItemsNoRest/SlicePatternItemsHasRest derived classes.
+ Update SlicePattern to hold patterns using the new classes.
+ * hir/tree/rust-hir-full-decls.h: Declare new classes.
+ * hir/tree/rust-hir.cc: Add visits for new classes.
+ * hir/tree/rust-hir-visitor.h: Add visits for new classes.
+ * hir/tree/rust-hir-visitor.cc: Implement visits for new classes.
+ * hir/rust-hir-dump.h: Add visits for new classes.
+ * hir/rust-hir-dump.cc: Implement Dump::visit for new classes.
+ * hir/rust-ast-lower-base.h: Declare new lower_slice_pattern_no_rest/has_rest
+ methods.
+ * hir/rust-ast-lower-base.cc: Implement lower_slice_pattern_no_rest/has_rest
+ to lower AST slice pattern items to HIR.
+ * hir/rust-ast-lower-pattern.cc: Update ASTLoweringPattern::visit for
+ SlicePattern to use new lowering methods.
+ * backend/rust-compile-pattern.cc: Update CompilePatternCheckExpr::visit
+ and CompilePatternBindings::visit for SlicePattern to handle
+ SlicePatternItemsNoRest/HasRest.
+ * checks/errors/borrowck/rust-bir-builder-pattern.cc: Update
+ PatternBindingBuilder::visit for SlicePattern to iterate members correctly.
+ * checks/errors/borrowck/rust-bir-builder-struct.h: Add visits for new
+ classes.
+ * checks/errors/borrowck/rust-function-collector.h: Add visits for new
+ classes.
+ * checks/errors/rust-const-checker.h: Add visits for new classes.
+ * checks/errors/rust-const-checker.cc: Implement empty visits for new classes.
+ * checks/errors/rust-hir-pattern-analysis.h: Add visits for new classes.
+ * checks/errors/rust-hir-pattern-analysis.cc: Implement empty visits for new
+ classes.
+ * checks/errors/rust-unsafe-checker.h: Add visits for new classes.
+ * checks/errors/rust-unsafe-checker.cc: Implement empty visits for new
+ classes.
+ * typecheck/rust-hir-type-check-pattern.cc: Update TypeCheckPattern::visit
+ for SlicePattern to handle SlicePatternItemsNoRest/HasRest.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust-session-manager.cc (Session::compile_crate): Collect lang
+ items after expansion.
+
+2025-10-30 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * Make-lang.in: Replace old read-only checker with new implementation.
+ * checks/errors/rust-readonly-check.cc (ReadonlyChecker::ReadonlyChecker):
+ Replace old read-only checker with new implementation.
+ * checks/errors/rust-readonly-check.h:
+ Replace old read-only checker with new implementation.
+ * rust-session-manager.cc (Session::compile_crate):
+ Switch to new read-only checker.
+ * checks/errors/rust-readonly-check2.cc: Removed.
+ * checks/errors/rust-readonly-check2.h: Removed.
+
+2025-10-30 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * checks/errors/rust-readonly-check2.cc (ReadonlyChecker::check_variable):
+ Read-only check if the variable is mutable type.
+ (ReadonlyChecker::is_mutable_type): Read-only check if the variable is mutable type.
+ * checks/errors/rust-readonly-check2.h: Read-only check if the variable is mutable type.
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc(ClosureParamInfer(IdentifierPattern)):
+ Resolve subpattern types for IdentifierPattern.
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-pattern.cc(CompilePatternLet::visit(IdentifierPattern)):
+ Add support for subpatterns.
+ * backend/rust-compile-var-decl.h(CompileVarDecl::visit(IdentifierPattern)):
+ Implement compilation for subpatterns.
+
+2025-10-30 lishin <lishin1008@gmail.com>
+
+ * typecheck/rust-hir-dot-operator.cc (MethodResolver::Select):
+ Skip asserts by checking candidate type and using early-continue.
+ (MethodResolver::try_select_predicate_candidates):
+ Skip invalid candidates.
+
+2025-10-30 lishin <lishin1008@gmail.com>
+
+ * rust-gcc.cc (constructor_expression):
+ Ensure vec_alloc reserves at least one element.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast.cc (Attribute::check_cfg_predicate): Emit an error with
+ empty cfg_attr input.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-forever-stack.hxx
+ (ForeverStack::resolve_segments): Remove usage of optional
+ reference, allow non-final path segments to resolve to types
+ even outside the type namespace, and allow resolution to
+ progress past non-final path segments which resolve to modules.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_stmt_or_expr): Add null check
+ on parse_macro_invocation_partial call.
+ * ast/rust-path.cc (Path::convert_to_simple_path): Do not exclude
+ capitalized "Self".
+
+2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-fragment.cc (Fragment::is_pattern_fragment): New function.
+ (Fragment::take_pattern_fragment): Likewise.
+ (Fragment::assert_single_fragment): Likewise.
+ * ast/rust-ast-fragment.h: Declare them.
+ * ast/rust-ast.cc (SingleASTNode::SingleASTNode): Add new constructor for pattern
+ single AST nodes.
+ (SingleASTNode::operator=): Handle patterns.
+ (SingleASTNode::accept_vis): Likewise.
+ (SingleASTNode::is_error): Likewise.
+ (SingleASTNode::as_string): Likewise.
+ * ast/rust-ast.h: Add get_pattern_ptr() functions.
+ * ast/rust-expr.h: Likewise.
+ * ast/rust-item.h: Likewise.
+ * ast/rust-pattern.h: Likewise.
+ * ast/rust-stmt.h: Likewise.
+ * expand/rust-expand-visitor.cc (derive_item): Use new API enum values.
+ (expand_item_attribute): Likewise.
+ (expand_stmt_attribute): Likewise.
+ (ExpandVisitor::maybe_expand_pattern): New function.
+ (ExpandVisitor::expand_closure_params): Handle patterns.
+ (ExpandVisitor::visit): Add new visitors for patterns and missed exprs.
+ * expand/rust-expand-visitor.h: Declare them.
+ * expand/rust-macro-expand.cc (transcribe_pattern): New function.
+ (transcribe_context): Call it.
+ * expand/rust-macro-expand.h (struct MacroExpander): New Context type.
+
+2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h: Change NodeType to enum class Kind.
+ * ast/rust-ast-fragment.cc: Use new names.
+ * ast/rust-ast-fragment.h: Likewise.
+ * ast/rust-ast.cc (SingleASTNode::SingleASTNode): Likewise.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h
+ (Parser::parse_identifier_or_keyword_token): Record error on
+ failure.
+
+2025-10-30 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * resolve/rust-ast-resolve-stmt.h:
+ Add name resolution processing for discriminant values.
+
+2025-10-30 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): fix error code
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-cfg-strip.cc: Include "rust-macro-expand.h".
+ (fails_cfg): Rename to...
+ (CfgStrip::fails_cfg): ...here and handle test attributes.
+ (fails_cfg_with_expand): Rename to...
+ (CfgStrip::fails_cfg_with_expand): ...here and handle test
+ attributes.
+ * expand/rust-cfg-strip.h (struct ExpansionCfg): Forward
+ declare.
+ (CfgStrip::fails_cfg): New member function.
+ (CfgStrip::fails_cfg_with_expand): Likewise.
+ (CfgStrip::CfgStrip): Accept reference to ExpansionCfg.
+ (CfgStrip::expansion_cfg): New member variable.
+ * rust-session-manager.cc (Session::expansion): Pass
+ ExpansionCfg instance to CfgStrip constructor.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-early-name-resolver-2.0.cc (Early::finalize_rebind_import):
+ Do not abort on wildcard patterns.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-expr.h: Add const getters to llvm members.
+ * hir/rust-ast-lower-expr.cc (check_llvm_asm_support): Check llvm_asm
+ usage validity.
+ (ASTLoweringExpr::visit): Emit an error message instead of aborting.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-builtins-asm.cc (parse_llvm_clobbers): Expect a
+ comma between clobbers.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-builtins-asm.cc (parse_asm): Simplify expression.
+ (parse_llvm_asm): Likewise.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast.h (Stmt::get_node_id): Make virtual.
+ (Type::get_node_id): Likewise.
+ (AssociatedItem::get_node_id): New virtual member function.
+ * ast/rust-expr.h (TypeCastExpr::get_casted_expr_ptr): New
+ member function.
+ (TypeCastExpr::get_type_to_cast_to_ptr): Likewise.
+ (ClosureExprInner::get_definition_expr_ptr): Likewise.
+ * ast/rust-item.h (TypeAlias::get_node_id): New member function
+ to override AssociatedItem::get_node_id.
+ (ConstantItem::get_node_id): Likewise.
+ * expand/rust-expand-visitor.cc
+ (ExpandVisitor::maybe_expand_expr): Adjust
+ macro_invoc_expect_id.
+ (ExpandVisitor::maybe_expand_type): Likewise and add an overload
+ for std::unique_ptr<TypeNoBounds>.
+ (ExpandVisitor::visit): Check macro_invoc_expect_id and
+ generally improve visitors so that the testsuite will still
+ pass.
+ * expand/rust-expand-visitor.h (ExpandVisitor::ExpandVisitor):
+ Initialize member variable macro_invoc_expect_id.
+ (ExpandVisitor::maybe_expand_type): Add an overload for
+ std::unique_ptr<TypeNoBounds>.
+ (ExpandVisitor::expand_macro_children): Adjust
+ macro_invoc_expect_id.
+ (ExpandVisitor::visit): Add an overload for TypeCastExpr.
+ (ExpandVisitor::macro_invoc_expect_id): New member variable.
+
+2025-10-30 lishin <lishin1008@gmail.com>
+
+ * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit):
+ Check upper compare operator.
+ * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit):
+ Handle lowering of exclusive range pattern.
+ * hir/tree/rust-hir-pattern.h (class RangePattern):
+ Add support for exclusive ranges in HIR representation.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-macro-expand.cc (transcribe_expression): Parse any
+ outer attributes before parsing an expression.
+ * parse/rust-parse.h (Parser::parse_outer_attributes): Make
+ public.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-expr.h (struct TupleClobber): Add constructor.
+ * backend/rust-compile-context.h (struct fncontext): Likewise.
+ * typecheck/rust-hir-dot-operator.h: Likewise.
+ * typecheck/rust-tyty-variance-analysis-private.h (struct Constraint):
+ Likewise.
+ * typecheck/rust-unify.h: Likewise.
+ * ast/rust-ast-builder.cc (Builder::new_lifetime_param): Add memory
+ reservation and construct in place.
+ (Builder::new_generic_args): Likewise.
+ * ast/rust-ast-collector.cc (TokenCollector::newline): Likewise.
+ (TokenCollector::indentation): Likewise.
+ (TokenCollector::comment): Likewise.
+ * ast/rust-desugar-apit.cc: Likewise.
+ * ast/rust-path.cc (Path::convert_to_simple_path): Likewise.
+ (TypePath::as_simple_path): Likewise.
+ * ast/rust-path.h: Likewise.
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): Likewise.
+ (TyTyResolveCompile::create_dyn_obj_record): Likewise.
+ * checks/errors/rust-hir-pattern-analysis.cc (Matrix::specialize):
+ Likewise.
+ (WitnessMatrix::apply_constructor): Likewise.
+ (check_match_usefulness): Likewise.
+ * expand/rust-derive-clone.cc (DeriveClone::clone_fn): Likewise.
+ * expand/rust-macro-builtins-asm.cc (parse_clobber_abi): Likewise.
+ * expand/rust-macro-expand.cc (MacroExpander::parse_proc_macro_output):
+ Likewise.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_generic_args):
+ Likewise.
+ (ASTLoweringBase::lower_extern_block): Likewise.
+ * hir/rust-ast-lower-enumitem.h: Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ * hir/rust-ast-lower-extern.h: Likewise.
+ * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): Likewise.
+ (ASTLowerTraitItem::visit): Likewise.
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise.
+ * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit): Likewise.
+ * hir/rust-ast-lower.cc (ASTLowering::go): Likewise.
+ (ASTLoweringBlock::visit): Likewise.
+ (ASTLoweringIfLetBlock::desugar_iflet): Likewise.
+ (ASTLoweringExprWithBlock::visit): Likewise.
+ (ASTLowerPathInExpression::visit): Likewise.
+ (ASTLowerQualPathInExpression::visit): Likewise.
+ * hir/tree/rust-hir.cc (PathPattern::convert_to_simple_path): Likewise.
+ (TypePath::as_simple_path): Likewise.
+ * metadata/rust-export-metadata.cc (ExportContext::emit_function):
+ Likewise.
+ * parse/rust-parse-impl.h (Parser::parse_decl_macro_def): Likewise.
+ (Parser::parse_lifetime_params): Likewise.
+ * resolve/rust-ast-resolve-item.cc (ResolveTraitItems::visit):
+ Likewise.
+ (ResolveItem::visit): Likewise.
+ (flatten_list): Likewise.
+ * resolve/rust-ast-resolve-pattern.cc (PatternDeclaration::visit):
+ Likewise.
+ * typecheck/rust-autoderef.cc (AutoderefCycle::try_autoderefed):
+ Likewise.
+ * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsized):
+ Likewise.
+ * typecheck/rust-hir-dot-operator.cc: Likewise.
+ * typecheck/rust-hir-path-probe.cc: Likewise.
+ * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait):
+ Likewise.
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit):
+ Likewise.
+ (TypeCheckExpr::resolve_fn_trait_call): Likewise.
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelExternItem::visit):
+ Likewise.
+ (TypeCheckImplItem::visit): Likewise.
+ * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit):
+ Likewise.
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit):
+ Likewise.
+ * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::resolve):
+ Likewise.
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit):
+ Likewise.
+ * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn):
+ Likewise.
+ * typecheck/rust-typecheck-context.cc (TypeCheckContext::push_return_type):
+ Likewise.
+ (TypeCheckContext::insert_associated_impl_mapping): Likewise.
+ * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::scan): Likewise.
+ (TypeBoundsProbe::add_trait_bound): Likewise.
+ (TypeBoundPredicate::operator=): Likewise.
+ (TypeBoundPredicateItem::get_tyty_for_receiver): Likewise.
+ (TypeBoundPredicate::get_associated_type_items): Likewise.
+ * typecheck/rust-tyty-call.cc (TypeCheckMethodCallExpr::go): Likewise.
+ * typecheck/rust-tyty-subst.cc (SubstitutionRef::clone_substs):
+ Likewise.
+ (SubstitutionRef::infer_substitions): Likewise.
+ (SubstitutionRef::are_mappings_bound): Likewise.
+ * typecheck/rust-tyty-variance-analysis.cc (GenericTyPerCrateCtx::query_generic_variance):
+ Likewise.
+ (GenericTyVisitorCtx::add_constraint): Likewise.
+ * typecheck/rust-tyty.cc (FnPtr::clone): Likewise.
+ (DynamicObjectType::get_object_items): Likewise.
+ * typecheck/rust-unify.cc (UnifyRules::Resolve): Likewise.
+ (UnifyRules::go): Likewise.
+ (UnifyRules::expect_tuple): Likewise.
+ * util/rust-canonical-path.h: Likewise.
+ * util/rust-token-converter.cc (convert): Likewise.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * util/bi-map.h: Add include directive for required declarations.
+ * util/fnv-hash.h: Likewise.
+ * util/rust-dump.h: Likewise.
+ * util/rust-inline-visitor.h: Likewise.
+ * util/rust-unwrap-segment.h: Likewise.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * util/rust-lang-item.h (RUST_LANG_ITEM_H): Add header guards.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * parse/rust-parse.h: Change class to struct for friend qualification.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * checks/lints/rust-lint-marklive-base.h (RUST_HIR_LIVENESS_BASE):
+ Remove header includes.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-cond-compilation.h: Delete copy constructor for
+ ConfigurationAll and ConfigurationAny.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-type.h: Update member instead of parameter
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-cond-compilation.h: Move vector instead of passing it by
+ value.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-pattern.h: Include header directly.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-cond-compilation.h: Copy cfg_attrs
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-formatting.h (RUST_AST_FORMATTING_H): Include required
+ headers directly.
+
+2025-10-30 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * util/rust-attributes.cc (Attributes::extract_string_literal):
+ New function definition.
+ * util/rust-attributes.h (Attributes::extract_string_literal):
+ New function declaration.
+ * ast/rust-collect-lang-items.cc (get_lang_item_attr): Use
+ extract_string_literal.
+ * backend/rust-compile-base.cc: Include "rust-attributes.h".
+ (HIRCompileBase::handle_link_section_attribute_on_fndecl):
+ Use extract_string_literal.
+ (HIRCompileBase::handle_must_use_attribute_on_fndecl): Likewise.
+ * hir/rust-ast-lower-base.cc
+ (ASTLoweringBase::handle_lang_item_attribute): Likewise.
+ * rust-session-manager.cc (Session::handle_crate_name):
+ Likewise.
+
+2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * hir/tree/rust-hir-pattern.h:
+ - Rename TupleItems to PatternItems.
+ - Rename TuplePatternItemsMultiple/Ranged & TupleStructItemsRange/NoRange to
+ TuplePatternItemsNoRest/HasRest and TupleStructItemsNoRest/HasRest.
+ - Update enum values to NO_REST/HAS_REST.
+ - Rename clone_tuple_items_impl to clone_pattern_items_impl.
+ * hir/tree/rust-hir-full-decls.h: Renamed the classes accordingly.
+ * hir/tree/rust-hir-visitor.h: Renamed the classes accordingly.
+ * hir/tree/rust-hir-visitor.cc: Renamed the classes accordingly.
+ * hir/rust-hir-dump.h: Renamed the classes accordingly.
+ * hir/rust-hir-dump.cc: Renamed the classes accordingly.
+ * hir/tree/rust-hir.cc: Renamed the classes accordingly.
+ * hir/rust-ast-lower-base.cc: Renamed the classes accordingly.
+ * hir/rust-ast-lower-pattern.cc: Renamed the classes accordingly.
+ * backend/rust-compile-pattern.cc: Renamed the classes accordingly.
+ * backend/rust-compile-var-decl.h: Renamed the classes accordingly.
+ * checks/errors/borrowck/rust-bir-builder-pattern.cc: Renamed the classes accordingly.
+ * checks/errors/borrowck/rust-bir-builder-struct.h: Renamed the classes accordingly.
+ * checks/errors/borrowck/rust-function-collector.h: Renamed the classes accordingly.
+ * checks/errors/rust-const-checker.cc: Renamed the classes accordingly.
+ * checks/errors/rust-const-checker.h: Renamed the classes accordingly.
+ * checks/errors/rust-hir-pattern-analysis.cc: Renamed the classes accordingly.
+ * checks/errors/rust-hir-pattern-analysis.h: Renamed the classes accordingly.
+ * checks/errors/rust-unsafe-checker.cc: Renamed the classes accordingly.
+ * checks/errors/rust-unsafe-checker.h: Renamed the classes accordingly.
+ * checks/errors/rust-readonly-check2.cc: Renamed the classes accordingly.
+ * typecheck/rust-hir-type-check-pattern.cc: Update references to renamed classes and enum
+ values.
+
+2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-derive-eq.cc: Use empty vector explicitly.
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * Make-lang.in (rust-readonly-check2.cc):
+ Add read-only check on HIR
+ * checks/errors/rust-readonly-check2.cc (ReadonlyChecker):
+ Add read-only check on HIR
+ * checks/errors/rust-readonly-check2.h (ReadonlyChecker):
+ Add read-only check on HIR
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk):
+ Call base class's accept_vis method
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk):
+ Add check before calling `get_trait_ref()`
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-macro-builtins-helpers.cc
+ (try_extract_string_literal_from_fragment): Perform static_cast
+ to AST::LiteralExpr only after it's verified that an AST::Expr
+ is a literal.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * util/rust-attribute-values.h
+ (Attributes::RUSTC_ARGS_REQUIRED_CONST): New constexpr variable.
+ * util/rust-attributes.cc (__definitions): New entry for
+ RUSTC_ARGS_REQUIRED_CONST.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast.cc (AttributeParser::parse_meta_item_inner):
+ Handle removal of AttributeParser-specific functions.
+ (AttributeParser::parse_path_meta_item): Likewise.
+ (AttributeParser::parse_meta_item_seq): Likewise.
+ (AttributeParser::parse_meta_item_lit): Likewise.
+ (AttributeParser::parse_literal): Remove function.
+ (AttributeParser::parse_simple_path): Likewise.
+ (AttributeParser::parse_simple_path_segment): Likewise.
+ (AttributeParser::peek_token): Likewise.
+ (AttributeParser::skip_token): Likewise.
+ * ast/rust-macro.h (AttributeParser::parse_simple_path):
+ Likewise.
+ (AttributeParser::parse_simple_path_segment): Likewise.
+ (AttributeParser::parse_literal): Likewise.
+ (AttributeParser::peek_token): Likewise.
+ (AttributeParser::skip_token): Likewise.
+ * parse/rust-parse.h (Parser): Make AttributeParser a friend
+ class.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Add proper handling
+ of the node.
+ * rust-backend.h (lookup_field): Declare it.
+ * rust-gcc.cc (lookup_field): Add forked implementation from gcc/c/.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast.cc (AttributeParser::parse_path_meta_item): Catch
+ parse_expr returning nullptr and remove defunct comment.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * Make-lang.in (GRS_OBJS): Add entries.
+ * parse/rust-parse-impl.h: Adjust header comment.
+ (Parser::parse_lifetime_params_objs): Fix bug and add comment.
+ (Parser::unexpected_token): Likewise.
+ * parse/rust-parse.h: Remove inclusion of "rust-parse-impl.h".
+ * parse/rust-parse-impl-lexer.cc: New file.
+ * parse/rust-parse-impl-macro.cc: New file.
+ * parse/rust-parse-impl-proc-macro.cc: New file.
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * hir/rust-ast-lower-implitem.cc (ASTLowerTraitItem::visit):
+ Fix object copying issue causing pointer inconsistency
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast.cc (AttributeParser::parse_path_meta_item): Parse
+ expression instead of literal. Update variant name.
+ (MetaItemPathLit::to_attribute): Remove function.
+ (AttributeParser::parse_path_meta_item): Update name.
+ (MetaItemPathLit::check_cfg_predicate): Likewise.
+ (MetaItemPathExpr::check_cfg_predicate): Likewise.
+ (MetaItemPathLit::accept_vis): Likewise.
+ (MetaItemPathExpr::accept_vis): Likewise.
+ * ast/rust-ast-collector.h: Update prototype and adapt code to new
+ expression.
+ * ast/rust-ast-collector.cc: Update code to expr.
+ * ast/rust-ast-full-decls.h (class MetaItemPathLit): Likewise.
+ (class MetaItemPathExpr): Likewise.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast-visitor.h: Likewise.
+ * ast/rust-ast.h (class MetaItemPathLit): Rename class from here...
+ (class MetaItemPathExpr): ... to here.
+ * ast/rust-expr.h (class MetaItemPathLit): Rename class from here...
+ (class MetaItemPathExpr): ...to here.
+ * expand/rust-derive.h: Update class name.
+ * expand/rust-expand-visitor.cc (ExpandVisitor::visit): Likewise.
+ * expand/rust-expand-visitor.h: Likewise.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise.
+ * hir/rust-ast-lower-base.h: Likewise.
+ * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise.
+ * resolve/rust-ast-resolve-base.h: Likewise.
+ * resolve/rust-early-name-resolver.cc (EarlyNameResolver::visit):
+ Likewise.
+ * resolve/rust-early-name-resolver.h: Likewise.
+ * util/rust-attributes.cc (AttributeChecker::visit): Likewise.
+ * util/rust-attributes.h: Likewise.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-subst.cc (SubstitutionRef::infer_substitions): remove debug
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-type-util.cc (unify_site_and): improve debug
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-autoderef.cc: remove useless assertion
+ * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsafe_ptr): refactor
+ (TypeCoercionRules::coerce_borrowed_pointer): remove FIXME this is fine
+ * typecheck/rust-hir-inherent-impl-overlap.h: use types_compatable
+ * typecheck/rust-hir-path-probe.cc (PathProbeType::PathProbeType): remove const
+ (PathProbeType::Probe): likewise
+ (PathProbeImplTrait::PathProbeImplTrait): likewise
+ (PathProbeImplTrait::Probe): likewise
+ * typecheck/rust-hir-path-probe.h: likewise
+ * typecheck/rust-hir-type-check-base.cc (walk_types_to_constrain): likewise
+ * typecheck/rust-hir-type-check-base.h: likewise
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): use types_compatable
+ * typecheck/rust-hir-type-check.h: remove const
+ * typecheck/rust-typecheck-context.cc (TypeCheckContext::insert_associated_impl_mapping):
+ likewise
+ (TypeCheckContext::lookup_associated_impl_mapping_for_self): remove can_Eq
+ * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::is_equal): likewise
+ * typecheck/rust-tyty-subst.cc (SubstitutionArg::get_tyty): remove const version
+ * typecheck/rust-tyty-subst.h: likewise
+ * typecheck/rust-tyty.cc (BaseType::get_root): likewise
+ * typecheck/rust-tyty.h: likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-subst.cc: track the const generic
+ * typecheck/rust-tyty.cc (ConstType::is_equal): finish the is_equal
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * hir/rust-hir-dump.cc (Dump::Dump): Initialize flag.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::ASTLoweringPattern):
+ flag was not initialized in the constructor.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * hir/rust-ast-lower-implitem.cc (ASTLowerTraitItem::visit): Remove
+ use after move.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-builtins-helpers.cc: Remove use after move.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * ast/rust-ast-collector.cc: Add support for the 2 new classes.
+ * ast/rust-ast-collector.h: Header file update for above.
+ * ast/rust-ast-full-decls.h: Add forward decls for the 2 new classes.
+ * ast/rust-ast-visitor.cc: Add visit support for the 2 new classes.
+ * ast/rust-ast-visitor.h: Header file update for above.
+ * ast/rust-pattern.cc: Implementation of certain methods for the 2 new classes.
+ * ast/rust-pattern.h: Define the 2 new classes. Update SlicePattern to be able to hold
+ 2 kinds of items - SlicePatternItemsNoRest or SlicePatternItemsRest.
+ * expand/rust-cfg-strip.cc: Add support for the 2 new classes.
+ * expand/rust-cfg-strip.h: Header file update for above.
+ * expand/rust-derive.h: Add visits for the 2 new classes.
+ * hir/rust-ast-lower-base.cc: Add visits for the 2 new classes.
+ * hir/rust-ast-lower-base.h: Header file update for above.
+ * hir/rust-ast-lower-pattern.cc: Update lowering of SlicePattern to support
+ SlicePatternItemsNoRest.
+ * parse/rust-parse-impl.h (parse_slice_pattern()): Add support for parsing DOT_DOT into
+ respective SlicePatternItems.
+ * resolve/rust-ast-resolve-base.cc: Add visits for the 2 new classes.
+ * resolve/rust-ast-resolve-base.h: Header file update for above.
+ * resolve/rust-ast-resolve-pattern.cc: Update SlicePattern resolution to support new
+ classes.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-subst.cc: fix check for total arguments
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): create infer variable
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/rust-hir-dump.cc (Dump::visit): check for expression
+ * hir/tree/rust-hir.cc (AnonConst::as_string): likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): check for value
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): formatting
+ * typecheck/rust-tyty-variance-analysis-private.h: likewise
+ * typecheck/rust-tyty.cc (VariantDef::clone): likewise
+ (VariantDef::monomorphized_clone): likewise
+ * typecheck/rust-tyty.h: likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.cc: useful debug
+ * backend/rust-compile-stmt.cc (CompileStmt::visit): likewise
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): fold the capacity into ConstType
+ * hir/tree/rust-hir-generic-param.h: make const
+ * hir/tree/rust-hir-path.h: take into account const arguments now
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): needs const
+ * typecheck/rust-hir-type-check-base.h: add error handling for const supported locations
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): const type the arrays
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelExternItem::visit): update
+ (TypeCheckImplItem::visit): likewise
+ * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): likewise
+ (TypeCheckItem::resolve_impl_block_substitutions): likewise
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): wrap up const type
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise
+ (TypeResolveGenericParam::visit): likewise
+ (TypeResolveGenericParam::apply_trait_bounds): remove HIR::Generic from Param
+ * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): cleanup
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::SubstitutionParamMapping):
+ handle const generics
+ (SubstitutionParamMapping::get_type_representation): likewise
+ (SubstitutionParamMapping::param_has_default_ty): likewise
+ (SubstitutionParamMapping::get_default_ty): likewise
+ (SubstitutionRef::infer_substitions): likewise
+ * typecheck/rust-tyty-subst.h: likewise
+ * typecheck/rust-tyty-util.cc (TyVar::get_implicit_const_infer_var): new helper
+ * typecheck/rust-tyty-util.h (class ConstType): likewise
+ * typecheck/rust-tyty.cc (BaseType::is_concrete): check for array const concrete
+ (ArrayType::as_string): update to const
+ (ArrayType::handle_substitions): likewise
+ (ParamType::ParamType): likewise
+ (ParamType::get_generic_param): likewise
+ (ParamType::clone): likewise
+ (ConstType::ConstType): likewise
+ (ConstType::set_value): likewise
+ (ConstType::clone): likewise
+ (ConstType::get_generic_param): likewise
+ (generate_tree_str): new helper to pretty print gimple
+ (ConstType::get_name): uses the generate_tree_str
+ (ConstType::handle_substitions): handle const infer's
+ * typecheck/rust-tyty.h (RUST_TYTY): likewise
+ * typecheck/rust-unify.cc (UnifyRules::expect_array): likewise
+ (UnifyRules::expect_const): likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): error_mark_node for const types
+ * backend/rust-compile-type.h: boilerplate
+ * checks/errors/borrowck/rust-bir-fact-collector.h: likewise
+ * checks/errors/borrowck/rust-bir-place.h: likewise
+ * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::check_base_type_privacy):
+ likewise
+ * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): likewise
+ * typecheck/rust-substitution-mapper.h: likewise
+ * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::assemble_marker_builtins): likewise
+ * typecheck/rust-tyty-call.h: likewise
+ * typecheck/rust-tyty-cmp.h (class ConstCmp): likewise
+ * typecheck/rust-tyty-variance-analysis-private.h: likewise
+ * typecheck/rust-tyty-visitor.h: likewise
+ * typecheck/rust-tyty.cc (TypeKindFormat::to_string): likewise
+ (BaseType::is_unit): likewise
+ (BaseType::has_substitutions_defined): likewise
+ (BaseType::needs_generic_substitutions): likewise
+ (ConstType::ConstType): likewise
+ (ConstType::accept_vis): likewise
+ (ConstType::as_string): likewise
+ (ConstType::can_eq): likewise
+ (ConstType::clone): likewise
+ (ConstType::get_symbol): likewise
+ (ConstType::get_generic_param): likewise
+ (ConstType::can_resolve): likewise
+ (ConstType::resolve): likewise
+ (ConstType::get_name): likewise
+ (ConstType::is_equal): likewise
+ (ConstType::handle_substitions): likewise
+ * typecheck/rust-tyty.h (enum TypeKind): new tyty_kind
+ (class ConstType): new type
+ * typecheck/rust-unify.cc (UnifyRules::go): Handle a const type unify
+ (UnifyRules::expect_inference_variable): likewise
+ (UnifyRules::expect_adt): likewise
+ (UnifyRules::expect_str): likewise
+ (UnifyRules::expect_reference): likewise
+ (UnifyRules::expect_pointer): likewise
+ (UnifyRules::expect_param): likewise
+ (UnifyRules::expect_array): likewise
+ (UnifyRules::expect_slice): likewise
+ (UnifyRules::expect_fndef): likewise
+ (UnifyRules::expect_fnptr): likewise
+ (UnifyRules::expect_tuple): likewise
+ (UnifyRules::expect_bool): likewise
+ (UnifyRules::expect_char): likewise
+ (UnifyRules::expect_int): likewise
+ (UnifyRules::expect_uint): likewise
+ (UnifyRules::expect_float): likewise
+ (UnifyRules::expect_isize): likewise
+ (UnifyRules::expect_usize): likewise
+ (UnifyRules::expect_placeholder): likewise
+ (UnifyRules::expect_projection): likewise
+ (UnifyRules::expect_dyn): likewise
+ (UnifyRules::expect_closure): likewise
+ (UnifyRules::expect_const): likewise
+ * typecheck/rust-unify.h: new expect_const_type handler
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-intrinsic.cc (sizeof_handler): refactor types
+ (op_with_overflow_inner): likewise
+ (uninit_handler): likewise
+ (move_val_init_handler): likewise
+ * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): likewise
+ * typecheck/rust-hir-trait-resolve.cc: likewise
+ * typecheck/rust-hir-type-check-base.cc: likewise
+ * typecheck/rust-hir-type-check-item.cc: likewise
+ * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::is_equal): likewise
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_param_ty): likewise
+ (SubstitutionArg::get_param_mapping): likewise
+ (SubstitutionRef::prepare_higher_ranked_bounds): likewise
+ (SubstitutionRef::monomorphize): likewise
+ * typecheck/rust-tyty-subst.h (class BaseGeneric): new generic base
+ * typecheck/rust-tyty.cc (VariantDef::clone): likewise
+ (VariantDef::monomorphized_clone): refactor
+ (ADTType::is_equal): likewise
+ (FnType::is_equal): likewise
+ (ParamType::ParamType): likewise
+ * typecheck/rust-tyty.h (class ParamType): likewise
+ (class BaseGeneric): new base class impl
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty.cc (ADTType::is_equal): let param::is_eq do this
+ (FnType::is_equal): remove whitespace
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-base.cc: check for type param
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::SubstitutionParamMapping):
+ return HIR::GenericParam base class
+ (SubstitutionParamMapping::get_generic_param): likewise
+ (SubstitutionParamMapping::get_type_representation): new helper
+ (SubstitutionParamMapping::param_has_default_ty): check for param type
+ (SubstitutionParamMapping::get_default_ty): likewise
+ * typecheck/rust-tyty-subst.h: get the locus from the subst HIR::GenericParam now
+ * typecheck/rust-tyty-variance-analysis.cc (GenericTyPerCrateCtx::debug_print_solutions):
+ likwise
+ (GenericTyVisitorCtx::process_type): likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::visit): check for ADTType instead of assert
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * checks/lints/rust-lint-unused-var.cc (check_decl):
+ Do not warn about unused `self` parameter.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in:
+ * ast/rust-expression-yeast.cc (ExpressionYeast::dispatch_loops): Call DesugarWhileLet.
+ * ast/rust-desugar-while-let.cc: New file.
+ * ast/rust-desugar-while-let.h: New file.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast.cc (AttrInputMacro::operator=): Add return type.
+ * ast/rust-expr.h: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-desugar-for-loops.cc: Remove functions implemented in AST::Builder.
+ * ast/rust-desugar-for-loops.h: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * hir/rust-ast-lower-base.cc: Add rust_unreachable() when lowering desugared exprs.
+ * hir/rust-ast-lower-base.h: Mention this.
+ * hir/rust-ast-lower-block.h: Remove existing definitions.
+ * hir/rust-ast-lower-expr.cc: Likewise.
+ * hir/rust-ast-lower-expr.h: Likewise.
+ * hir/rust-ast-lower.cc: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-desugar-question-mark.cc (DesugarQuestionMark::go): Add assertion for the
+ expr's type.
+ * ast/rust-desugar-try-block.cc (DesugarTryBlock::go): Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-desugar-for-loops.h: Adapt API and remove visitor.
+ * ast/rust-desugar-for-loops.cc: Likewise.
+ * ast/rust-expression-yeast.cc: Call DesugarForLoop.
+ * ast/rust-expression-yeast.h: Declare dispatch_loops function.
+ * rust-session-manager.cc (Session::expansion): Do not call for-loop desugar.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * hir/tree/rust-hir-expr.h (class OffsetOf): New.
+ * hir/tree/rust-hir-expr.cc: Define its methods.
+ * hir/tree/rust-hir-expr-abstract.h: Add ExprType::OffsetOf.
+ * hir/tree/rust-hir-full-decls.h (class OffsetOf): Declare it.
+ * backend/rust-compile-block.h: Add handling for OffsetOf.
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Likewise.
+ * backend/rust-compile-expr.h: Likewise.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Likewise.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.h (RUST_BIR_BUILDER_EXPR_H): Likewise.
+ * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Likewise.
+ * checks/errors/borrowck/rust-bir-builder-struct.h: Likewise.
+ * checks/errors/borrowck/rust-function-collector.h: Likewise.
+ * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::visit): Likewise.
+ * checks/errors/privacy/rust-privacy-reporter.h (RUST_PRIVACY_REPORTER_H): Likewise.
+ * checks/errors/rust-const-checker.cc (ConstChecker::visit): Likewise.
+ * checks/errors/rust-const-checker.h: Likewise.
+ * checks/errors/rust-hir-pattern-analysis.cc (PatternChecker::visit): Likewise.
+ * checks/errors/rust-hir-pattern-analysis.h: Likewise.
+ * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): Likewise.
+ * checks/errors/rust-unsafe-checker.h: Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ * hir/rust-hir-dump.cc (Dump::visit): Likewise.
+ * hir/rust-hir-dump.h: Likewise.
+ * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): Likewise.
+ * hir/tree/rust-hir-visitor.h: Likewise.
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
+ * typecheck/rust-hir-type-check-expr.h (RUST_HIR_TYPE_CHECK_EXPR): Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in: Compile the offset_of handler.
+ * lang.opt: Add -frust-assume-builtin-offset-of option.
+ * ast/rust-ast.h: Add has_str() for const_TokenPtr.
+ * expand/rust-macro-builtins.cc: Map offset_of as builtin.
+ * expand/rust-macro-builtins.h: Declare it.
+ * expand/rust-macro-expand.cc (MacroExpander::expand_invoc): Add hack for calling builtin
+ offset_of!().
+ * resolve/rust-early-name-resolver-2.0.cc (Early::visit): Likewise.
+ * expand/rust-macro-builtins-offset-of.cc: New file.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h: Add OffsetOf expression kind.
+ * ast/rust-builtin-ast-nodes.h (class OffsetOf): Add node.
+ * ast/rust-ast.cc: Define it.
+ * ast/rust-ast-collector.cc: Add visitor for OffsetOf.
+ * ast/rust-ast-collector.h: Likewise.
+ * ast/rust-ast-visitor.cc: Likewise.
+ * ast/rust-ast-visitor.h: Likewise.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise.
+ * hir/rust-ast-lower-base.h: Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ * hir/rust-ast-lower-expr.h: Likewise.
+ * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise.
+ * resolve/rust-ast-resolve-base.h: Likewise.
+ * resolve/rust-early-name-resolver-2.0.cc: Likewise.
+ * expand/rust-derive.h:
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * rust-diagnostics.h (struct Error): Add disambiguation.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-builtins-asm.cc (parse_format_strings): Emit an
+ error when expecting a comma.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * checks/errors/borrowck/rust-bir-fact-collector.h: Remove spurious
+ comment.
+ * checks/errors/rust-feature.cc: Likewise.
+ * util/optional.h: Likewise.
+ * expand/rust-token-tree-desugar.cc (TokenTreeDesugar::visit): Remove
+ semicolons on namespace.
+ * expand/rust-token-tree-desugar.h: Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * typecheck/rust-hir-type-check-base.cc
+ (TypeCheckBase::TypeCheckBase): Remove initialization of
+ resolver field.
+ * typecheck/rust-hir-type-check-base.h
+ (TypeCheckBase::resolver): Remove field.
+ * typecheck/rust-hir-trait-resolve.cc: Remove "options.h"
+ include.
+ (TraitResolver::resolve_path_to_trait): Assume name resolution
+ 2.0 is always enabled.
+ * typecheck/rust-hir-type-check-enumitem.cc: Remove "options.h"
+ include.
+ (TypeCheckEnumItem::visit): Assume name resolution 2.0 is always
+ enabled.
+ * typecheck/rust-hir-type-check-expr.cc: Remove "options.h"
+ include.
+ (TypeCheckExpr::visit): Assume name resolution 2.0 is always
+ enabled.
+ (TypeCheckExpr::resolve_operator_overload): Likewise.
+ (TypeCheckExpr::resolve_fn_trait_call): Likewise.
+ * typecheck/rust-hir-type-check-implitem.cc: Remove "options.h"
+ include.
+ (TypeCheckImplItem::visit): Assume name resolution 2.0 is always
+ enabled.
+ * typecheck/rust-hir-type-check-item.cc: Remove "options.h"
+ include.
+ (TypeCheckItem::visit): Assume name resolution 2.0 is always
+ enabled.
+ * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::visit):
+ Likewise.
+ (TypeCheckExpr::resolve_root_path): Likewise.
+ (TypeCheckExpr::resolve_segments): Likewise.
+ * typecheck/rust-hir-type-check-pattern.cc: Remove "options.h"
+ include.
+ (TypeCheckPattern::visit): Assume name resolution 2.0 is always
+ enabled.
+ * typecheck/rust-hir-type-check-type.cc
+ (TypeCheckType::resolve_root_path): Likewise.
+ (ResolveWhereClauseItem::visit): Likewise.
+ * typecheck/rust-hir-type-check.cc: Remove "options.h" include.
+ (TraitItemReference::get_type_from_fn): Assume name resolution
+ 2.0 is always enabled.
+ * typecheck/rust-type-util.cc (query_type): Likewise.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * backend/rust-compile-asm.cc (get_out_expr): Return valid output from
+ an operand.
+ (CompileAsm::asm_construct_outputs): Handle every output
+ (get_in_expr): Return valid input from an operand.
+ (CompileAsm::asm_construct_inputs): Handle every input
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-builtins-asm.cc (parse_reg_operand_inout): Parse
+ expressions and build split in out.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * hir/rust-hir-dump.cc (Dump::visit): Dump inline assembly fields
+ * hir/tree/rust-hir-expr.h: Add non const getter and avoid operand copy
+ from getters.
+ * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): Use non const
+ reference.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-builtins-asm.cc (expand_inline_asm_strings): Handle
+ transformation for indexed positional arguments.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * rust-backend.h: New slice_index_expression function.
+ * rust-gcc.cc: Implementation of slice_index_expression to generate tree node for
+ accessing slice elements.
+ * backend/rust-compile-pattern.cc: Implement SlicePattern check expression & binding
+ compilation against SliceType scrutinee.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(SlicePattern)):
+ Add new type check case for SliceType wrapped in ReferenceType.
+ * backend/rust-compile-pattern.cc: Adjusted the asserts accordingly for
+ CompilePatternCheckExpr(SlicePattern) & CompilePatternBindings(SlicePattern).
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in: Compile it.
+ * ast/rust-expression-yeast.cc (ExpressionYeast::dispatch): Dispatch to try-block
+ desugar.
+ * ast/rust-desugar-try-block.cc: New file.
+ * ast/rust-desugar-try-block.h: New file.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h: Add the new variant.
+ * ast/rust-expr.h: Use it for TryExpr class.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc (DefaultResolver::visit): Add
+ visitor for IfLetExprConseqElse.
+ * resolve/rust-default-resolver.h (DefaultResolver::visit):
+ Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit a block's loop label if it
+ exists.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in: Compile it.
+ * rust-session-manager.cc: Call the expression desugar dispatcher.
+ * ast/rust-desugar-question-mark.cc: Rework class API.
+ * ast/rust-desugar-question-mark.h: Likewise.
+ * ast/rust-expression-yeast.cc: New file.
+ * ast/rust-expression-yeast.h: New file.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-expr.h: Fix formatting.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Handle defered consts.
+ * hir/tree/rust-hir-expr.cc (AnonConst::AnonConst): Likewise.
+ (AnonConst::operator=): Likewise.
+ * hir/tree/rust-hir-expr.h: Likewise.
+ * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): Likewise.
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-expr.h: Add handling for deferred consts.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast.cc (AnonConst::as_string): Likewise.
+ (ArrayType::as_string): Likewise.
+ * ast/rust-type.h (class ArrayType): Use AnonConst for sizes.
+ * parse/rust-parse-impl.h (Parser::parse_anon_const): New function.
+ (Parser::parse_slice_or_array_type): Call it.
+ * parse/rust-parse.h: Declare it.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-early-name-resolver-2.0.cc (Early::resolve_glob_import): Adapt for enums.
+ (Early::finalize_glob_import): Likewise.
+ * resolve/rust-early-name-resolver-2.0.h: Likewise.
+ * resolve/rust-finalize-imports-2.0.cc (GlobbingVisitor::go): Likewise.
+ (GlobbingVisitor::visit_module_container): New function.
+ (GlobbingVisitor::visit_enum_container): New function.
+ * resolve/rust-finalize-imports-2.0.h: Declare them.
+ * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Insert enums as potential
+ containers.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * util/rust-hir-map.cc (Mappings::insert_ast_module): Rename to...
+ (Mappings::insert_glob_container): ...this.
+ (Mappings::lookup_ast_module): Rename to...
+ (Mappings::lookup_glob_container): ...this.
+ * util/rust-hir-map.h: Change declarations.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-cfg-strip.cc (CfgStrip::visit): Load unloaded
+ modules.
+ * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit):
+ Assume modules have been loaded by CfgStrip.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-expand-visitor.cc
+ (ExpandVisitor::expand_inner_items): Adjust call to
+ expand_macro_children.
+ (ExpandVisitor::expand_inner_stmts): Likewise.
+ (ExpandVisitor::visit): Likewise.
+ * expand/rust-expand-visitor.h
+ (ExpandVisitor::expand_macro_children): Take a pointer to member
+ function instead of a std::function.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): do another lookup
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast.cc: Include "rust-macro-invoc-lexer.h".
+ (AttributeParser::~AttributeParser): Move function definition
+ here.
+ (AttributeParser::AttributeParser): Likewise and adjust member
+ initialization.
+ (AttributeParser::parse_meta_item_inner): Handle changes to
+ peek_token.
+ (AttributeParser::parse_literal): Likewise.
+ (AttributeParser::parse_simple_path_segment): Likewise.
+ (AttributeParser::parse_meta_item_seq): Handle changes to
+ AttributeParser fields.
+ (AttributeParser::peek_token): Move function definition here and
+ wrap MacroInvocLexer.
+ (AttributeParser::skip_token): Likewise.
+ * ast/rust-macro.h (class MacroInvocLexer): Forward declare.
+ (class Parser): Likewise.
+ (AttributeParser::token_stream): Remove field.
+ (AttributeParser::stream_pos): Likewise.
+ (AttributeParser::lexer): New field.
+ (AttributeParser::parser): Likewise.
+ (AttributeParser::AttributeParser): Move definition to
+ "rust-ast.cc".
+ (AttributeParser::~AttributeParser): Likewise.
+ (AttributeParser::peek_token): Likewise.
+ (AttributeParser::skip_token): Likewise.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-resolve-path.cc (ResolvePathRef::resolve): return error_mark_node
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/tree/rust-hir-expr.cc (OperatorExprMeta::OperatorExprMeta): track the rhs
+ * hir/tree/rust-hir-expr.h: likewise
+ * hir/tree/rust-hir-path.h: get rid of old comments
+ * typecheck/rust-hir-trait-reference.cc (TraitReference::get_trait_substs): return
+ references instead of copy
+ * typecheck/rust-hir-trait-reference.h: update header
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::ResolveOpOverload): write ambigious
+ operator overloads to a table and try to resolve it at the end
+ * typecheck/rust-hir-type-check-expr.h: new static helper
+ * typecheck/rust-hir-type-check.h (struct DeferredOpOverload): new model to defer resolution
+ * typecheck/rust-typecheck-context.cc (TypeCheckContext::lookup_operator_overload): new
+ (TypeCheckContext::compute_ambigious_op_overload): likewise
+ (TypeCheckContext::compute_inference_variables): likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.cc: check the canonical path
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_simple_path): Be more
+ careful about skipping SCOPE_RESOLUTION tokens.
+ (Parser::parse_simple_path_segment): Allow parsing from a
+ starting offset.
+ (Parser::parse_use_tree): Handle a non-skipped SCOPE_RESOLUTION
+ token.
+ * parse/rust-parse.h (Parser::parse_simple_path_segment): Add
+ parameter for parsing from a starting offset.
+
+2025-08-05 lishin <lishin1008@gmail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Add a catch for const/static.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * rust-backend.h: New size_constant_expression function.
+ * rust-gcc.cc: Implementation of size_constant_expression function to generate tree node
+ for array access.
+ * backend/rust-compile-pattern.h: Remove empty visits for SlicePattern.
+ * backend/rust-compile-pattern.cc: Implement SlicePattern check expression & binding
+ compilation against ArrayType scrutinee.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc(TypeCheckPattern::visit(SlicePattern)):
+ Implement size checking for SlicePattern when type checking against array parent
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * util/rust-attribute-values.h: Add declarations for them.
+ * util/rust-attributes.cc: Add definitions.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::visit): fix typo
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-casts.cc (TypeCastRules::resolve): optional emit_error flag
+ (TypeCastRules::check): try the simple cast rules then fallback to coercions
+ (TypeCastRules::check_ptr_ptr_cast): ensure the underlying's
+ (TypeCastRules::emit_cast_error): make this a static helper
+ * typecheck/rust-casts.h: new emit_error prototype
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Check for a label
+ before visiting it.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): track is super trait
+ * typecheck/rust-hir-type-bounds.h: refactor bounds scan
+ * typecheck/rust-hir-type-check-base.h: track from super trait
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise
+ * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::is_bound_satisfied_for_type): refactor
+ (TypeBoundsProbe::scan): likewise
+ (TypeBoundPredicate::apply_generic_arguments): likewise
+ * typecheck/rust-tyty-subst.cc: optional bounds checking on parm subst
+ * typecheck/rust-tyty-subst.h: likewise
+ * typecheck/rust-tyty.h: likewise
+
+2025-08-05 Marc Poulhiès <dkm@kataplop.net>
+
+ * checks/errors/borrowck/rust-bir-place.h (LoanId::value): Make
+ it size_t to match Loan's base type.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc(TypeCheckPattern::visit(LiteralPattern)):
+ Check LiteralPattern's type against its parent.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(SlicePattern)):
+ Implement initial type checking for SlicePattern.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): check for missing borrow
+ * ast/rust-expr.h: add helper
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.cc (HIRCompileBase::query_compile_const_expr): new wrapper
+ * backend/rust-compile-base.h: add prototype
+ * backend/rust-compile-context.cc (Context::get): singleton helper
+ * backend/rust-compile-context.h: likewise
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): handle infer's that can default
+ * rust-session-manager.cc (Session::compile_crate): create the gcc context earlier for tychk
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): const fold it
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise
+ * typecheck/rust-tyty.cc (BaseType::monomorphized_clone): fix constructor call
+ (ArrayType::as_string): print capacity
+ (ArrayType::clone): fix constructor call
+ * typecheck/rust-tyty.h: track capacity
+ * typecheck/rust-unify.cc (UnifyRules::expect_array): check the capacities
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): New visitor.
+ * resolve/rust-late-name-resolver-2.0.h: Declare it.
+ * resolve/rust-name-resolution-context.h (enum class): New binding context.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Check that the WhileLet has a label
+ before visiting it.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Add visitor
+ for TryExpr.
+ * ast/rust-ast-collector.h (TokenCollector::visit): Likewise.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast-visitor.h (ASTVisitor::visit): Likewise.
+ (DefaultASTVisitor::visit): Likewise.
+ * expand/rust-derive.h (DeriveVisitor::visit): Likewise.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise.
+ * hir/rust-ast-lower-base.h (ASTLoweringBase::visit): Likewise.
+ * resolve/rust-ast-resolve-base.cc (ResolverBase::visit):
+ Likewise.
+ * resolve/rust-ast-resolve-base.h (ResolverBase::visit):
+ Likewise.
+ * ast/rust-ast-full-decls.h (class TryExpr): New forward class
+ declaration.
+ * ast/rust-ast.cc (TryExpr::as_string): New function.
+ (TryExpr::accept_vis): Likewise.
+ * ast/rust-expr.h (class TryExpr): New class.
+ * parse/rust-parse.h (Parser::parse_try_expr): New function.
+ * parse/rust-parse-impl.h (Parser::parse_try_expr): Likewise.
+ (Parser::null_denotation_not_path): Use parse_try_expr to parse
+ try expressions.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-macro-builtins-format-args.cc
+ (format_args_parse_arguments): Accept a RAW_STRING_LITERAL token
+ as the first argument.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * parse/rust-parse-impl.h: Add enum prefix.
+ * parse/rust-parse.h (enum ParseSelfError): Change from enum...
+ (enum class): To enum class.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Replace
+ usages of reinterpret_cast with static_cast.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove
+ override for StructStruct visitor.
+ * resolve/rust-late-name-resolver-2.0.h (Late::visit): Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-context.cc (Context::Context): Remove
+ initialization of resolver field.
+ * backend/rust-compile-context.h (Context::get_resolver): Remove
+ function.
+ (Context::resolver): Remove field.
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Assume name
+ resolution 2.0 is always enabled.
+ (CompileExpr::generate_closure_function): Likewise.
+ * backend/rust-compile-implitem.cc (CompileTraitItem::visit):
+ Likewise.
+ * backend/rust-compile-item.cc (CompileItem::visit): Likewise.
+ * backend/rust-compile-resolve-path.cc
+ (ResolvePathRef::resolve): Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * lang.opt (frust-name-resolution-2.0): Enable by default.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit(TuplePattern)):
+ Implement check expression compilation for TuplePatternItems::RANGED.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (visit(TuplePattern)): Fix
+ incorrect logic for field size checking.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-builder.cc: Remove extra include, fix new formatting.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h (reconstruct_vec): Pre-allocate size of vector.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in: Remove object file for ASTTypeBuilder.
+ * ast/rust-ast-builder.h: Remove function.
+ * ast/rust-ast-builder.cc (Builder::new_type): Likewise.
+ (Builder::new_const_param): Use reconstruct_type() instead.
+ (Builder::new_generic_args): Likewise.
+ * expand/rust-derive-default.cc (DeriveDefault::visit_struct): Likewise.
+ (DeriveDefault::visit_tuple): Likewise.
+ * expand/rust-derive-eq.cc (DeriveEq::visit_tuple): Likewise.
+ (DeriveEq::visit_struct): Likewise.
+ (DeriveEq::visit_enum): Likewise.
+ (DeriveEq::visit_union): Likewise.
+ * ast/rust-ast-builder-type.cc: Removed.
+ * ast/rust-ast-builder-type.h: Removed.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h: Add reconstruct() and reconstruct_impl() for Type nodes.
+ * ast/rust-type.h: Implement them.
+ * ast/rust-macro.h: Likewise.
+ * ast/rust-path.h: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h (reconstruct): New function for calling the `reconstruct_*_impl` method
+ and asserting that the new NodeId is different, and then wrap it in a unique_ptr<T>.
+ (reconstruct_vec): Likewise, but for vectors of unique_ptr<T>
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-forever-stack.hxx (ForeverStack::resolve_path):
+ Resolve final segments which point to modules.
+ * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit):
+ Avoid inserting module names into ribs in the type namespace.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc
+ (visit_identifier_as_pattern): Handle is_ref and is_mut.
+ (Late::visit): Likewise.
+ * resolve/rust-name-resolution-context.cc
+ (BindingLayer::insert_ident): Likewise.
+ (BindingLayer::bind_test): Handle changes to BindingLayer
+ fields.
+ (BindingLayer::merge): Likewise and emit more error messages.
+ * resolve/rust-name-resolution-context.h
+ (struct IdentifierMode): New.
+ (Binding::has_expected_bindings): New field.
+ (Binding::set): Rename field to...
+ (Binding::idents): ...here and convert from a set to a map.
+ (Binding::Binding): Initialize has_expected_bindings.
+ (BindingLayer::insert_ident): Adjust parameters.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-expr.h: Add getter to locus field.
+ * ast/rust-pattern.h (tokenid_to_rangekind): Likewise.
+ * hir/tree/rust-hir-item.h: Likewise.
+ * hir/tree/rust-hir-visibility.h: Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc
+ (DefaultResolver::visit_extern_crate): New function.
+ (DefaultResolver::visit): New visitor function for ExternCrate.
+ * resolve/rust-default-resolver.h
+ (DefaultResolver::visit_extern_crate): New function.
+ (DefaultResolver::visit): New visitor function for ExternCrate.
+ * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit):
+ Adjust ExternCrate visitor and rename to...
+ (TopLevel::visit_extern_crate): ...here.
+ * resolve/rust-toplevel-name-resolver-2.0.h (TopLevel::visit):
+ Remove ExternCrate visitor override.
+ (TopLevel::visit_extern_crate): New function.
+ * rust-session-manager.cc (Session::load_extern_crate): Only run
+ name resolution 1.0 if name resolution 2.0 is disabled.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(TuplePattern)):
+ Implement type checking for ItemType::RANGED.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust-lang.cc: Move version check from C++11 to C++14.
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * Make-lang.in: Scaffolding new rust-hir-visitor files
+ * hir/tree/rust-hir-visitor.h (DefaultHIRVisitor): Declare default HIR visitor
+ * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor): Define default HIR visitor
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * Make-lang.in (GRS_OBJS): Add rust-ggc.o.
+ * backend/rust-compile-base.cc
+ (HIRCompileBase::compile_function): Adjust call to
+ Backend::function.
+ (HIRCompileBase::compile_constant_item): Likewise and adjust
+ initialization of Backend::typed_identifier.
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Adjust call
+ to Backend::label.
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit):
+ Adjust initialization of Backend::typed_identifier.
+ * rust-backend.h: Add includes.
+ (Backend::GGC::Ident): Use Rust::GGC::Ident.
+ (struct typed_identifier): Store name as a GGC::Ident rather
+ than a std::string and adjust constructors.
+ (named_type): Take GGC::Ident/tl::optional<GGC::Ident> rather
+ than std::string.
+ (global_variable): Likewise.
+ (local_variable): Likewise.
+ (parameter_variable): Likewise.
+ (static_chain_variable): Likewise.
+ (label): Likewise.
+ (function): Likewise.
+ * rust-gcc.cc (named_type): Likewise.
+ (global_variable): Likewise.
+ (local_variable): Likewise.
+ (parameter_variable): Likewise.
+ (static_chain_variable): Likewise.
+ (label): Likewise.
+ (function): Likewise.
+ (function_defer_statement): Adjust call to Backend::label.
+ (get_identifier_from_string): Remove function.
+ (fill_in_fields): Handle adjustments to typed_identifier.
+ * util/rust-ggc.cc: New file.
+ * util/rust-ggc.h: New file.
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * hir/tree/rust-hir-item.h (SelfParam::get_lifetime): Add getter
+ for non const lifetime object
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * hir/tree/rust-hir-expr.h (MatchArm::get_outer_attrs): Add getter for outer attributions
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-resolve-path.cc: if this fails fall back to query compile
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::visit): add const call check
+ * backend/rust-compile-item.cc (CompileItem::visit): ensure we upfront compile types where
+ possible
+ * backend/rust-compile-item.h: update header
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): make parent ctx optional
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-pattern.cc(CompilePatternCheckExpr::visit(TupleStructPattern)):
+ Fix error thrown when compiling non-enum TupleStructPattern.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc (DefaultResolver::visit):
+ Call DefaultASTVisitor::visit even on ConstantItem instances
+ without expressions.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-unify.cc (UnifyRules::expect_fnptr): add unify rules
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-reference.cc (TraitReference::on_resolved): ensure associated
+ types are done first
+ * typecheck/rust-hir-type-check-type.cc: Update call site.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-bounds.cc: Check super traits for type bindings.
+ * typecheck/rust-tyty.h: Add helper methods for bound checking.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-bounds.h: Rename method.
+ * typecheck/rust-tyty-bounds.cc: Refactor marker trait assembly
+ and add proper Fn trait handling for function types.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-dot-operator.cc: Major refactoring and cleanup.
+ * typecheck/rust-hir-dot-operator.h: Add new helper methods.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-resolve.cc: Add cyclical projection
+ protection.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-expr.cc: Look at bounds behind
+ references.
+ * typecheck/rust-hir-type-check-expr.h: Add helper method.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust-session-manager.cc (Session::compile_crate): Move
+ AST desugaring to...
+ (Session::expansion): ...here and add a final TopLevel pass
+ afterwards.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): check for has_expr
+ * hir/rust-hir-dump.cc (Dump::visit): likewise
+ * hir/tree/rust-hir-item.h: add has_expr helper
+ * resolve/rust-ast-resolve-item.cc (ResolveItem::visit): check for has_expr
+ * resolve/rust-ast-resolve-stmt.h: likewise
+ * typecheck/rust-hir-type-check-stmt.cc (TypeCheckStmt::visit): likewise
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Add
+ visitor for ExternCrate.
+ * hir/rust-ast-lower-item.h (ASTLoweringItem::visit): Likewise.
+ * rust-session-manager.cc (Session::load_extern_crate): Avoid
+ lowering or type resolving external crates here.
+ * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit):
+ Add visitor for ExternCrate.
+ * typecheck/rust-hir-type-check-item.h (TypeCheckItem::visit):
+ Replace empty definition with a declaration.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty.cc (ParamType::handle_substitions): make this consistent
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit(IdentifierPattern)):
+ Remove redundant subpattern check.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-pattern.cc: Add support for IdentifierPattern's
+ subpattern under CompilePatternBindings.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * resolve/rust-ast-resolve-pattern.cc: Implement name resolution for
+ IdentifierPattern's subpattern.
+ * resolve/rust-late-name-resolver-2.0.cc: Ditto, but for nr2.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * ast/rust-ast-collector.cc: Rename get_pattern_to_bind to get_subpattern
+ * ast/rust-ast-visitor.cc: Ditto.
+ * ast/rust-pattern.h: Ditto.
+ * expand/rust-cfg-strip.cc: Ditto.
+ * hir/rust-ast-lower-pattern.cc: Ditto.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc (DefaultResolver::visit):
+ Adjust scoping of trait definitions and their generic
+ parameters.
+ * resolve/rust-forever-stack.hxx (ForeverStack::get): Prevent
+ lookups inside TraitOrImpl ribs.
+ (ForeverStack::resolve_segments): Prevent lookups of the first
+ segment inside TraitOrImpl ribs.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * hir/rust-hir-dump.cc: Change pattern dumps to use visit_field.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive.cc: Fix formatting after fork update.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-cmp-common.cc (EnumMatchBuilder::tuple): Create two different
+ variant paths.
+ (EnumMatchBuilder::strukt): Likewise.
+ * expand/rust-derive-cmp-common.h: Change API.
+ * expand/rust-derive-ord.cc (DeriveOrd::visit_enum): Use new EnumMatchBuilder API.
+ * expand/rust-derive-partial-eq.cc (DerivePartialEq::visit_enum): Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc (DeriveOrd::make_cmp_arms): Use new make_equal function.
+ (DeriveOrd::make_equal): New function.
+ (DeriveOrd::recursive_match): Handle the unit struct/tuple case.
+ * expand/rust-derive-ord.h: Declare make_equal.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc (DeriveOrd::cmp_call): Use references.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc (DeriveOrd::make_cmp_arms): Fix condition.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc: Finish implementation for enums.
+ * expand/rust-derive-ord.h: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-partial-eq.cc (DerivePartialEq::eq_fn): Change signature.
+ (DerivePartialEq::visit_tuple): Use new eq_fn API.
+ (DerivePartialEq::visit_struct): Likewise.
+ (DerivePartialEq::visit_enum): Implement proper discriminant comparison.
+ * expand/rust-derive-partial-eq.h: Change eq_fn signature.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-cmp-common.h (class EnumMatchBuilder): New helper class.
+ * expand/rust-derive-cmp-common.cc (EnumMatchBuilder::tuple): New function.
+ (EnumMatchBuilder::strukt): New function.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-builder.h: Put `loc` member in public.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc (DeriveOrd::cmp_call): New function.
+ (DeriveOrd::recursive_match): Use it.
+ (DeriveOrd::visit_enum): Likewise.
+ * expand/rust-derive-ord.h: Declare it.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-hash.cc (DeriveHash::visit_enum): Use new APIs.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-builder.cc (Builder::discriminant_value): New function.
+ * ast/rust-ast-builder.h: Declare it.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc (is_last): Remove.
+ (DeriveOrd::visit_tuple): Fix implementation.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-cmp-common.cc (SelfOther::indexes): Fix formatting.
+ (SelfOther::fields): Make iterator const.
+ * expand/rust-derive-cmp-common.h (struct SelfOther): New declaration for indexes.
+ * expand/rust-derive-partial-eq.cc (DerivePartialEq::visit_tuple): Use the new API.
+ (DerivePartialEq::visit_struct): Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc (DeriveOrd::make_cmp_arms): New function.
+ (is_last): Likewise.
+ (recursive_match): Likewise.
+ (DeriveOrd::recursive_match): Likewise.
+ (DeriveOrd::visit_struct): Add proper implementation.
+ (DeriveOrd::visit_union): Likewise.
+ * expand/rust-derive-ord.h: Declare these new functions.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-partial-eq.cc (DerivePartialEq::tuple_indexes): Remove.
+ (DerivePartialEq::field_acccesses): Remove.
+ (DerivePartialEq::visit_tuple): Use new API.
+ (DerivePartialEq::visit_struct): Likewise.
+ * expand/rust-derive-partial-eq.h: Remove declarations.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-cmp-common.cc: New file.
+ * expand/rust-derive-cmp-common.h: New file.
+ * Make-lang.in: Compile them.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-builder.cc (Builder::block): New function.
+ (Builder::match_case): Likewise.
+ * ast/rust-ast-builder.h: Declare them.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-builder.cc (Builder::new_const_param): New function.
+ * ast/rust-ast-builder.h (vec): New function for creating 3 elts vector.
+ * expand/rust-derive.cc: Use the new_const_param builder.
+ * ast/rust-path.h: Add get_default_value() method.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in: Compile it.
+ * expand/rust-derive.cc (DeriveVisitor::derive): Call them.
+ * expand/rust-derive-ord.cc: New file.
+ * expand/rust-derive-ord.h: New file.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-clone.h: Add missing override qualifiers to DeriveVisitor methods.
+ * expand/rust-derive-copy.h: Likewise.
+ * expand/rust-derive-eq.h: Likewise.
+ * expand/rust-derive-hash.h: Likewise.
+ * expand/rust-derive-partial-eq.h: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-rib.h: Add missing switch cases.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-type-util.cc (query_type): early return.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): reuse GCC's build_array_type
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc
+ (visit_identifier_as_pattern): Make sure to map identifiers
+ inside or-bindings to prior identifiers.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * ast/rust-ast-collector.cc: Rename to_bind to subpattern.
+ * ast/rust-ast-visitor.cc: Ditto.
+ * ast/rust-pattern.cc: Ditto.
+ * ast/rust-pattern.h: Ditto.
+ * backend/rust-compile-pattern.cc: Ditto.
+ * expand/rust-cfg-strip.cc: Ditto.
+ * hir/rust-ast-lower-pattern.cc: Ditto.
+ * hir/rust-hir-dump.cc: Ditto.
+ * hir/tree/rust-hir-pattern.h: Ditto.
+ * hir/tree/rust-hir.cc: Ditto.
+ * typecheck/rust-hir-type-check-pattern.cc: Ditto.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-pattern.cc: Add CheckExpr compilation for
+ IdentifierPattern with subpattern.
+ * backend/rust-compile-pattern.h: Modify IdentifierPattern's
+ visit func to support the above.
+ * typecheck/rust-hir-type-check-pattern.cc: Add typechecking
+ support for the changes above.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc
+ (DefaultResolver::visit_closure_params): New member function
+ definition.
+ (DefaultResolver::visit): New visiting function definition for
+ ClosureExpr called from visiting functions for ClosureExprInner
+ and ClosureExprInnerTyped.
+ * resolve/rust-default-resolver.h
+ (DefaultResolver::visit_closure_params): New member function
+ declaration.
+ (DefaultResolver::visit): New visiting function declaration for
+ ClosureExpr.
+ * resolve/rust-late-name-resolver-2.0.cc (add_captures): Remove
+ function.
+ (Late::visit): New visiting function definition for ClosureExpr,
+ remove visiting function definitions for ClosureExprInner and
+ ClosureExprInnerTyped.
+ (Late::visit_closure_params): New member function definition.
+ * resolve/rust-late-name-resolver-2.0.h (Late::visit): New
+ visiting function declaration for ClosureExpr, remove visiting
+ function declarations for ClosureExprInner and
+ ClosureExprInnerTyped.
+ (Late::visit_closure_params): New member function declaration.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-forever-stack.hxx (ForeverStack::resolve_path):
+ Handle single segment paths "crate", "self", and "super".
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Use
+ visit_identifier_as_pattern to handle IdentifierPattern and
+ StructPatternFieldIdent.
+ (visit_identifier_as_pattern): New function.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-expr.h (ClosureExpr::get_definition_expr): New
+ virtual member function.
+ (ClosureExprInner::get_definition_expr): Add override specifier.
+ (ClosureExprInnerTyped::get_definition_block): Rename to...
+ (ClosureExprInnerTyped::get_definition_expr): ...here and add
+ override specifier.
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Handle
+ rename of ClosureExprInnerTyped::get_definition_block to
+ ClosureExprInnerTyped::get_definition_expr.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * expand/rust-cfg-strip.cc (CfgStrip::visit): Likewise.
+ * expand/rust-expand-visitor.cc (ExpandVisitor::visit):
+ Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit):
+ Likewise.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit):
+ Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-base.cc
+ (HIRCompileBase::compile_function): Since canonical paths
+ returned from nr2.0 now include the crate name, avoid prepending
+ the crate name again.
+ * backend/rust-compile-implitem.cc (CompileTraitItem::visit):
+ Use NameResolutionContext::to_canonical_path instead of
+ ForeverStack::to_canonical_path.
+ * backend/rust-compile-item.cc (CompileItem::visit): Likewise.
+ * typecheck/rust-hir-type-check-enumitem.cc
+ (TypeCheckEnumItem::visit): Likewise.
+ * typecheck/rust-hir-type-check-implitem.cc
+ (TypeCheckImplItem::visit): Likewise.
+ * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit):
+ Likewise.
+ * typecheck/rust-hir-type-check.cc
+ (TraitItemReference::get_type_from_fn): Likewise.
+ * resolve/rust-default-resolver.cc (DefaultResolver::visit): Add
+ Crate and EnumItem instance visitors, handle canonical path
+ context scoping.
+ * resolve/rust-default-resolver.h (DefaultResolver::visit): Add
+ Crate and EnumItem instance visitors.
+ * resolve/rust-early-name-resolver-2.0.cc (Early::go): Visit
+ instances of Crate using the virtual member function visit.
+ * resolve/rust-forever-stack.h
+ (ForeverStack::to_canonical_path): Remove function declaration.
+ * resolve/rust-forever-stack.hxx
+ (ForeverStack::to_canonical_path): Remove function definition.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::go): Visit
+ instances of Crate using the virtual member function visit.
+ * resolve/rust-name-resolution-context.cc
+ (CanonicalPathRecordCrateRoot::as_path): New function definition.
+ (CanonicalPathRecordNormal::as_path): Likewise.
+ (CanonicalPathRecordLookup::as_path): Likewise.
+ (CanonicalPathRecordImpl::as_path): Likewise.
+ (CanonicalPathRecordTraitImpl::as_path): Likewise.
+ (NameResolutionContext::NameResolutionContext): Initialize
+ member variable canonical_ctx.
+ * resolve/rust-name-resolution-context.h: Include "rust-item.h".
+ (class NameResolutionContext): Forward declare class.
+ (class CanonicalPathRecord): New class.
+ (class CanonicalPathRecordWithParent): Likewise.
+ (class CanonicalPathRecordCrateRoot): Likewise.
+ (class CanonicalPathRecordNormal): Likewise.
+ (class CanonicalPathRecordLookup): Likewise.
+ (class CanonicalPathRecordImpl): Likewise.
+ (class CanonicalPathRecordTraitImpl): Likewise.
+ (class CanonicalPathCtx): Likewise.
+ (NameResolutionContext::canonical_ctx): New member variable.
+ (NameResolutionContext::to_canonical_path): New member function.
+ * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::go):
+ Visit instances of Crate with the virtual member function visit.
+ (TopLevel::visit): Handle canonical path context scoping for
+ external crates, use DefaultResolver::visit when visiting
+ instances of StructStruct.
+ * util/rust-canonical-path.h (CanonicalPath::new_seg): Take path
+ parameter by-value, as a duplicate instance will be constructed
+ regardless.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * hir/rust-ast-lower-pattern.cc: Lower of IdentifierPattern's to_bind to HIR.
+ * hir/rust-hir-dump.cc: Update IdentifierPattern's dump to properly show to_bind's full
+ full properties.
+
+2025-08-05 Vishruth-Thimmaiah <vishruththimmaiah@gmail.com>
+
+ * lex/rust-lex.cc (Lexer::parse_raw_byte_string):
+ Fix infinite looping when a raw byte string is not terminated.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc (DefaultResolver::visit): Use
+ visit_impl_type to visit the self types of impl blocks.
+ * resolve/rust-default-resolver.h
+ (DefaultResolver::visit_impl_type): New member function
+ declaration.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::Late):
+ Initialize member variable block_big_self.
+ (Late::visit_impl_type): New member function definition.
+ (Late::visit): Check for Self while inside impl block self
+ types.
+ * resolve/rust-late-name-resolver-2.0.h (Late::visit_impl_type):
+ New member function.
+ (Late::block_big_self): New member variable.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-forever-stack.h
+ (enum ResolutionMode): New.
+ (ForeverStack::get): Add a private overload that takes a
+ starting node as a parameter.
+ (ForeverStack::resolve_path): Replace boolean parameter
+ has_opening_scope_resolution with ResolutionMode parameter mode.
+ * resolve/rust-forever-stack.hxx
+ (ForeverStack::resolve_path): Likewise.
+ (ForeverStack::get): Add a private overload that takes a
+ starting node as a parameter.
+ * resolve/rust-late-name-resolver-2.0.cc
+ (Late::visit): Add Visibility visitor.
+ * resolve/rust-late-name-resolver-2.0.h
+ (Late::visit): Likewise.
+ * resolve/rust-name-resolution-context.h
+ (NameResolutionContext::resolve_path): Rework overloading a bit
+ and accept ResolutionMode parameter.
+
+2025-08-05 Vishruth-Thimmaiah <vishruththimmaiah@gmail.com>
+
+ * parse/rust-parse.cc (Rust::extract_module_path):
+ Handle empty or whitespace-only path attributes.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Handle
+ changed type of ConstantItem::identifier.
+ * ast/rust-ast.cc (ConstantItem::as_string): Likewise.
+ * ast/rust-ast.h (operator const std::string &): New member
+ function.
+ * ast/rust-item.h (ConstantItem::identifier): Change type from
+ std::string to Identifier.
+ (ConstantItem::ConstantItem): Handle changed type of identifier
+ field.
+ (ConstantItem::is_unnamed): Likewise.
+ (ConstantItem::get_identifier): Likewise.
+ * hir/rust-ast-lower-extern.h (ASTLoweringExternItem::visit):
+ Avoid discarding location of wildcard patterns.
+ * lex/rust-token.cc: Include "rust-ast.h".
+ (Token::make_identifier): Add overload accepting an Identifier
+ instance.
+ * lex/rust-token.h (class Identifier): Add forward declaration
+ in order to...
+ (Token::make_identifier): ...declare an overload for this static
+ member function.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * hir/tree/rust-hir-expr.h: New classes.
+ * hir/tree/rust-hir-full-decls.h: Likewise.
+ * hir/tree/rust-hir.cc: Handle AnonConst and ConstBlock.
+ * backend/rust-compile-block.cc: Likewise.
+ * backend/rust-compile-block.h: Likewise.
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Likewise.
+ * backend/rust-compile-expr.h: Likewise.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Likewise.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Likewise.
+ * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Likewise.
+ * checks/errors/borrowck/rust-bir-builder-struct.h: Likewise.
+ * checks/errors/borrowck/rust-function-collector.h: Likewise.
+ * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::visit): Likewise.
+ * checks/errors/privacy/rust-privacy-reporter.h: Likewise.
+ * checks/errors/rust-const-checker.cc (ConstChecker::visit): Likewise.
+ * checks/errors/rust-const-checker.h: Likewise.
+ * checks/errors/rust-hir-pattern-analysis.cc (PatternChecker::visit): Likewise.
+ * checks/errors/rust-hir-pattern-analysis.h: Likewise.
+ * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): Likewise.
+ * checks/errors/rust-unsafe-checker.h: Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ (translate_operand_out): Likewise.
+ (translate_operand_inout): Likewise.
+ (translate_operand_const): Likewise.
+ * hir/rust-ast-lower-expr.h: Likewise.
+ * hir/rust-hir-dump.cc (Dump::visit): Likewise.
+ * hir/rust-hir-dump.h: Likewise.
+ * hir/tree/rust-hir-expr-abstract.h: Likewise.
+ * hir/tree/rust-hir-expr.cc (AnonConst::AnonConst): Likewise.
+ (AnonConst::operator=): Likewise.
+ (ConstBlock::ConstBlock): Likewise.
+ (ConstBlock::operator=): Likewise.
+ * hir/tree/rust-hir-visitor.h:
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
+ (typecheck_inline_asm_operand): Likewise.
+ * typecheck/rust-hir-type-check-expr.h: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_const_block_expr): New function.
+ * parse/rust-parse.h: Declare it.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-expr.h: Declare AnonConst and ConstBlock and use them.
+ * ast/rust-ast-full-decls.h: Likewise.
+ * ast/rust-ast.cc: Add implementation for AnonConst and ConstBlock.
+ * ast/rust-ast.h: Likewise.
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Likewise.
+ * ast/rust-ast-collector.h: Likewise.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast-visitor.h: Likewise.
+ * expand/rust-derive.h: Likewise.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise.
+ * hir/rust-ast-lower-base.h: Likewise.
+ * hir/rust-ast-lower-expr.cc (translate_operand_const): Likewise.
+ * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise.
+ * resolve/rust-ast-resolve-base.h: Likewise.
+ * resolve/rust-ast-resolve-expr.h: Likewise.
+ * resolve/rust-ast-resolve-expr.cc: Likewise.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsized): dont emit error here
+ * typecheck/rust-unify.cc (UnifyRules::resolve_subtype): new helper to handle emit error
+ (UnifyRules::expect_adt): call resolve_subtype
+ (UnifyRules::expect_reference): likewise
+ (UnifyRules::expect_pointer): likewise
+ (UnifyRules::expect_array): likewise
+ (UnifyRules::expect_slice): likewise
+ (UnifyRules::expect_fndef): likewise
+ (UnifyRules::expect_fnptr): likewise
+ (UnifyRules::expect_tuple): likewise
+ (UnifyRules::expect_closure): likewise
+ (UnifyRules::expect_opaque): likeiwse
+ * typecheck/rust-unify.h: add new helper to header
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc
+ (DefaultResolver::visit_if_let_patterns): New function
+ definition.
+ (DefaultResolver::visit): New IfLetExpr visitor definition.
+ * resolve/rust-default-resolver.h
+ (DefaultResolver::visit_if_let_patterns): New function
+ declaration.
+ (DefaultResolver::visit): New IfLetExpr visitor declaration.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove
+ IfLetExpr visitor definition.
+ (Late::visit_if_let_patterns): New function definition.
+ * resolve/rust-late-name-resolver-2.0.h (Late::visit): Remove
+ IfLetExpr visitor declaration.
+ (Late::visit_if_let_patterns): New function declaration.
+ * resolve/rust-name-resolution-context.h (BindingSource::IfLet):
+ New enumerator.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): we need to resolve the
+ underlying type
+ * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): just clone
+ * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit):
+ ensure we monomphize to get the underlying
+ * typecheck/rust-tyty.cc (BaseType::destructure): handle opaque types
+ (OpaqueType::resolve): this is much simpler now
+ (OpaqueType::handle_substitions): no longer needed
+ * typecheck/rust-tyty.h: update header
+ * typecheck/rust-unify.cc (UnifyRules::expect_opaque): unify rules for opaque
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): use get_name
+ * typecheck/rust-tyty.cc (TupleType::get_name): likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::check_base_type_privacy):
+ no need for unreachable here
+ * typecheck/rust-unify.cc (UnifyRules::commit): dont clone infer vars
+ (UnifyRules::expect_inference_variable): likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check.h: new function
+ * typecheck/rust-typecheck-context.cc (TypeCheckContext::compute_inference_variables):
+ call the new helper
+ (TypeCheckContext::compute_infer_var): refactored code
+
+2025-08-05 Tom Schollenberger <tss2344@g.rit.edu>
+
+ * resolve/rust-early-name-resolver-2.0.cc (Early::visit_attributes): rust_assert to if
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_expr_stmt): Avoid
+ reference binding and remove std::move in return statements.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-visitor.cc
+ (DefaultASTVisitor::visit): Only visit the path of an instance
+ of Visibility if the instance has a path.
+ * ast/rust-ast.h
+ (SimplePath::SimplePath): Make sure constructors are explicit.
+ * resolve/rust-early-name-resolver-2.0.cc
+ (Early::visit_attributes): Pass entire paths to
+ NameResolutionContext::resolve_path.
+ (Early::visit): Likewise and avoid copying a path.
+ * resolve/rust-forever-stack.hxx
+ (ForeverStack::resolve_path): Assert that at least one path
+ segment has been passed in.
+
+2025-08-05 Marc Poulhiès <dkm@kataplop.net>
+
+ * rust-attribs.cc (handle_hot_attribute): Remove clang-format comment.
+
+2025-08-05 Marc Poulhiès <dkm@kataplop.net>
+
+ * ast/rust-ast-builder-type.cc (ASTTypeBuilder::visit): Reindent.
+ * ast/rust-ast-builder.cc (Builder::new_generic_args): Likewise.
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Likewise.
+ * ast/rust-ast-dump.h (debug): Likewise.
+ * ast/rust-ast-formatting.h (indent_spaces): Likewise.
+ (get_string_in_delims): Likewise.
+ (get_mode_dump_desc): Likewise.
+ (append_attributes): Likewise.
+ (unquote_string): Likewise.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast.cc (Attribute::get_traits_to_derive): Likewise.
+ (UseTreeGlob::as_string): Likewise.
+ (UseTreeList::as_string): Likewise.
+ (AttributeParser::parse_path_meta_item): Likewise.
+ (FormatArgs::set_outer_attrs): Likewise.
+ * ast/rust-ast.h (operator<<): Likewise.
+ * ast/rust-cond-compilation.h: Likewise.
+ * ast/rust-desugar-apit.cc: Likewise.
+ * ast/rust-fmt.h (collect_pieces): Likewise.
+ (clone_pieces): Likewise.
+ * ast/rust-pattern.h (tokenid_to_rangekind): Likewise.
+ * backend/rust-compile-context.cc (Context::type_hasher): Likewise.
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Likewise.
+ * backend/rust-compile-intrinsic.cc (get_identifier): Likewise.
+ (offset_handler): Likewise.
+ (sizeof_handler): Likewise.
+ (transmute_handler): Likewise.
+ (rotate_handler): Likewise.
+ (wrapping_op_handler_inner): Likewise.
+ (op_with_overflow_inner): Likewise.
+ (uninit_handler): Likewise.
+ (move_val_init_handler): Likewise.
+ (assume_handler): Likewise.
+ (discriminant_value_handler): Likewise.
+ (variant_count_handler): Likewise.
+ (prefetch_data_handler): Likewise.
+ (atomic_store_handler_inner): Likewise.
+ (atomic_load_handler_inner): Likewise.
+ (unchecked_op_inner): Likewise.
+ (copy_handler_inner): Likewise.
+ (expect_handler_inner): Likewise.
+ (try_handler_inner): Likewise.
+ * backend/rust-compile-pattern.cc (compile_range_pattern_bound): Likewise.
+ (CompilePatternCheckExpr::visit): Likewise.
+ (CompilePatternBindings::visit): Likewise.
+ (CompilePatternLet::visit): Likewise.
+ * backend/rust-compile-var-decl.h: Likewise.
+ * backend/rust-constexpr.cc (verify_constant): Likewise.
+ (find_array_ctor_elt): Likewise.
+ (array_index_cmp): Likewise.
+ (potential_constant_expression_1): Likewise.
+ (unshare_constructor): Likewise.
+ (maybe_save_constexpr_fundef): Likewise.
+ (returns): Likewise.
+ (breaks): Likewise.
+ (continues): Likewise.
+ (switches): Likewise.
+ (constant_value_1): Likewise.
+ (decl_constant_value): Likewise.
+ (non_const_var_error): Likewise.
+ (eval_constant_expression): Likewise.
+ (constexpr_fn_retval): Likewise.
+ (eval_store_expression): Likewise.
+ (eval_call_expression): Likewise.
+ (eval_binary_expression): Likewise.
+ (get_function_named_in_call): Likewise.
+ (eval_statement_list): Likewise.
+ (extract_string_elt): Likewise.
+ (eval_conditional_expression): Likewise.
+ (eval_bit_field_ref): Likewise.
+ (eval_loop_expr): Likewise.
+ (eval_switch_expr): Likewise.
+ (eval_unary_expression): Likewise.
+ (get_or_insert_ctor_field): Likewise.
+ (eval_and_check_array_index): Likewise.
+ * backend/rust-constexpr.h (maybe_save_constexpr_fundef): Likewise.
+ * backend/rust-mangle-v0.cc (v0_path): Likewise.
+ (v0_complex_type_prefix): Likewise.
+ * backend/rust-mangle.h (legacy_mangle_item): Likewise.
+ (v0_mangle_item): Likewise.
+ * backend/rust-tree.cc (convert_to_void): Likewise.
+ (find_parameter_packs_r): Likewise.
+ (rs_tree_equal): Likewise.
+ (publicly_uniquely_derived_p): Likewise.
+ (instantiation_dependent_expression_p): Likewise.
+ (type_has_nontrivial_copy_init): Likewise.
+ (is_normal_capture_proxy): Likewise.
+ (is_bitfield_expr_with_lowered_type): Likewise.
+ (undeduced_auto_decl): Likewise.
+ (require_deduced_type): Likewise.
+ (gt_pch_nx): Likewise.
+ (lvalue_kind): Likewise.
+ * backend/rust-tree.h (LANG_DECL_MIN_CHECK): Likewise.
+ (LANG_DECL_FN_CHECK): Likewise.
+ (LANG_DECL_NS_CHECK): Likewise.
+ (LANG_DECL_PARM_CHECK): Likewise.
+ (LANG_DECL_DECOMP_CHECK): Likewise.
+ (resort_type_member_vec): Likewise.
+ (convert_to_void): Likewise.
+ (mark_discarded_use): Likewise.
+ (mark_exp_read): Likewise.
+ (mark_use): Likewise.
+ (mark_rvalue_use): Likewise.
+ (mark_lvalue_use): Likewise.
+ (mark_lvalue_use_nonread): Likewise.
+ (convert_from_reference): Likewise.
+ (maybe_warn_nodiscard): Likewise.
+ (expr_loc_or_loc): Likewise.
+ (expr_loc_or_input_loc): Likewise.
+ (get_fndecl_from_callee): Likewise.
+ (pointer_offset_expression): Likewise.
+ (is_empty_class): Likewise.
+ (is_really_empty_class): Likewise.
+ (rs_type_quals): Likewise.
+ (init_modules): Likewise.
+ (lookup_add): Likewise.
+ (ovl_make): Likewise.
+ (struct c_fileinfo): Likewise.
+ (get_fileinfo): Likewise.
+ (cxx_make_type): Likewise.
+ (build_cplus_array_type): Likewise.
+ (comptypes): Likewise.
+ (rs_build_qualified_type_real): Likewise.
+ (vector_targets_convertible_p): Likewise.
+ (get_class_binding_direct): Likewise.
+ (lang_check_failed): Likewise.
+ (check_for_uninitialized_const_var): Likewise.
+ (cp_fold_maybe_rvalue): Likewise.
+ (fold_offsetof): Likewise.
+ (fold_non_dependent_expr): Likewise.
+ (in_immediate_context): Likewise.
+ (cxx_mark_addressable): Likewise.
+ (decl_constant_value): Likewise.
+ (is_class_type): Likewise.
+ (fold_builtin_is_pointer_inverconvertible_with_class): Likewise.
+ (c_common_type_for_mode): Likewise.
+ (next_common_initial_seqence): Likewise.
+ (fold_builtin_is_corresponding_member): Likewise.
+ (maybe_constant_value): Likewise.
+ (rs_walk_subtrees): Likewise.
+ (make_tree_vector): Likewise.
+ (release_tree_vector): Likewise.
+ (location_of): Likewise.
+ (maybe_constant_init): Likewise.
+ (explain_invalid_constexpr_fn): Likewise.
+ (literal_type_p): Likewise.
+ (maybe_constexpr_fn): Likewise.
+ (fold_non_dependent_init): Likewise.
+ * checks/errors/borrowck/polonius/rust-polonius.h (polonius_run): Likewise.
+ (FFIVector__new): Likewise.
+ (FFIVector__new_vec_pair): Likewise.
+ (FFIVector__new_vec_triple): Likewise.
+ (FFIVector__push): Likewise.
+ (FFIVector__push_vec_triple): Likewise.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
+ (ExprStmtBuilder::visit): Likewise.
+ * checks/errors/borrowck/rust-bir-builder-pattern.cc
+ (PatternBindingBuilder::visit): Likewise.
+ * checks/errors/borrowck/rust-bir-dump.cc (Dump::visit): Likewise.
+ * checks/errors/borrowck/rust-bir-fact-collector.h (points): Likewise.
+ * checks/errors/borrowck/rust-bir-place.h: Likewise.
+ * checks/errors/borrowck/rust-bir-visitor.h: Likewise.
+ * checks/errors/privacy/rust-privacy-check.cc (saw_errors): Likewise.
+ * checks/errors/privacy/rust-privacy-ctx.h (rust_privacy_ctx_test): Likewise.
+ * checks/errors/privacy/rust-privacy-reporter.cc
+ (PrivacyReporter::check_for_privacy_violation): Likewise.
+ (PrivacyReporter::check_base_type_privacy): Likewise.
+ (PrivacyReporter::visit): Likewise.
+ * checks/errors/privacy/rust-reachability.cc (ReachabilityVisitor::visit): Likewise.
+ * checks/errors/privacy/rust-visibility-resolver.cc
+ (VisibilityResolver::resolve_visibility): Likewise.
+ * checks/errors/rust-hir-pattern-analysis.cc (Constructor::is_covered_by): Likewise.
+ (PlaceInfo::specialize): Likewise.
+ (WitnessPat::to_string): Likewise.
+ (WitnessMatrix::apply_constructor): Likewise.
+ (lower_pattern): Likewise.
+ (lower_tuple_pattern): Likewise.
+ (lower_struct_pattern): Likewise.
+ * checks/errors/rust-hir-pattern-analysis.h (check_match_usefulness): Likewise.
+ * expand/rust-cfg-strip.cc (CfgStrip::maybe_strip_generic_args): Likewise.
+ * expand/rust-derive-eq.cc (DeriveEq::visit_enum): Likewise.
+ * expand/rust-derive.cc: Likewise.
+ * expand/rust-expand-format-args.cc (expand_format_args): Likewise.
+ * expand/rust-expand-visitor.h (is_derive): Likewise.
+ (is_builtin): Likewise.
+ * expand/rust-macro-builtins-asm.cc (expand_inline_asm_strings): Likewise.
+ * expand/rust-macro-builtins-asm.h (parse_asm): Likewise.
+ (check_identifier): Likewise.
+ (check_and_set): Likewise.
+ (parse_label): Likewise.
+ (parse_llvm_outputs): Likewise.
+ (parse_llvm_inputs): Likewise.
+ (parse_llvm_clobbers): Likewise.
+ (parse_llvm_options): Likewise.
+ * expand/rust-macro-builtins-helpers.h (make_macro_path_str): Likewise.
+ (make_token): Likewise.
+ (make_string): Likewise.
+ (macro_end_token): Likewise.
+ (parse_single_string_literal): Likewise.
+ (source_relative_path): Likewise.
+ (load_file_bytes): Likewise.
+ * expand/rust-macro-expand.cc (MacroExpander::match_fragment): Likewise.
+ (MacroExpander::match_matcher): Likewise.
+ (MacroExpander::match_n_matches): Likewise.
+ * expand/rust-macro-substitute-ctx.cc (SubstituteCtx::substitute_token): Likewise.
+ * expand/rust-proc-macro.h (load_macros): Likewise.
+ (generate_proc_macro_decls_symbol): Likewise.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_generic_args): Likewise.
+ (ASTLoweringBase::lower_range_pattern_bound): Likewise.
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise.
+ * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit): Likewise.
+ * hir/rust-ast-lower.h (struct_field_name_exists): Likewise.
+ (translate_visibility): Likewise.
+ * hir/rust-hir-dump.cc (Dump::visit): Likewise.
+ * hir/rust-hir-dump.h (debug): Likewise.
+ * hir/tree/rust-hir.cc (UseTreeGlob::as_string): Likewise.
+ (UseTreeList::as_string): Likewise.
+ * lex/rust-lex.cc (Lexer::parse_escape): Likewise.
+ (Lexer::parse_utf8_escape): Likewise.
+ * lex/rust-lex.h (rust_input_source_test): Likewise.
+ * lex/rust-token.cc (RS_TOKEN_KEYWORD_2015): Likewise.
+ * lex/rust-token.h (get_token_description): Likewise.
+ (token_id_to_str): Likewise.
+ (token_id_is_keyword): Likewise.
+ (token_id_keyword_string): Likewise.
+ (get_type_hint_string): Likewise.
+ (nfc_normalize_token_string): Likewise.
+ * metadata/rust-export-metadata.cc (PublicInterface::write_to_path): Likewise.
+ * metadata/rust-import-archive.cc: Likewise.
+ * metadata/rust-imports.h (add_search_path): Likewise.
+ * parse/rust-cfg-parser.h (parse_cfg_option): Likewise.
+ (rust_cfg_parser_test): Likewise.
+ * parse/rust-parse-impl.h (Parser::skip_generics_right_angle): Likewise.
+ (Parser::parse_attr_input): Likewise.
+ (Parser::parse_macro_match): Likewise.
+ (Parser::parse_visibility): Likewise.
+ (Parser::parse_module): Likewise.
+ (Parser::parse_use_tree): Likewise.
+ (Parser::parse_generic_param): Likewise.
+ (Parser::parse_struct): Likewise.
+ (Parser::parse_enum_item): Likewise.
+ (Parser::parse_inherent_impl_item): Likewise.
+ (Parser::parse_external_item): Likewise.
+ (Parser::parse_generic_arg): Likewise.
+ (Parser::parse_type_path_segment): Likewise.
+ (Parser::parse_expr_stmt): Likewise.
+ (Parser::parse_if_expr): Likewise.
+ (Parser::parse_if_let_expr): Likewise.
+ (Parser::parse_type): Likewise.
+ (Parser::parse_for_prefixed_type): Likewise.
+ (Parser::parse_slice_or_array_type): Likewise.
+ (Parser::parse_type_no_bounds): Likewise.
+ (Parser::parse_range_pattern_bound): Likewise.
+ (Parser::parse_pattern_no_alt): Likewise.
+ (Parser::parse_grouped_or_tuple_pattern): Likewise.
+ (Parser::parse_ident_leading_pattern): Likewise.
+ (Parser::parse_tuple_struct_items): Likewise.
+ (Parser::parse_stmt_or_expr): Likewise.
+ (Parser::parse_struct_expr_field): Likewise.
+ (Parser::null_denotation): Likewise.
+ (Parser::left_denotation): Likewise.
+ (Parser::parse_closure_expr_pratt): Likewise.
+ * parse/rust-parse.cc (peculiar_fragment_match_compatible): Likewise.
+ (is_match_compatible): Likewise.
+ * parse/rust-parse.h (extract_module_path): Likewise.
+ (is_match_compatible): Likewise.
+ * resolve/rust-ast-resolve-expr.cc (translate_operand): Likewise.
+ * resolve/rust-ast-resolve-item.cc (flatten_glob): Likewise.
+ (flatten_rebind): Likewise.
+ (flatten_list): Likewise.
+ (flatten): Likewise.
+ * resolve/rust-ast-resolve-item.h (rust_simple_path_resolve_test): Likewise.
+ * resolve/rust-ast-resolve-pattern.cc (PatternDeclaration::visit): Likewise.
+ (resolve_range_pattern_bound): Likewise.
+ * resolve/rust-ast-resolve-type.cc (ResolveRelativeTypePath::go): Likewise.
+ (ResolveTypeToCanonicalPath::visit): Likewise.
+ * resolve/rust-ast-resolve.cc (saw_errors): Likewise.
+ * resolve/rust-early-name-resolver-2.0.cc (Early::finalize_rebind_import): Likewise.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise.
+ * resolve/rust-toplevel-name-resolver-2.0.cc (flatten_glob): Likewise.
+ * rust-backend.h (init): Likewise.
+ (debug): Likewise.
+ (get_identifier_node): Likewise.
+ (wchar_type): Likewise.
+ (get_pointer_size): Likewise.
+ (raw_str_type): Likewise.
+ (integer_type): Likewise.
+ (float_type): Likewise.
+ (pointer_type): Likewise.
+ (reference_type): Likewise.
+ (immutable_type): Likewise.
+ (function_type): Likewise.
+ (function_type_variadic): Likewise.
+ (function_ptr_type): Likewise.
+ (struct_type): Likewise.
+ (union_type): Likewise.
+ (array_type): Likewise.
+ (named_type): Likewise.
+ (type_field_offset): Likewise.
+ (var_expression): Likewise.
+ (float_constant_expression): Likewise.
+ (string_constant_expression): Likewise.
+ (char_constant_expression): Likewise.
+ (wchar_constant_expression): Likewise.
+ (boolean_constant_expression): Likewise.
+ (convert_expression): Likewise.
+ (struct_field_expression): Likewise.
+ (compound_expression): Likewise.
+ (conditional_expression): Likewise.
+ (negation_expression): Likewise.
+ (arithmetic_or_logical_expression): Likewise.
+ (arithmetic_or_logical_expression_checked): Likewise.
+ (comparison_expression): Likewise.
+ (lazy_boolean_expression): Likewise.
+ (constructor_expression): Likewise.
+ (array_constructor_expression): Likewise.
+ (array_initializer): Likewise.
+ (array_index_expression): Likewise.
+ (call_expression): Likewise.
+ (init_statement): Likewise.
+ (assignment_statement): Likewise.
+ (return_statement): Likewise.
+ (if_statement): Likewise.
+ (loop_expression): Likewise.
+ (exit_expression): Likewise.
+ (statement_list): Likewise.
+ (exception_handler_statement): Likewise.
+ (block): Likewise.
+ (block_add_statements): Likewise.
+ (global_variable): Likewise.
+ (global_variable_set_init): Likewise.
+ (local_variable): Likewise.
+ (parameter_variable): Likewise.
+ (static_chain_variable): Likewise.
+ (temporary_variable): Likewise.
+ (label): Likewise.
+ (function): Likewise.
+ (function_defer_statement): Likewise.
+ (function_set_parameters): Likewise.
+ (write_global_definitions): Likewise.
+ (fill_in_fields): Likewise.
+ * rust-diagnostics.cc (expand_format): Likewise.
+ (expand_message): Likewise.
+ (va_constructor): Likewise.
+ * rust-diagnostics.h (RUST_ATTRIBUTE_GCC_DIAG): Likewise.
+ (rust_open_quote): Likewise.
+ (rust_close_quote): Likewise.
+ (rust_debug_loc): Likewise.
+ * rust-gcc.cc (non_zero_size_type): Likewise.
+ * rust-object-export.h (rust_field_alignment): Likewise.
+ (rust_read_export_data): Likewise.
+ (rust_write_export_data): Likewise.
+ * rust-session-manager.cc (saw_errors): Likewise.
+ (rust_get_linemap): Likewise.
+ (validate_crate_name): Likewise.
+ (Session::load_extern_crate): Likewise.
+ * rust-session-manager.h (rust_crate_name_validation_test): Likewise.
+ * rust-system.h (rust_preserve_from_gc): Likewise.
+ (rust_localize_identifier): Likewise.
+ * rust-target.h (rust_add_target_info): Likewise.
+ * typecheck/rust-autoderef.cc:
+ * typecheck/rust-casts.cc (TypeCastRules::cast_rules): Likewise.
+ * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Likewise.
+ (TypeCoercionRules::coerce_unsafe_ptr): Likewise.
+ (TypeCoercionRules::coerce_borrowed_pointer): Likewise.
+ * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): Likewise.
+ (TraitItemReference::is_object_safe): Likewise.
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): Likewise.
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
+ (typecheck_inline_asm_operand): Likewise.
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItem::visit): Likewise.
+ (TypeCheckImplItemWithTrait::visit): Likewise.
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): Likewise.
+ * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::visit): Likewise.
+ * typecheck/rust-hir-type-check-type.cc
+ (TypeResolveGenericParam::apply_trait_bounds): Likewise.
+ (ResolveWhereClauseItem::visit): Likewise.
+ * typecheck/rust-hir-type-check.cc (saw_errors): Likewise.
+ (TraitItemReference::get_type_from_fn): Likewise.
+ * typecheck/rust-type-util.h (query_type): Likewise.
+ (types_compatable): Likewise.
+ (unify_site): Likewise.
+ (unify_site_and): Likewise.
+ (coercion_site): Likewise.
+ (try_coercion): Likewise.
+ (cast_site): Likewise.
+ * typecheck/rust-tyty-bounds.cc:
+ * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): Likewise.
+ * typecheck/rust-tyty-cmp.h:
+ * typecheck/rust-tyty-variance-analysis.h (query_field_regions): Likewise.
+ * typecheck/rust-tyty.cc (BaseType::is_unit): Likewise.
+ (BaseType::has_substitutions_defined): Likewise.
+ (BaseType::needs_generic_substitutions): Likewise.
+ (BaseType::get_subst_argument_mappings): Likewise.
+ (InferType::default_type): Likewise.
+ (InferType::apply_primitive_type_hint): Likewise.
+ * typecheck/rust-tyty.h (is_primitive_type_kind): Likewise.
+ * typecheck/rust-unify.cc (UnifyRules::expect_inference_variable): Likewise.
+ (UnifyRules::expect_adt): Likewise.
+ (UnifyRules::expect_str): Likewise.
+ (UnifyRules::expect_reference): Likewise.
+ (UnifyRules::expect_pointer): Likewise.
+ (UnifyRules::expect_param): Likewise.
+ (UnifyRules::expect_array): Likewise.
+ (UnifyRules::expect_slice): Likewise.
+ (UnifyRules::expect_fndef): Likewise.
+ (UnifyRules::expect_fnptr): Likewise.
+ (UnifyRules::expect_tuple): Likewise.
+ (UnifyRules::expect_bool): Likewise.
+ (UnifyRules::expect_char): Likewise.
+ (UnifyRules::expect_int): Likewise.
+ (UnifyRules::expect_uint): Likewise.
+ (UnifyRules::expect_float): Likewise.
+ (UnifyRules::expect_isize): Likewise.
+ (UnifyRules::expect_usize): Likewise.
+ (UnifyRules::expect_never): Likewise.
+ (UnifyRules::expect_placeholder): Likewise.
+ (UnifyRules::expect_projection): Likewise.
+ (UnifyRules::expect_dyn): Likewise.
+ (UnifyRules::expect_closure): Likewise.
+ (UnifyRules::expect_opaque): Likewise.
+ * util/rust-abi.h (get_abi_from_string): Likewise.
+ (get_string_from_abi): Likewise.
+ * util/rust-attributes.cc (check_doc_attribute): Likewise.
+ * util/rust-base62.h (base62_integer): Likewise.
+ * util/rust-dir-owner.h (get_file_subdir): Likewise.
+ * util/rust-edition.h (get_rust_edition): Likewise.
+ * util/rust-punycode.h (encode_punycode): Likewise.
+ (rust_punycode_encode_test): Likewise.
+ * util/rust-token-converter.cc (convert): Likewise.
+ (from_tokenstream): Likewise.
+ * util/rust-token-converter.h (convert): Likewise.
+ (convert_literal): Likewise.
+ * util/rust-unicode.h (is_alphabetic): Likewise.
+ (is_ascii_only): Likewise.
+ (is_numeric): Likewise.
+ (is_nfc_qc_no): Likewise.
+ (is_nfc_qc_maybe): Likewise.
+ (nfc_quick_check): Likewise.
+ (rust_nfc_qc_test): Likewise.
+ (rust_utf8_normalize_test): Likewise.
+ (rust_utf8_property_test): Likewise.
+ * util/rust-unwrap-segment.h (unwrap_segment_node_id): Likewise.
+
+2025-08-05 Marc Poulhiès <dkm@kataplop.net>
+
+ * Make-lang.in (GRS_OBJS): Remove rust-macro.o.
+ * ast/rust-macro.cc: Removed.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h
+ (Parser::parse_attr_input): Handle more delimeter tokens and the
+ END_OF_FILE token.
+ (Parser::skip_after_end_attribute): Handle the END_OF_FILE
+ token.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * hir/rust-ast-lower-item.cc
+ (ASTLoweringItem::visit): Keep going after a duplicate field is
+ found.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * checks/errors/borrowck/rust-bir-builder-internal.h: Include
+ "rust-immutable-name-resolution-context.h" and "options.h".
+ (AbstractBuilder::resolve_label): Use the 2.0 name resolver when
+ it's enabled.
+ (AbstractBuilder::resolve_variable): Likewise.
+ (AbstractBuilder::resolve_variable_or_fn): Likewise.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * expand/rust-derive-default.cc (DeriveDefault::visit_struct): use builder
+ (DeriveDefault::visit_tuple): likewise
+ * expand/rust-derive-eq.cc (DeriveEq::visit_tuple): likewise
+ (DeriveEq::visit_struct): likewise
+ (DeriveEq::visit_enum): likewise
+ (DeriveEq::visit_union): likewise
+
+2025-08-05 Marc Poulhiès <dkm@kataplop.net>
+
+ PR rust/120018
+ * rust-attribs.cc (handle_noreturn_attribute): Reindent declaration.
+ (handle_leaf_attribute): Likewise.
+ (handle_const_attribute): Likewise.
+ (handle_malloc_attribute): Likewise.
+ (handle_pure_attribute): Likewise.
+ (handle_novops_attribute): Likewise.
+ (handle_nonnull_attribute): Likewise.
+ (handle_nothrow_attribute): Likewise.
+ (handle_type_generic_attribute): Likewise.
+ (handle_transaction_pure_attribute): Likewise.
+ (handle_returns_twice_attribute): Likewise.
+ (handle_fnspec_attribute): Likewise.
+ (handle_omp_declare_simd_attribute): Likewise.
+ (handle_cold_attribute): New.
+ (handle_hot_attribute): New.
+ (attribute_spec::exclusions attr_cold_hot_exclusions): New.
+ (grs_langhook_common_attributes): Make it static.
+ (grs_langhook_common_attribute_table): New.
+ (grs_langhook_gnu_attributes): New.
+ (grs_langhook_gnu_attribute_table): New.
+ (handle_malloc_attribute): Make it static.
+ (handle_fnspec_attribute): Likewise.
+ (handle_pure_attribute): Replace gcc_assert by explicit warning.
+ (handle_novops_attribute): Likewise.
+ (handle_nothrow_attribute): Likewise.
+ (handle_returns_twice_attribute): Likewise.
+ (handle_omp_declare_simd_attribute): Likewise and make it static.
+ * rust-lang.cc (grs_langhook_gnu_attribute_table): New.
+ (grs_langhook_common_attribute_table): Adjust type to new hook.
+ (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Remove.
+ (LANG_HOOKS_ATTRIBUTE_TABLE): New.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-path.cc
+ (TypePath::make_debug_string): Add definition.
+ * ast/rust-path.h
+ (TypePath::make_debug_string): Add declaration.
+ * resolve/rust-default-resolver.cc
+ (DefaultResolver::visit): Adjust InherentImpl and TraitImpl
+ visitors to better handle associated item scope.
+ * resolve/rust-default-resolver.h
+ (DefaultResolver::maybe_insert_big_self): Add.
+ * resolve/rust-late-name-resolver-2.0.cc
+ (Late::visit): Adjust type path resolution errors.
+ * resolve/rust-rib.h
+ (Rib::Kind): Add Generics kind.
+ * resolve/rust-toplevel-name-resolver-2.0.cc
+ (TopLevel::visit): Remove InherentImpl and TraitImpl visitor
+ overrides.
+ (TopLevel::maybe_insert_big_self): Add override in order to add
+ a definition of 'Self'.
+ * resolve/rust-toplevel-name-resolver-2.0.h
+ (TopLevel::visit): Remove InherentImpl and TraitImpl visitor
+ overrides.
+ (TopLevel::maybe_insert_big_self): Add override.
+
+2025-08-05 0xn4utilus <gyanendrabanjare8@gmail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Implement for InlineAsm.
+ * ast/rust-ast-full-decls.h (enum class): Move InlineAsmOption enum inside InlineAsm.
+ * ast/rust-expr.h (enum class): Likewise.
+ (class InlineAsm): Likewise.
+ * expand/rust-macro-builtins-asm.cc (check_and_set): Likewise.
+ (parse_options): Likewise.
+ * expand/rust-macro-builtins-asm.h (check_and_set): Likewise.
+ * hir/tree/rust-hir-expr.cc (InlineAsm::InlineAsm): Likewise.
+ * hir/tree/rust-hir-expr.h: Likewise.
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
+
+2025-08-05 Tom Schollenberger <tss2344@g.rit.edu>
+
+ * backend/rust-constexpr.cc (eval_constant_expression): Check if t is a NULL_TREE
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * ast/rust-desugar-apit.cc: track if this is a impl-trait generic
+ * ast/rust-item.h (class TypeParam): add field to track if from impl trait
+ * hir/rust-ast-lower-type.cc (ASTLowerGenericParam::visit): likewise
+ * hir/tree/rust-hir-item.cc (TypeParam::TypeParam): upate hir as well
+ (TypeParam::operator=): likewise
+ * hir/tree/rust-hir-item.h (class TypeParam): likewise
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_generic_param): add error
+ * typecheck/rust-tyty-subst.h: add const getter for the associated TypeParm
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-visitor.cc
+ (DefaultASTVisitor::visit): Make call to EnumItem visitor from
+ EnumItem derived class visitors non-virtual.
+ * ast/rust-collect-lang-items.cc
+ (CollectLangItems::visit): Handle visitation of classes derived
+ from EnumItem.
+ * ast/rust-collect-lang-items.h
+ (CollectLangItems::visit): Likewise.
+ * resolve/rust-toplevel-name-resolver-2.0.cc
+ (TopLevel::visit): Call DefaultResolver::visit on EnumItem
+ instances.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-pattern.cc
+ (CompilePatternCheckExpr::visit): Fix GENERIC generation in
+ light of enum layout changes since this code was written.
+ (CompilePatternBindings::handle_struct_pattern_ident_pat):
+ Delegate handling of child patterns to another
+ CompilePatternBindings::Compile call.
+ (CompilePatternBindings::make_struct_access): Make field name
+ parameter const qualified.
+ * backend/rust-compile-pattern.h
+ (CompilePatternBindings::make_struct_access): Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-ast-resolve-item.cc
+ (ResolveItem::visit): Use the return values of
+ CanonicalPath::inherent_impl_seg and
+ CanonicalPath::trait_impl_projection_seg more directly.
+ * util/rust-canonical-path.h
+ (CanonicalPath::trait_impl_projection_seg): Append "<impl "
+ instead of "<" to the beginning of the returned path segment.
+ (CanonicalPath::inherent_impl_seg): Likewise.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * Make-lang.in: new desugar file
+ * ast/rust-ast.cc (ImplTraitTypeOneBound::as_string): its a unique_ptr now
+ (FormatArgs::set_outer_attrs): reformat
+ * ast/rust-path.h: remove has_generic_args assertion (can be empty because of desugar)
+ * ast/rust-type.h (class ImplTraitTypeOneBound): add copy ctor and use unique_ptr
+ * hir/rust-ast-lower-type.cc (ASTLoweringType::visit): update to use unique_ptr
+ * parse/rust-parse-impl.h (Parser::parse_type): reuse the existing unique_ptr instead
+ (Parser::parse_type_no_bounds): likewise
+ (Parser::parse_pattern): likewise
+ * resolve/rust-ast-resolve-type.cc (ResolveType::visit): its a unique_ptr now
+ * rust-session-manager.cc (Session::compile_crate): call desugar
+ * ast/rust-desugar-apit.cc: New file.
+ * ast/rust-desugar-apit.h: New file.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): allow impl type
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): likewise
+ * hir/rust-ast-lower-type.cc (ASTLoweringType::ASTLoweringType): new flag for impl trait
+ (ASTLoweringType::translate): pass flag
+ (ASTLoweringType::visit): track impl trait tag
+ (ASTLoweringType::emit_impl_trait_error): new diagnostic
+ * hir/rust-ast-lower-type.h: add new field
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-partial-eq.cc (DerivePartialEq::match_enum_tuple): Remove debug call.
+ (DerivePartialEq::match_enum_struct): Add proper implementation.
+ (DerivePartialEq::visit_enum): Call it.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-builder.cc (Builder::struct_pattern_ident_pattern): New.
+ * ast/rust-ast-builder.h: New declaration.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * backend/rust-compile-pattern.cc (CompilePatternBindings::make_struct_access):
+ New function.
+ (CompilePatternBindings::visit): Properly implement patterns mentioned above
+ and call make_struct_accesss.
+ * backend/rust-compile-pattern.h: New declaration.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * backend/rust-compile-pattern.h: Split struct pattern compilation into three functions.
+ * backend/rust-compile-pattern.cc: Implement them.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::Late): False initialize the
+ funny_error field.
+
+2025-07-25 David Malcolm <dmalcolm@redhat.com>
+
+ * resolve/rust-ice-finalizer.cc: Update usage of "diagnostic_info"
+ to explicitly refer to "diagnostics::diagnostic_info".
+ * resolve/rust-ice-finalizer.h: Likewise.
+
+2025-07-25 David Malcolm <dmalcolm@redhat.com>
+
+ * backend/rust-tree.cc: Update for diagnostic_t becoming
+ enum class diagnostics::kind.
+ * backend/rust-tree.h: Likewise.
+ * resolve/rust-ast-resolve-expr.cc: Likewise.
+ * resolve/rust-ice-finalizer.cc: Likewise.
+ * resolve/rust-ice-finalizer.h: Likewise.
+ * resolve/rust-late-name-resolver-2.0.cc: Likewise.
+
+2025-07-25 David Malcolm <dmalcolm@redhat.com>
+
+ * resolve/rust-ast-resolve-expr.cc: Update for diagnostic_text_finalizer
+ becoming diagnostics::text_finalizer.
+ * resolve/rust-late-name-resolver-2.0.cc: Likewise.
+
+2025-07-25 David Malcolm <dmalcolm@redhat.com>
+
+ * resolve/rust-ice-finalizer.cc: Update for move of diagnostics
+ output formats into namespace "diagnostics" as "sinks".
+ * resolve/rust-ice-finalizer.h: Likewise.
+
+2025-07-25 David Malcolm <dmalcolm@redhat.com>
+
+ * rust-diagnostics.cc: Update #include for move of
+ "diagnostic-metadata.h" to "diagnostics/metadata.h", and update
+ for move of diagnostic_metadata to diagnostics::metadata.
+
+2025-06-26 Martin Jambor <mjambor@suse.cz>
+
+ * checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
+ (BorrowCheckerDiagnostics::get_loan): Type cast loan to uint32_t.
+
+2025-04-28 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * checks/errors/borrowck/rust-bir-place.h
+ (IndexVec::size_type): Add.
+ (IndexVec::MAX_INDEX): Add.
+ (IndexVec::size): Change the return type to the type of the
+ internal value used by the index type.
+ (PlaceDB::lookup_or_add_variable): Use the return value from the
+ PlaceDB::add_place call.
+ * checks/errors/borrowck/rust-bir.h
+ (struct BasicBlockId): Move this definition before the
+ definition of the struct Function.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit visibility.
+
+2025-04-28 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-visitor.cc
+ (DefaultASTVisitor::visit): Visit the loop labels of
+ WhileLetLoopExpr instances before visiting their scrutinee
+ expressions.
+ * resolve/rust-early-name-resolver-2.0.cc
+ (Early::resolve_glob_import): Pass the glob import's path
+ directly to NameResolutionContext::resolve_path.
+ * resolve/rust-toplevel-name-resolver-2.0.cc
+ (TopLevel::visit): Remove unnecessary call to
+ Identifier::as_string.
+ (flatten_glob): Improve handling of cases where a glob use tree
+ has no path.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-derive-clone.cc (DeriveClone::clone_enum_struct): Clone
+ path to avoid using the same nodeid.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit_function_params):
+ Add specialized function to visit function parameters.
+ (DefaultASTVisitor::visit): Remove parameter visit and call specialized
+ function instead.
+ * ast/rust-ast-visitor.h: Add function prototye.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove
+ function.
+ (Late::visit_function_params): Override specialized visit function.
+ * resolve/rust-late-name-resolver-2.0.h: Add overriden function
+ prototype.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-name-resolution-context.h: Use BindingLayer instead.
+ * resolve/rust-name-resolution-context.cc (BindingLayer::BindingLayer):
+ Add new constructor for binding layer.
+ (BindingLayer::bind_test): Add a function to test a binding constraint.
+ (BindingLayer::push): Push a new binding group.
+ (BindingLayer::and_binded): Add function to test and-binding
+ constraint.
+ (BindingLayer::or_binded): Add function to test or-binding constraints.
+ (BindingLayer::insert_ident): Insert a new identifier in the current
+ binding group.
+ (BindingLayer::merge): Merge current binding group with it's parent.
+ (BindingLayer::get_source): Get the source of the current binding
+ group.
+ * resolve/rust-late-name-resolver-2.0.cc: Use stacked context for
+ binding group.
+ * util/rust-stacked-contexts.h: Add mutable peek function.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Add binding
+ creation in visitor.
+ * resolve/rust-late-name-resolver-2.0.h: Add function prototypes.
+ * resolve/rust-name-resolution-context.h: Add binding context.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-name-resolution-context.h (struct Binding): Add Binding
+ struct to differentiate Or and Product bindings in patterns.
+ (enum class): Add Binding kind.
+ (class BindingContext): Add binding context with Binding stack.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast.h: Add hash function.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast.h: Add equality operator.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-default-resolver.cc (DefaultResolver::visit): Add visit
+ function for TypeParam.
+ * resolve/rust-default-resolver.h: Add function prototype.
+ * resolve/rust-forever-stack.h: Add function to check for forward
+ declaration ban.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Check forward
+ declarations.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Remove error kind
+ and change function call.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Change call name.
+ * ast/rust-path.cc (ConstGenericParam::as_string): Likewise.
+ * ast/rust-path.h: Remove error kind.
+ * hir/rust-ast-lower-type.cc (ASTLowerGenericParam::visit): Change call
+ name.
+ * parse/rust-parse-impl.h (Parser::parse_generic_param): Use optional
+ on parsing failure.
+ (Parser::parse_generic_arg): Likewise.
+ (Parser::parse_path_generic_args): Likewise.
+ * parse/rust-parse.h: Likewise.
+ * resolve/rust-ast-resolve-type.h: Change call name.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Change error
+ message.
+
+2025-04-28 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-early-name-resolver-2.0.cc
+ (Early::build_import_mapping): Avoid outputting an "unresolved
+ import" error if other errors are outputted during resolution.
+ * resolve/rust-early-name-resolver-2.0.h
+ (Early::resolve_path_in_all_ns): Collect path resolution errors
+ while avoiding duplicate errors for resolutions in each
+ namespace.
+ * resolve/rust-forever-stack.h
+ (ForeverStack::resolve_path): Add parameter for collecting
+ errors.
+ (ForeverStack::find_starting_point): Likewise.
+ (ForeverStack::resolve_segments): Likewise.
+ * resolve/rust-forever-stack.hxx
+ (check_leading_kw_at_start): Likewise.
+ (ForeverStack::find_starting_point): Likewise.
+ (ForeverStack::resolve_segments): Likewise.
+ (ForeverStack::resolve_path): Likewise.
+ * resolve/rust-name-resolution-context.h
+ (NameResolutionContext::resolve_path): Add optional parameter
+ for collecting errors.
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::array_copied_expr): prealloc the vector
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): add guard
+ * expand/rust-expand-visitor.cc (ExpandVisitor::visit): add guard
+
+2025-04-28 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-ast-resolve-path.cc
+ (ResolvePath::resolve_path): Adjust error messages.
+ * resolve/rust-ast-resolve-type.cc
+ (ResolveRelativeTypePath::go): Likewise.
+ * resolve/rust-forever-stack.hxx
+ (check_leading_kw_at_start): Likewise.
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): fix bad assertion
+
+2025-04-28 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-forever-stack.hxx
+ (ForeverStack::resolve_path): Pass instance of Node to lambda by
+ reference instead of by value.
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-struct-field.h: keep reference to parent expression
+ * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::TypeCheckStructExpr):
+ update ctor
+ (TypeCheckStructExpr::resolve): remove bad rust_fatal_errors
+ (TypeCheckStructExpr::visit): cleanup errors
+
+2025-04-28 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc
+ (Late::visit): Handle StructPatternFieldIdent.
+ * resolve/rust-late-name-resolver-2.0.h
+ (Late::visit): Likewise.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Dump llvm inline
+ asm tokens.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Remove unreachable
+ code.
+ * ast/rust-expr.h (struct LlvmOperand): Add LlvmOperand struct to
+ represent input and outputs.
+ (class LlvmInlineAsm): Add input, output and clobber operands.
+ (struct TupleTemplateStr): Add locus getter.
+ * backend/rust-compile-block.h: Add visit for LlvmInlineAsm.
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Add llvm inline
+ asm stmt compilation.
+ * backend/rust-compile-expr.h: Add function prototype.
+ * backend/rust-compile-asm.h (class CompileLlvmAsm): Add llvm asm hir
+ not to gimple.
+ * backend/rust-compile-asm.cc (CompileLlvmAsm::CompileLlvmAsm): Add
+ constructor.
+ (CompileLlvmAsm::construct_operands): Add function to construct operand
+ tree.
+ (CompileLlvmAsm::construct_clobbers): Add function to construct clobber
+ tree.
+ (CompileLlvmAsm::tree_codegen_asm): Generate the whole tree for a given
+ llvm inline assembly node.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit):
+ Add visit function.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Add function
+ prototype.
+ * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Add visit
+ function.
+ * checks/errors/borrowck/rust-bir-builder-struct.h: Likewise.
+ * checks/errors/borrowck/rust-function-collector.h: Likewise.
+ * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::visit):
+ Likewise.
+ * checks/errors/privacy/rust-privacy-reporter.h: Add visit function
+ prototype.
+ * checks/errors/rust-const-checker.cc (ConstChecker::visit): Add visit
+ function.
+ * checks/errors/rust-const-checker.h: Add visit function prototype.
+ * checks/errors/rust-hir-pattern-analysis.cc (PatternChecker::visit):
+ Add visit function.
+ * checks/errors/rust-hir-pattern-analysis.h: Add visit function
+ prototype.
+ * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): Add
+ visit function.
+ * checks/errors/rust-unsafe-checker.h: Add function prototype.
+ * expand/rust-macro-builtins-asm.cc (parse_llvm_templates): Parse
+ templates.
+ (parse_llvm_arguments): Add function to parse non template tokens.
+ (parse_llvm_operands): Add function to parse operands, either input or
+ output.
+ (parse_llvm_outputs): Add function to parse and collect llvm asm
+ outputs.
+ (parse_llvm_inputs): Likewise with inputs.
+ (parse_llvm_clobbers): Add function to parse llvm asm clobbers.
+ (parse_llvm_options): Add function to parse llvm asm options.
+ (parse_llvm_asm): Add function to parse llvm asm.
+ * expand/rust-macro-builtins-asm.h (class LlvmAsmContext): Add context
+ for llvm asm parser.
+ (parse_llvm_outputs): Add function prototype.
+ (parse_llvm_inputs): Likewise.
+ (parse_llvm_clobbers): Likewise.
+ (parse_llvm_options): Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Lower AST llvm
+ asm node to HIR.
+ * hir/rust-ast-lower-expr.h: Add function prototype.
+ * hir/rust-hir-dump.cc (Dump::visit): Add visit function.
+ * hir/rust-hir-dump.h: Add function prototype.
+ * hir/tree/rust-hir-expr-abstract.h: Add HIR llvm asm node kind.
+ * hir/tree/rust-hir-expr.h (struct LlvmOperand): Add LlvmOperand type
+ to represent input and outputs.
+ (class LlvmInlineAsm): Add LlvmInlineAsm hir node.
+ * hir/tree/rust-hir-full-decls.h (class LlvmInlineAsm): Add
+ LlvmInlineAsm hir node forward declaration.
+ * hir/tree/rust-hir-visitor.h: Add visit functions for LlvmInlineAsm
+ hir node.
+ * hir/tree/rust-hir.cc (LlvmInlineAsm::accept_vis): Add hir node
+ visitor related functions.
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit):
+ Type check input and output operands.
+ * typecheck/rust-hir-type-check-expr.h: Add function prototype.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit input and
+ output operand expressions.
+ * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): Resolve input
+ and output expressions.
+ * resolve/rust-ast-resolve-expr.h: Add function prototypes.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Make visitor
+ unreachable.
+ * ast/rust-ast-collector.h: Add visit for LlvmInlineAsmNode.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Add visit
+ function for the default ast visitor.
+ * ast/rust-ast-visitor.h: Add function prototype.
+ * ast/rust-ast.cc (LlvmInlineAsm::accept_vis): Add accept_vis to
+ LlvmInlineAsm node.
+ * ast/rust-ast.h: Add LlvmInlineAsm node kind.
+ * ast/rust-expr.h (class LlvmInlineAsm): Add LlvmInlineAsm node.
+ * expand/rust-derive.h: Add visit function for LlvmInlineAsm node.
+ * expand/rust-macro-builtins-asm.cc (MacroBuiltin::llvm_asm_handler):
+ Add handler for llvm inline assembly nodes.
+ (parse_llvm_asm): Add function to parse llvm assembly nodes.
+ * expand/rust-macro-builtins-asm.h (parse_llvm_asm): Add function
+ prototypes.
+ * expand/rust-macro-builtins.cc (inline_llvm_asm_maker): Add macro
+ transcriber.
+ * expand/rust-macro-builtins.h: Add transcriber function prototype.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Add visit
+ function for LlvmInlineAsm node.
+ * hir/rust-ast-lower-base.h: Add visit function prototype.
+ * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Add visit
+ function for LlvmInlineAsm node.
+ * resolve/rust-ast-resolve-base.h: Add visit function prototype.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-builtins-asm.cc (parse_asm_arg): Emit error
+ message.
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): add diagnostic
+ * typecheck/rust-tyty.cc (BaseType::contains_infer): new helper to grab first infer var
+ * typecheck/rust-tyty.h: prototype
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * rust-gcc.cc (arithmetic_or_logical_expression): Ensure this is an integer
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/rust-hir-dump.cc (Dump::visit): add guard for optional label
+
+2025-04-28 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-tyty.h: Remove extra redundant comment.
+ * typecheck/rust-hir-type-check-base.cc: Update comment on repr
+ handling.
+
+2025-04-28 Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-base.cc: Set enum representing
+ type properly if repr is an integer type.
+ * typecheck/rust-hir-type-check-item.cc: Update comments.
+
+2025-04-28 Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-tyty.h: Add new `ReprKind` enum to
+ `ReprOptions`.
+ * typecheck/rust-hir-type-check-base.cc: Handle setting of
+ `repr_kind`.
+ * typecheck/rust-hir-type-check-item.cc: New check for
+ zero-variant enums.
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): add null check
+ * hir/tree/rust-hir-item.h: add has_type helper
+ * typecheck/rust-hir-trait-resolve.cc (TraitItemReference::resolve_item):
+ add missing type checking
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * util/rust-lang-item.h: Add new manually_drop lang item.
+ * util/rust-lang-item.cc: Likewise.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * util/rust-attribute-values.h: Add RUSTFMT value.
+ * util/rust-attributes.cc: Define the attribute.
+ * util/rust-attributes.h (enum CompilerPass): Add EXTERNAL variant.
+ * expand/rust-macro-builtins.cc: Fix formatting.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-early-name-resolver-2.0.cc (Early::visit_attributes): Remove assertion.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * util/rust-attribute-values.h: Add missing attributes.
+ * util/rust-attributes.cc: Likewise.
+ * util/rust-attributes.h (enum CompilerPass): Mention adding something for const
+ functions.
+
+2025-04-14 beamandala <mandalapubhavesh@gmail.com>
+
+ * expand/rust-macro-builtins.cc (MacroBuiltin::builtin_transcribers):
+ Add entry for track_caller.
+ * util/rust-attribute-values.h: add `TRACK_CALLER` attribute.
+ * util/rust-attributes.cc: add `track_caller` attribute definition.
+
+2025-04-14 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * checks/errors/rust-const-checker.cc
+ (ConstChecker::visit): Visit the enum items of enums.
+ * resolve/rust-ast-resolve-item.cc
+ (ResolveItem::visit): Resolve enum discriminants during nr1.0.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-macro-builtins-format-args.cc (format_args_parse_arguments): Improve safety,
+ allow extra commas after end of argument list.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-macro-expand.cc (MacroExpander::expand_decl_macro): Call into
+ TokenTreeDesugar.
+ * expand/rust-token-tree-desugar.cc: New file.
+ * expand/rust-token-tree-desugar.h: New file.
+ * Make-lang.in: Compile them.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-macro-expand.cc (MacroExpander::match_n_matches): Do not
+ insert fragments and substack fragments if the matcher failed.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust-session-manager.cc (Session::compile_crate): Call the visitor later in the pipeline.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h (DelimTokenTree::get_locus): New function.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-expr.h (class RangeExpr): Add empty outer attributes and allow getting them
+ and setting them.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Return if module
+ is unloaded.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * typecheck/rust-hir-type-check-expr.cc (is_default_fn): New.
+ (emit_ambiguous_resolution_error): New.
+ (handle_multiple_candidates): Properly handle multiple candidates in
+ the case of specialization.
+ (TypeCheckExpr::visit): Call `handle_multiple_candidates`.
+
+2025-04-14 Andrew Pinski <quic_apinski@quicinc.com>
+
+ PR rust/119342
+ * rust-gcc.cc (block): Add comment on why chaining
+ the variables of the scope toether.
+
+2025-04-14 Andrew Pinski <quic_apinski@quicinc.com>
+
+ PR rust/119341
+ * rust-gcc.cc (function_type): Use range fors.
+ (function_type_variadic): Likewise.
+ (fill_in_fields): Likewise.
+ (statement_list): Likewise.
+ (block): Likewise.
+ (block_add_statements): Likewise.
+ (function_set_parameters): Likewise.
+ (write_global_definitions): Likewise.
+
+2025-04-14 Andrew Pinski <quic_apinski@quicinc.com>
+
+ * rust-gcc.cc (Bvariable::get_tree): Use error_operand_p.
+ (pointer_type): Likewise.
+ (reference_type): Likewise.
+ (immutable_type): Likewise.
+ (function_type): Likewise.
+ (function_type_variadic): Likewise.
+ Cleanup the check for receiver.type first.
+ (function_ptr_type): Use error_operand_p.
+ (fill_in_fields): Likewise.
+ (fill_in_array): Likewise.
+ (named_type): Likewise.
+ (type_size): Likewise.
+ (type_alignment): Likewise.
+ (type_field_alignment): Likewise.
+ (type_field_offset): Likewise.
+ (zero_expression): Likewise.
+ (float_constant_expression): Likewise.
+ (convert_expression): Likewise.
+ (struct_field_expression): Likewise.
+ (compound_expression): Likewise.
+ (conditional_expression): Likewise.
+ (negation_expression): Likewise.
+ (arithmetic_or_logical_expression): Likewise.
+ (arithmetic_or_logical_expression_checked): Likewise.
+ (comparison_expression): Likewise.
+ (lazy_boolean_expression): Likewise.
+ (constructor_expression): Likewise.
+ (array_constructor_expression): Likewise.
+ (array_index_expression): Likewise.
+ (call_expression): Likewise.
+ (init_statement): Likewise.
+ (assignment_statement): Likewise.
+ (return_statement): Likewise.
+ (exception_handler_statement): Likewise.
+ (if_statement): Likewise.
+ (compound_statement): Likewise.
+ Tighten up the code, removing t variable.
+ (statement_list): Use error_operand_p.
+ (block): Likewise.
+ (block_add_statements): Likewise.
+ (convert_tree): Likewise.
+ (global_variable): Likewise.
+ (global_variable_set_init): Likewise.
+ (local_variable): Likewise.
+ (parameter_variable): Likewise.
+ (static_chain_variable): Likewise.
+ (temporary_variable): Likewise.
+ (function): Likewise. Tighten up the code.
+ (function_defer_statement): Use error_operand_p.
+ (function_set_parameters): Use error_operand_p.
+ (write_global_definitions): Use error_operand_p.
+ Tighten up the code around the loop.
+
+2025-04-14 Andrew Pinski <quic_apinski@quicinc.com>
+
+ * rust-gcc.cc (is_floating_point): Use FLOAT_TYPE_P
+ instead of manually checking the type.
+
+2025-04-08 Matty Kuhn <matty.kuhn.1@gmail.com>
+
+ * ast/rust-ast.h: (AST::Attribute): add empty_input function
+ * checks/errors/rust-feature-gate.cc: (FeatureGate::visit): check for empty feature gate
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Update label
+ getter call.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast.cc (BreakExpr::as_string): Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): Likewise.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise.
+ * ast/rust-expr.h: Add optional getter and rename label getter to
+ get_label_unchecked.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit):
+ Call unchecked getter.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit):
+ Likewise.
+ * ast/rust-ast.cc (ContinueExpr::as_string): Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): Likewise.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise.
+ * ast/rust-expr.h: Add new getter for the optional and rename getter
+ to get_label_unchecked.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_loop_label): Change function
+ return type to expected.
+ (Parser::parse_labelled_loop_expr): Adapt call location to new return
+ type.
+ * parse/rust-parse.h (enum class): Update function prototype.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Add call
+ to label resolution if there is one label.
+ (Late::resolve_label): Look for labels and emit an error message on
+ failure.
+ * resolve/rust-late-name-resolver-2.0.h: Add function prototypes.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit):
+ Change error message to match rustc.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-builder.cc (Builder::self_ref_param): Remove error state
+ and use optional.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Check label
+ before visiting.
+ * ast/rust-ast.cc (ContinueExpr::as_string): Retrieve label value.
+ (Lifetime::as_string): Retrieve lifetime value.
+ (ReferenceType::as_string): Likewise.
+ (SelfParam::as_string): Likewise.
+ * ast/rust-ast.h: Remove lifetime and LifetimeParam error state.
+ * ast/rust-desugar-for-loops.cc (DesugarForLoops::DesugarCtx::make_break_arm):
+ Use optional instead of error state.
+ * ast/rust-expr.h (class ContinueExpr): Make label optional.
+ * ast/rust-item.h (class SelfParam): Make lifetime optional.
+ * ast/rust-type.h (class ReferenceType): Likewise.
+ * backend/rust-compile-base.cc: Use optional for self param instead
+ of error state.
+ * backend/rust-compile-base.h: Update function prototype.
+ * expand/rust-derive-clone.cc (DeriveClone::clone_fn): Use optional.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_self): Lower
+ lifetime only if it exists.
+ * hir/rust-ast-lower-block.h: Lower loop label only if it exists.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): Remove
+ references to error state.
+ (ASTLowerTraitItem::visit): Lower self param only if it exists.
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Use nullopt
+ for default value instead of SelfParam error state.
+ * hir/rust-ast-lower.cc (ASTLoweringExprWithBlock::visit): Lower label
+ only if it exists.
+ * hir/rust-hir-dump.cc (Dump::do_traitfunctiondecl): Print self only if
+ it exists.
+ (Dump::visit): Liewise.
+ * hir/tree/rust-hir-bound.h: Remove error state.
+ * hir/tree/rust-hir-expr.cc (ContinueExpr::ContinueExpr): Use optional
+ in constructor for loop label.
+ (BreakExpr::BreakExpr): Likewise.
+ * hir/tree/rust-hir-expr.h (class ContinueExpr): Remove error state
+ implementation.
+ (class BreakExpr): Likewise.
+ * hir/tree/rust-hir-generic-param.h: Likewise.
+ * hir/tree/rust-hir-item.cc (SelfParam::SelfParam): Make lifetime
+ optional.
+ (Function::Function): Make self param optional.
+ * hir/tree/rust-hir-item.h (class Function): Likewise.
+ * hir/tree/rust-hir-type.cc (ReferenceType::ReferenceType): Make
+ lifetime optional.
+ * hir/tree/rust-hir-type.h (class ReferenceType): Likewise.
+ * hir/tree/rust-hir.cc (ContinueExpr::as_string): Use new getter.
+ (BreakExpr::as_string): Likewise.
+ (Lifetime::as_string): Likewise.
+ (ReferenceType::as_string): Likewise.
+ (TraitFunctionDecl::as_string): Likewise.
+ (SelfParam::as_string): Remove error state checking.
+ * parse/rust-parse-impl.h (Parser::parse_generic_param): Adapt to
+ optional.
+ (Parser::parse_lifetime_params): Likewise.
+ (Parser::parse_lifetime_params_objs): Likewise.
+ (Parser::parse_lifetime_param): Likewise.
+ (Parser::parse_lifetime_where_clause_item): Likewise.
+ (Parser::parse_type_param_bound): Likewise.
+ (Parser::parse_lifetime_bounds): Likewise.
+ (Parser::parse_path_generic_args): Likewise.
+ (Parser::parse_self_param): Likewise.
+ (Parser::parse_break_expr): Likewise.
+ (Parser::parse_continue_expr): Likewise.
+ (Parser::parse_reference_type_inner): Likewise.
+ * parse/rust-parse.h (class ParseLifetimeParamError): Add new class for
+ lifetime param parsing errors.
+ (class ParseLifetimeError): Add new class for lifetime parsing errors.
+ (enum ParseSelfError): Add new class for self param parsing errors.
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItem::visit):
+ Use unchecked getter in checked context. And make anonymous region.
+ * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn):
+ Likewise.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Add
+ check for loop label before visiting it.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-expr.h: Remove error getter and constructor.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-builder.cc (Builder::block): Call with a nullopt instead
+ of an error loop label.
+ (WhileLetLoopExpr::as_string): Use getter function and adapt to
+ newtype.
+ * ast/rust-ast.cc (WhileLoopExpr::as_string): Likewise.
+ (LoopExpr::as_string): Likewise.
+ (BreakExpr::as_string): Likewise.
+ (ForLoopExpr::as_string): Likewise.
+ * ast/rust-expr.h (class BlockExpr): Make loop label optional.
+ (class BreakExpr): Likewise.
+ * expand/rust-derive-clone.cc (DeriveClone::clone_fn): Use nullopt.
+ * expand/rust-derive-debug.cc (DeriveDebug::stub_debug_fn): Likewise.
+ * expand/rust-derive-default.cc (DeriveDefault::default_fn): Likewise.
+ * expand/rust-derive-eq.cc: Likewise.
+ * parse/rust-parse-impl.h (Parser::parse_block_expr): Use optional
+ for arguments.
+ (Parser::parse_loop_expr): Likewise.
+ (Parser::parse_while_loop_expr): Likewise.
+ (Parser::parse_while_let_loop_expr): Likewise.
+ (Parser::parse_for_loop_expr): Likewise.
+ (Parser::parse_labelled_loop_expr): Likewise.
+ (Parser::parse_loop_label): Return an optional.
+ * parse/rust-parse.h: Update function prototype and use nullopt for
+ default values.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Change default
+ visit order.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit loop label
+ only if it exists.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * hir/rust-ast-lower.cc (ASTLoweringBlock::visit): Lower label only if
+ it exists.
+ * hir/tree/rust-hir-expr.cc (BlockExpr::BlockExpr): Make loop label
+ optional.
+ (BaseLoopExpr::BaseLoopExpr): Likewise.
+ (LoopExpr::LoopExpr): Likewise.
+ (WhileLoopExpr::WhileLoopExpr): Likewise.
+ * hir/tree/rust-hir-expr.h: Use optional for lifetime and labels.
+ * hir/tree/rust-hir.cc (WhileLoopExpr::as_string): Use getter.
+ (WhileLetLoopExpr::as_string): Likewise.
+ (LoopExpr::as_string): Likewise.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Resolve labels.
+ * resolve/rust-late-name-resolver-2.0.h: Add visit function prototype
+ for loop labels.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * util/expected.h: Use gcc_unreachable within gcc context.
+
+2025-04-08 Sri Ganesh Thota <sriganeshthota12345@gmail.com>
+
+ * resolve/rust-ast-resolve-base.h (redefined_error): created a function for
+ rust_error_at for redefined at multiple times.
+ * resolve/rust-ast-resolve-implitem.h: changed rust_error_at to redefined_error.
+ * resolve/rust-ast-resolve-stmt.cc (ResolveStmt::visit): changed rust_error_at to
+ redefined_error.
+ * resolve/rust-ast-resolve-stmt.h: changed rust_error_at to redefined_error.
+ * resolve/rust-ast-resolve-toplevel.h: changed rust_error_at to redefined_error.
+
+2025-04-08 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-visitor.cc
+ (DefaultASTVisitor::visit): Remove explicit visitation of a
+ function's self parameter, as if it exists it'll be visited as
+ one of the function parameters.
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-typecheck-context.cc (TypeCheckContext::lookup_lifetime): emit error
+
+2025-04-08 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.cc (Function::Function): Rename is_default -> has_default.
+ (Function::operator=): Likewise.
+ * ast/rust-item.h (class Function): Add `is_default` method.
+ * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): Lower default qualifier.
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise.
+ * hir/tree/rust-hir-item.cc (Function::Function): Add `is_default` member.
+ (Function::operator=): Likewise.
+ * hir/tree/rust-hir-item.h (enum class Defaultness): New enum.
+ (class Function): Use it.
+
+2025-04-08 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * checks/errors/rust-feature.cc (Feature::create): Handle `#![feature(min_specialization)]`.
+ * checks/errors/rust-feature.h: Likewise.
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * resolve/rust-ast-resolve-type.cc (ResolveRelativeTypePath::go): fix error msg
+ * typecheck/rust-substitution-mapper.cc (SubstMapper::Resolve): add validation
+ (SubstMapper::valid_type): new check
+ (SubstMapper::visit): check if can resolve
+ * typecheck/rust-substitution-mapper.h: new prototype
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.cc (HIRCompileBase::address_expression): allow optional type
+ * backend/rust-compile-base.h: update prototype
+ * backend/rust-compile-expr.cc (CompileExpr::visit): update borrow expr
+ * backend/rust-compile-extern.h: remove unused debug
+ * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): update usage
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): lower raw ref
+ * hir/tree/rust-hir-expr.cc (BorrowExpr::BorrowExpr): add flag for raw ref
+ * hir/tree/rust-hir-expr.h (class BorrowExpr): add new raw ref field
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): add handle for raw ref
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): emit error
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): new argument
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::TypeCheckBase): new helper
+ * typecheck/rust-hir-type-check-base.h: new helper prototype
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelExternItem::visit):
+ remove comment out code
+ * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_root_path): check for null
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path): likewise
+ (TypeResolveGenericParam::Resolve): new args
+ (TypeResolveGenericParam::ApplyAnyTraitBounds): new helper
+ (TypeResolveGenericParam::apply_trait_bounds): new field
+ (TypeResolveGenericParam::visit): update
+ * typecheck/rust-hir-type-check-type.h: new args
+ * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): reuse helper
+ * typecheck/rust-type-util.cc (query_type): check for recursive query
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::SubstitutionParamMapping):
+ remove const
+ (SubstitutionParamMapping::get_generic_param): likewise
+ * typecheck/rust-tyty-subst.h: likewise
+ * typecheck/rust-tyty-variance-analysis.cc (GenericTyVisitorCtx::process_type): likewise
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.cc: new flag is_root_item
+ * backend/rust-compile-base.h: update prototype
+ * backend/rust-compile-implitem.cc (CompileTraitItem::visit): update call
+ * backend/rust-compile-implitem.h: remove old debug internal error
+ * backend/rust-compile-item.cc (CompileItem::visit): update call
+ * backend/rust-compile-item.h: remove old debug
+ * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): update calls
+ * backend/rust-compile.cc: likewise
+ * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_path_to_trait):
+ remove assertion and error
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-base.cc: remove assertion
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * rust-gcc.cc (arithmetic_or_logical_expression): unwrap const decls
+
+2025-04-08 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-forever-stack.h
+ (ForeverStack::ForeverStack): Initialize extern_prelude.
+ (ForeverStack::resolve_path): Add parameter
+ has_opening_scope_resolution.
+ (ForeverStack::extern_prelude): Add field.
+ * resolve/rust-forever-stack.hxx: Include rust-edition.h.
+ (ForeverStacl::resolve_path): Handle global paths (paths with an
+ opening scope resolution operator).
+ * resolve/rust-late-name-resolver-2.0.cc
+ (Late::visit): Handle global paths.
+ * resolve/rust-name-resolution-context.h
+ (NameResolutionContext::resolve_path): Handle global paths.
+
+2025-04-08 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * backend/rust-compile-resolve-path.cc: Evaluate the enum's discriminant in a const context
+
2025-03-31 Philip Herron <herron.philip@googlemail.com>
* typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path):
@@ -1939,7 +6937,7 @@
2025-03-21 Owen Avery <powerboat9.gamer@gmail.com>
- * resolve/rust-name-resolver.cc: Include options.txt.
+ * resolve/rust-name-resolver.cc: Include options.h.
(Resolver::insert_resolved_name): Assert that name resolution
2.0 is disabled.
(Resolver::lookup_resolved_name): Likewise.
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 4028b47..e5a8a5e 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,8 @@ GRS_OBJS = \
rust/rust-ast-dump.o \
rust/rust-ast-collector.o \
rust/rust-ast-visitor.o \
+ rust/rust-ast-pointer-visitor.o \
+ rust/rust-hir-visitor.o \
rust/rust-hir-dump.o \
rust/rust-session-manager.o \
rust/rust-compile.o \
@@ -92,14 +97,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,8 +119,10 @@ 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 \
rust/rust-fmt.o \
rust/rust-hir.o \
rust/rust-hir-map.o \
@@ -122,7 +130,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 \
@@ -141,17 +148,8 @@ GRS_OBJS = \
rust/rust-ice-finalizer.o \
rust/rust-late-name-resolver-2.0.o \
rust/rust-immutable-name-resolution-context.o \
- rust/rust-early-name-resolver.o \
rust/rust-name-resolver.o \
- rust/rust-ast-resolve.o \
- rust/rust-ast-resolve-base.o \
- rust/rust-ast-resolve-item.o \
- rust/rust-ast-resolve-pattern.o \
- rust/rust-ast-resolve-expr.o \
- rust/rust-ast-resolve-type.o \
- rust/rust-ast-resolve-path.o \
- rust/rust-ast-resolve-stmt.o \
- rust/rust-ast-resolve-struct-expr-field.o \
+ rust/rust-resolve-builtins.o \
rust/rust-forever-stack.o \
rust/rust-hir-type-check.o \
rust/rust-privacy-check.o \
@@ -236,11 +234,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
@@ -431,6 +434,7 @@ RUST_INCLUDES = -I $(srcdir)/rust \
-I $(srcdir)/rust/checks/errors \
-I $(srcdir)/rust/checks/errors/privacy \
-I $(srcdir)/rust/checks/errors/borrowck \
+ -I $(srcdir)/rust/checks/errors/feature \
-I $(srcdir)/rust/util \
-I $(srcdir)/rust/metadata \
-I $(srcdir)/../libgrust
@@ -503,6 +507,11 @@ rust/%.o: rust/checks/errors/%.cc
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
$(POSTCOMPILE)
+# build feature related files in rust folder
+rust/%.o: rust/checks/errors/feature/%.cc
+ $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+ $(POSTCOMPILE)
+
# build privacy pass files in rust folder
rust/%.o: rust/checks/errors/privacy/%.cc
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
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 cdc6eec..632f945 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 {
@@ -137,7 +135,7 @@ Builder::tuple (std::vector<std::unique_ptr<Expr>> &&values) const
std::unique_ptr<Param>
Builder::self_ref_param (bool mutability) const
{
- return std::make_unique<SelfParam> (Lifetime::error (), mutability, loc);
+ return std::make_unique<SelfParam> (tl::nullopt, mutability, loc);
}
std::unique_ptr<Param>
@@ -332,12 +330,18 @@ 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
{
- return std::unique_ptr<BlockExpr> (
- new BlockExpr (std::move (stmts), std::move (tail_expr), {}, {},
- LoopLabel::error (), loc, loc));
+ return std::unique_ptr<BlockExpr> (new BlockExpr (std::move (stmts),
+ std::move (tail_expr), {},
+ {}, tl::nullopt, loc, loc));
}
std::unique_ptr<Expr>
@@ -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,23 +540,26 @@ 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>
Builder::new_lifetime_param (LifetimeParam &param)
{
Lifetime l = new_lifetime (param.get_lifetime ());
+
std::vector<Lifetime> lifetime_bounds;
+ lifetime_bounds.reserve (param.get_lifetime_bounds ().size ());
+
for (auto b : param.get_lifetime_bounds ())
- {
- Lifetime bl = new_lifetime (b);
- lifetime_bounds.push_back (bl);
- }
+ lifetime_bounds.emplace_back (new_lifetime (b));
auto p = new LifetimeParam (l, std::move (lifetime_bounds),
param.get_outer_attrs (), param.get_locus ());
@@ -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 ();
@@ -574,11 +605,11 @@ Builder::new_type_param (
for (const auto &lifetime : tb.get_for_lifetimes ())
{
std::vector<Lifetime> lifetime_bounds;
+ lifetime_bounds.reserve (
+ lifetime.get_lifetime_bounds ().size ());
+
for (const auto &b : lifetime.get_lifetime_bounds ())
- {
- Lifetime bl = new_lifetime (b);
- lifetime_bounds.push_back (std::move (bl));
- }
+ lifetime_bounds.emplace_back (new_lifetime (b));
Lifetime nl = new_lifetime (lifetime.get_lifetime ());
LifetimeParam p (std::move (nl), std::move (lifetime_bounds),
@@ -591,33 +622,34 @@ 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 (
+
+ segments.emplace_back (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));
+ segment.get_locus ()));
}
break;
- case TypePathSegment::GENERIC: {
+ case TypePathSegment::GENERIC:
+ {
TypePathSegmentGeneric &generic
= (TypePathSegmentGeneric &) (*seg.get ());
GenericArgs args
= new_generic_args (generic.get_generic_args ());
- TypePathSegmentGeneric *s = new TypePathSegmentGeneric (
+
+ segments.emplace_back (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));
+ generic.get_locus ()));
}
break;
- case TypePathSegment::FUNCTION: {
+ case TypePathSegment::FUNCTION:
+ {
rust_unreachable ();
// TODO
// const TypePathSegmentFunction &fn
@@ -630,22 +662,19 @@ Builder::new_type_param (
TypePath p (std::move (segments), path.get_locus (),
path.has_opening_scope_resolution_op ());
- TraitBound *b = new TraitBound (std::move (p), tb.get_locus (),
- tb.is_in_parens (),
- tb.has_opening_question_mark (),
- std::move (for_lifetimes));
- std::unique_ptr<TypeParamBound> bound (b);
- type_param_bounds.push_back (std::move (bound));
+ type_param_bounds.emplace_back (new TraitBound (
+ std::move (p), tb.get_locus (), tb.is_in_parens (),
+ tb.has_opening_question_mark (), std::move (for_lifetimes)));
}
break;
- case TypeParamBound::TypeParamBoundType::LIFETIME: {
+ case TypeParamBound::TypeParamBoundType::LIFETIME:
+ {
const Lifetime &l = (const Lifetime &) *b.get ();
- auto bl = new Lifetime (l.get_lifetime_type (),
- l.get_lifetime_name (), l.get_locus ());
- std::unique_ptr<TypeParamBound> bound (bl);
- type_param_bounds.push_back (std::move (bound));
+ type_param_bounds.emplace_back (
+ new Lifetime (l.get_lifetime_type (), l.get_lifetime_name (),
+ l.get_locus ()));
}
break;
}
@@ -674,35 +703,37 @@ Builder::new_generic_args (GenericArgs &args)
location_t locus = args.get_locus ();
for (const auto &lifetime : args.get_lifetime_args ())
- {
- Lifetime l = new_lifetime (lifetime);
- lifetime_args.push_back (std::move (l));
- }
+ lifetime_args.push_back (new_lifetime (lifetime));
for (auto &binding : args.get_binding_args ())
{
Type &t = *binding.get_type_ptr ().get ();
- std::unique_ptr<Type> ty = new_type (t);
- GenericArgsBinding b (binding.get_identifier (), std::move (ty),
- binding.get_locus ());
- binding_args.push_back (std::move (b));
+ std::unique_ptr<Type> ty = t.reconstruct ();
+ binding_args.emplace_back (binding.get_identifier (), std::move (ty),
+ binding.get_locus ());
}
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 3297407..721d274 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"
@@ -75,13 +76,13 @@ TokenCollector::trailing_comma ()
void
TokenCollector::newline ()
{
- tokens.push_back ({CollectItem::Kind::Newline});
+ tokens.emplace_back (CollectItem::Kind::Newline);
}
void
TokenCollector::indentation ()
{
- tokens.push_back ({indent_level});
+ tokens.emplace_back (indent_level);
}
void
@@ -100,7 +101,7 @@ TokenCollector::decrement_indentation ()
void
TokenCollector::comment (std::string comment)
{
- tokens.push_back ({comment});
+ tokens.emplace_back (comment);
}
void
@@ -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;
}
@@ -350,7 +355,8 @@ TokenCollector::visit (MaybeNamedParam &param)
void
TokenCollector::visit (Token &tok)
{
- std::string data = tok.get_tok_ptr ()->has_str () ? tok.get_str () : "";
+ std::string data
+ = tok.get_tok_ptr ()->should_have_str () ? tok.get_str () : "";
switch (tok.get_id ())
{
case IDENTIFIER:
@@ -491,7 +497,7 @@ TokenCollector::visit (ConstGenericParam &param)
if (param.has_default_value ())
{
push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
- visit (param.get_default_value ());
+ visit (param.get_default_value_unchecked ());
}
}
@@ -634,13 +640,12 @@ 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)));
}
break;
- case GenericArg::Kind::Error:
- rust_unreachable ();
}
}
@@ -791,7 +796,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)
@@ -835,13 +841,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
@@ -866,7 +872,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
@@ -1266,12 +1273,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
@@ -1279,7 +1308,7 @@ TokenCollector::visit (ContinueExpr &expr)
{
push (Rust::Token::make (CONTINUE, expr.get_locus ()));
if (expr.has_label ())
- visit (expr.get_label ());
+ visit (expr.get_label_unchecked ());
}
void
@@ -1287,7 +1316,7 @@ TokenCollector::visit (BreakExpr &expr)
{
push (Rust::Token::make (BREAK, expr.get_locus ()));
if (expr.has_label ())
- visit (expr.get_label ());
+ visit (expr.get_label_unchecked ());
if (expr.has_break_expr ())
visit (expr.get_break_expr ());
}
@@ -1351,6 +1380,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 ()));
@@ -1520,7 +1556,136 @@ 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)
+{
+ push (Rust::Token::make_identifier (expr.get_locus (), "llvm_asm"));
+ push (Rust::Token::make (EXCLAM, expr.get_locus ()));
+ push (Rust::Token::make (LEFT_PAREN, expr.get_locus ()));
+ for (auto &template_str : expr.get_templates ())
+ push (Rust::Token::make_string (template_str.get_locus (),
+ std::move (template_str.symbol)));
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+ for (auto output : expr.get_outputs ())
+ {
+ push (Rust::Token::make_string (expr.get_locus (),
+ std::move (output.constraint)));
+ visit (output.expr);
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+ for (auto input : expr.get_inputs ())
+ {
+ push (Rust::Token::make_string (expr.get_locus (),
+ std::move (input.constraint)));
+ visit (input.expr);
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+ for (auto &clobber : expr.get_clobbers ())
+ {
+ 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 ()));
+ // Dump options
+
+ push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ()));
+}
// rust-item.h
@@ -1656,7 +1821,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));
@@ -1676,7 +1842,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));
@@ -1704,7 +1871,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 (
@@ -1925,8 +2093,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 ());
@@ -2005,19 +2172,6 @@ TokenCollector::visit (SelfParam &param)
}
void
-TokenCollector::visit (TraitItemConst &item)
-{
- auto id = item.get_identifier ().as_string ();
- indentation ();
- push (Rust::Token::make (CONST, item.get_locus ()));
- push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
- push (Rust::Token::make (COLON, UNDEF_LOCATION));
- visit (item.get_type ());
- push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
- newline ();
-}
-
-void
TokenCollector::visit (TraitItemType &item)
{
visit_items_as_lines (item.get_outer_attrs ());
@@ -2331,10 +2485,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 ());
}
}
@@ -2466,7 +2620,7 @@ TokenCollector::visit (StructPattern &pattern)
if (elems.has_struct_pattern_fields ())
{
visit_items_joined_by_separator (elems.get_struct_pattern_fields ());
- if (elems.has_etc ())
+ if (elems.has_rest ())
{
push (Rust::Token::make (COMMA, UNDEF_LOCATION));
visit_items_as_lines (elems.get_etc_outer_attrs ());
@@ -2483,13 +2637,13 @@ TokenCollector::visit (StructPattern &pattern)
// void TokenCollector::visit(TupleStructItems& ){}
void
-TokenCollector::visit (TupleStructItemsNoRange &pattern)
+TokenCollector::visit (TupleStructItemsNoRest &pattern)
{
visit_items_joined_by_separator (pattern.get_patterns ());
}
void
-TokenCollector::visit (TupleStructItemsRange &pattern)
+TokenCollector::visit (TupleStructItemsHasRest &pattern)
{
for (auto &lower : pattern.get_lower_patterns ())
{
@@ -2516,13 +2670,13 @@ TokenCollector::visit (TupleStructPattern &pattern)
// {}
void
-TokenCollector::visit (TuplePatternItemsMultiple &pattern)
+TokenCollector::visit (TuplePatternItemsNoRest &pattern)
{
visit_items_joined_by_separator (pattern.get_patterns (), COMMA);
}
void
-TokenCollector::visit (TuplePatternItemsRanged &pattern)
+TokenCollector::visit (TuplePatternItemsHasRest &pattern)
{
for (auto &lower : pattern.get_lower_patterns ())
{
@@ -2552,10 +2706,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));
}
@@ -2819,8 +2997,234 @@ TokenCollector::visit (BareFunctionType &type)
void
TokenCollector::visit (AST::FormatArgs &fmt)
{
- rust_sorry_at (fmt.get_locus (), "%s:%u: unimplemented FormatArgs visitor",
- __FILE__, __LINE__);
+ push (Rust::Token::make_identifier (fmt.get_locus (), "format_args"));
+ push (Rust::Token::make (EXCLAM, fmt.get_locus ()));
+ push (Rust::Token::make (LEFT_PAREN, fmt.get_locus ()));
+
+ std::string reconstructed_template = "\"";
+ const auto &template_pieces = fmt.get_template ();
+
+ for (const auto &piece : template_pieces.get_pieces ())
+ {
+ if (piece.tag == Fmt::ffi::Piece::Tag::String)
+ {
+ std::string literal = piece.string._0.to_string ();
+ for (char c : literal)
+ {
+ if (c == '"' || c == '\\')
+ {
+ reconstructed_template += '\\';
+ }
+ else if (c == '\n')
+ {
+ reconstructed_template += "\\n";
+ continue;
+ }
+ else if (c == '\r')
+ {
+ reconstructed_template += "\\r";
+ continue;
+ }
+ else if (c == '\t')
+ {
+ reconstructed_template += "\\t";
+ continue;
+ }
+ reconstructed_template += c;
+ }
+ }
+ else if (piece.tag == Fmt::ffi::Piece::Tag::NextArgument)
+ {
+ reconstructed_template += "{";
+
+ const auto &argument = piece.next_argument._0;
+ const auto &position = argument.position;
+
+ switch (position.tag)
+ {
+ case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs:
+ break;
+ case Fmt::ffi::Position::Tag::ArgumentIs:
+ reconstructed_template
+ += std::to_string (position.argument_is._0);
+ break;
+ case Fmt::ffi::Position::Tag::ArgumentNamed:
+ reconstructed_template += position.argument_named._0.to_string ();
+ break;
+ }
+
+ // Add format specifiers if any (like :?, :x, etc.)
+ const auto &format_spec = argument.format;
+
+ bool has_format_spec = false;
+ std::string format_part;
+
+ // For now, skipping the complex format specifications that use FFIOpt
+ // since FFIOpt::get_opt() has a bug.
+
+ // Alignment
+ if (format_spec.align != Fmt::ffi::Alignment::AlignUnknown)
+ {
+ has_format_spec = true;
+ switch (format_spec.align)
+ {
+ case Fmt::ffi::Alignment::AlignLeft:
+ format_part += "<";
+ break;
+ case Fmt::ffi::Alignment::AlignRight:
+ format_part += ">";
+ break;
+ case Fmt::ffi::Alignment::AlignCenter:
+ format_part += "^";
+ break;
+ case Fmt::ffi::Alignment::AlignUnknown:
+ break;
+ }
+ }
+
+ // Alternate flag
+ if (format_spec.alternate)
+ {
+ has_format_spec = true;
+ format_part += "#";
+ }
+
+ // Zero pad flag
+ if (format_spec.zero_pad)
+ {
+ has_format_spec = true;
+ format_part += "0";
+ }
+
+ // Width
+ if (format_spec.width.tag != Fmt::ffi::Count::Tag::CountImplied)
+ {
+ has_format_spec = true;
+ switch (format_spec.width.tag)
+ {
+ case Fmt::ffi::Count::Tag::CountIs:
+ format_part += std::to_string (format_spec.width.count_is._0);
+ break;
+ case Fmt::ffi::Count::Tag::CountIsParam:
+ format_part
+ += std::to_string (format_spec.width.count_is_param._0)
+ + "$";
+ break;
+ case Fmt::ffi::Count::Tag::CountIsName:
+ format_part
+ += format_spec.width.count_is_name._0.to_string () + "$";
+ break;
+ case Fmt::ffi::Count::Tag::CountIsStar:
+ format_part += "*";
+ break;
+ case Fmt::ffi::Count::Tag::CountImplied:
+ break;
+ }
+ }
+
+ // Precision
+ if (format_spec.precision.tag != Fmt::ffi::Count::Tag::CountImplied)
+ {
+ has_format_spec = true;
+ format_part += ".";
+ switch (format_spec.precision.tag)
+ {
+ case Fmt::ffi::Count::Tag::CountIs:
+ format_part
+ += std::to_string (format_spec.precision.count_is._0);
+ break;
+ case Fmt::ffi::Count::Tag::CountIsParam:
+ format_part
+ += std::to_string (format_spec.precision.count_is_param._0)
+ + "$";
+ break;
+ case Fmt::ffi::Count::Tag::CountIsName:
+ format_part
+ += format_spec.precision.count_is_name._0.to_string ()
+ + "$";
+ break;
+ case Fmt::ffi::Count::Tag::CountIsStar:
+ format_part += "*";
+ break;
+ case Fmt::ffi::Count::Tag::CountImplied:
+ break;
+ }
+ }
+
+ // Type/trait (like ?, x, X, etc.)
+ std::string type_str = format_spec.ty.to_string ();
+ if (!type_str.empty ())
+ {
+ has_format_spec = true;
+ format_part += type_str;
+ }
+
+ // Add the format specification if any
+ if (has_format_spec)
+ {
+ reconstructed_template += ":";
+ reconstructed_template += format_part;
+ }
+
+ reconstructed_template += "}";
+ }
+ }
+ reconstructed_template += "\"";
+
+ push (Rust::Token::make_string (fmt.get_locus (), reconstructed_template));
+
+ // Visit format arguments if any exist
+ auto &arguments = fmt.get_arguments ();
+ if (!arguments.empty ())
+ {
+ push (Rust::Token::make (COMMA, fmt.get_locus ()));
+
+ auto &args = arguments.get_args ();
+ for (size_t i = 0; i < args.size (); ++i)
+ {
+ if (i > 0)
+ {
+ push (Rust::Token::make (COMMA, fmt.get_locus ()));
+ }
+
+ auto kind = args[i].get_kind ();
+
+ // Handle named arguments: name = expr
+ if (kind.kind == FormatArgumentKind::Kind::Named)
+ {
+ auto ident = kind.get_ident ().as_string ();
+ push (Rust::Token::make_identifier (fmt.get_locus (),
+ std::move (ident)));
+ push (Rust::Token::make (EQUAL, fmt.get_locus ()));
+ }
+ // Note: Captured arguments are handled implicitly in the template
+ // reconstruction They don't need explicit "name =" syntax in the
+ // reconstructed macro call
+
+ auto &expr = args[i].get_expr ();
+ expr.accept_vis (*this);
+ }
+ }
+
+ push (Rust::Token::make (RIGHT_PAREN, fmt.get_locus ()));
+}
+
+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
diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h
index b014c23..3e33476 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);
@@ -303,6 +306,7 @@ public:
void visit (AwaitExpr &expr);
void visit (AsyncBlockExpr &expr);
void visit (InlineAsm &expr);
+ void visit (LlvmInlineAsm &expr);
// rust-item.h
void visit (TypeParam &param);
void visit (LifetimeWhereClauseItem &item);
@@ -326,7 +330,6 @@ public:
void visit (ConstantItem &const_item);
void visit (StaticItem &static_item);
void visit (SelfParam &param);
- void visit (TraitItemConst &item);
void visit (TraitItemType &item);
void visit (Trait &trait);
void visit (InherentImpl &impl);
@@ -366,14 +369,16 @@ public:
void visit (StructPatternFieldIdent &field);
void visit (StructPattern &pattern);
// void visit(TupleStructItems& tuple_items);
- void visit (TupleStructItemsNoRange &tuple_items);
- void visit (TupleStructItemsRange &tuple_items);
+ void visit (TupleStructItemsNoRest &tuple_items);
+ void visit (TupleStructItemsHasRest &tuple_items);
void visit (TupleStructPattern &pattern);
// void visit(TuplePatternItems& tuple_items);
- void visit (TuplePatternItemsMultiple &tuple_items);
- void visit (TuplePatternItemsRanged &tuple_items);
+ void visit (TuplePatternItemsNoRest &tuple_items);
+ void visit (TuplePatternItemsHasRest &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);
@@ -399,6 +404,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..075c51c 100644
--- a/gcc/rust/ast/rust-ast-formatting.h
+++ b/gcc/rust/ast/rust-ast-formatting.h
@@ -19,6 +19,9 @@
#ifndef RUST_AST_FORMATTING_H
#define RUST_AST_FORMATTING_H
+#include "rust-ast.h"
+#include "rust-system.h"
+
namespace Rust {
namespace AST {
@@ -35,23 +38,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-fragment.cc b/gcc/rust/ast/rust-ast-fragment.cc
index 076cab3..8a547b4 100644
--- a/gcc/rust/ast/rust-ast-fragment.cc
+++ b/gcc/rust/ast/rust-ast-fragment.cc
@@ -107,29 +107,42 @@ Fragment::should_expand () const
bool
Fragment::is_expression_fragment () const
{
- return is_single_fragment_of_kind (SingleASTNode::NodeType::EXPRESSION);
+ return is_single_fragment_of_kind (SingleASTNode::Kind::Expr);
}
bool
Fragment::is_type_fragment () const
{
- return is_single_fragment_of_kind (SingleASTNode::NodeType::TYPE);
+ return is_single_fragment_of_kind (SingleASTNode::Kind::Type);
+}
+
+bool
+Fragment::is_pattern_fragment () const
+{
+ return is_single_fragment_of_kind (SingleASTNode::Kind::Pattern);
}
std::unique_ptr<Expr>
Fragment::take_expression_fragment ()
{
- assert_single_fragment (SingleASTNode::NodeType::EXPRESSION);
+ assert_single_fragment (SingleASTNode::Kind::Expr);
return nodes[0].take_expr ();
}
std::unique_ptr<Type>
Fragment::take_type_fragment ()
{
- assert_single_fragment (SingleASTNode::NodeType::TYPE);
+ assert_single_fragment (SingleASTNode::Kind::Type);
return nodes[0].take_type ();
}
+std::unique_ptr<Pattern>
+Fragment::take_pattern_fragment ()
+{
+ assert_single_fragment (SingleASTNode::Kind::Pattern);
+ return nodes[0].take_pattern ();
+}
+
void
Fragment::accept_vis (ASTVisitor &vis)
{
@@ -144,21 +157,22 @@ Fragment::is_single_fragment () const
}
bool
-Fragment::is_single_fragment_of_kind (SingleASTNode::NodeType expected) const
+Fragment::is_single_fragment_of_kind (SingleASTNode::Kind expected) const
{
return is_single_fragment () && nodes[0].get_kind () == expected;
}
void
-Fragment::assert_single_fragment (SingleASTNode::NodeType expected) const
-{
- static const std::map<SingleASTNode::NodeType, const char *> str_map = {
- {SingleASTNode::NodeType::ASSOC_ITEM, "associated item"},
- {SingleASTNode::NodeType::ITEM, "item"},
- {SingleASTNode::NodeType::TYPE, "type"},
- {SingleASTNode::NodeType::EXPRESSION, "expr"},
- {SingleASTNode::NodeType::STMT, "stmt"},
- {SingleASTNode::NodeType::EXTERN, "extern"},
+Fragment::assert_single_fragment (SingleASTNode::Kind expected) const
+{
+ static const std::map<SingleASTNode::Kind, const char *> str_map = {
+ {SingleASTNode::Kind::Assoc, "associated item"},
+ {SingleASTNode::Kind::Item, "item"},
+ {SingleASTNode::Kind::Type, "type"},
+ {SingleASTNode::Kind::Expr, "expr"},
+ {SingleASTNode::Kind::Stmt, "stmt"},
+ {SingleASTNode::Kind::Extern, "extern"},
+ {SingleASTNode::Kind::Pattern, "pattern"},
};
auto actual = nodes[0].get_kind ();
diff --git a/gcc/rust/ast/rust-ast-fragment.h b/gcc/rust/ast/rust-ast-fragment.h
index 7d01fd7..23f26d3 100644
--- a/gcc/rust/ast/rust-ast-fragment.h
+++ b/gcc/rust/ast/rust-ast-fragment.h
@@ -86,9 +86,11 @@ public:
bool is_expression_fragment () const;
bool is_type_fragment () const;
+ bool is_pattern_fragment () const;
std::unique_ptr<Expr> take_expression_fragment ();
std::unique_ptr<Type> take_type_fragment ();
+ std::unique_ptr<Pattern> take_pattern_fragment ();
void accept_vis (ASTVisitor &vis);
@@ -119,8 +121,8 @@ private:
* one Node will be extracted from the `nodes` vector
*/
bool is_single_fragment () const;
- bool is_single_fragment_of_kind (SingleASTNode::NodeType expected) const;
- void assert_single_fragment (SingleASTNode::NodeType expected) const;
+ bool is_single_fragment_of_kind (SingleASTNode::Kind expected) const;
+ void assert_single_fragment (SingleASTNode::Kind expected) const;
};
enum class InvocKind
diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
index 9359248..2903ba7 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;
@@ -193,7 +195,6 @@ class Enum;
class Union;
class ConstantItem;
class StaticItem;
-class TraitItemConst;
class TraitItemType;
class Trait;
class Impl;
@@ -238,14 +239,16 @@ class StructPatternFieldIdent;
class StructPatternElements;
class StructPattern;
class TupleStructItems;
-class TupleStructItemsNoRange;
-class TupleStructItemsRange;
+class TupleStructItemsNoRest;
+class TupleStructItemsHasRest;
class TupleStructPattern;
class TuplePatternItems;
-class TuplePatternItemsMultiple;
-class TuplePatternItemsRanged;
+class TuplePatternItemsNoRest;
+class TuplePatternItemsHasRest;
class TuplePattern;
class GroupedPattern;
+class SlicePatternItemsNoRest;
+class SlicePatternItemsHasRest;
class SlicePattern;
class AltPattern;
diff --git a/gcc/rust/ast/rust-ast-pointer-visitor.cc b/gcc/rust/ast/rust-ast-pointer-visitor.cc
new file mode 100644
index 0000000..ee1f001
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-pointer-visitor.cc
@@ -0,0 +1,1475 @@
+// 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-ast-pointer-visitor.h"
+#include "rust-ast-visitor.h"
+#include "rust-ast-full.h"
+
+namespace Rust {
+namespace AST {
+
+void
+PointerVisitor::visit (AST::Crate &crate)
+{
+ visit_inner_attrs (crate);
+ for (auto &item : crate.items)
+ reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::AttrInputMetaItemContainer &input)
+{
+ // FIXME: I think we might actually have to reseat sub-items for macro
+ // invocations within attributes correct?
+
+ for (auto &item : input.get_items ())
+ visit (item);
+}
+
+void
+PointerVisitor::visit (AST::IdentifierExpr &ident_expr)
+{
+ visit_outer_attrs (ident_expr);
+}
+
+void
+PointerVisitor::visit (AST::LifetimeParam &lifetime_param)
+{
+ visit_outer_attrs (lifetime_param);
+
+ // Nothing to do for lifetimes right?
+}
+
+void
+PointerVisitor::visit (AST::ConstGenericParam &const_param)
+{
+ visit_outer_attrs (const_param);
+ if (const_param.has_type ())
+ reseat (const_param.get_type_ptr ());
+
+ if (const_param.has_default_value ())
+ visit (const_param.get_default_value_unchecked ());
+}
+
+void
+PointerVisitor::visit (AST::PathInExpression &path)
+{
+ visit_outer_attrs (path);
+
+ if (!path.is_lang_item ())
+ for (auto &segment : path.get_segments ())
+ visit (segment);
+}
+
+void
+PointerVisitor::visit (GenericArgsBinding &binding)
+{
+ reseat (binding.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TypePathSegmentGeneric &segment)
+{
+ if (segment.has_generic_args ())
+ visit (segment.get_generic_args ());
+}
+
+void
+PointerVisitor::visit (AST::TypePathFunction &tpf)
+{
+ for (auto &input : tpf.get_params ())
+ reseat (input);
+ if (tpf.has_return_type ())
+ reseat (tpf.get_return_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TypePathSegmentFunction &segment)
+{
+ // FIXME: No reseating here correct? No macros possible or desugar?
+ visit (segment.get_type_path_function ());
+ visit (segment.get_ident_segment ());
+}
+
+void
+PointerVisitor::visit (AST::GenericArgs &args)
+{
+ // Nothing to do for lifetimes?
+ // for (auto &lifetime : args.get_lifetime_args ())
+ // reseat (lifetime);
+
+ // FIXME: Actually this can probably be a macro invocation, so we need to
+ // reseat them?
+ for (auto &generic : args.get_generic_args ())
+ visit (generic);
+
+ for (auto &binding : args.get_binding_args ())
+ visit (binding);
+}
+
+void
+PointerVisitor::visit (AST::PathExprSegment &segment)
+{
+ visit (segment.get_ident_segment ());
+ if (segment.has_generic_args ())
+ visit (segment.get_generic_args ());
+}
+void
+PointerVisitor::visit (AST::TypePath &path)
+{
+ for (auto &segment : path.get_segments ())
+ visit (segment);
+}
+
+void
+PointerVisitor::visit (AST::QualifiedPathInExpression &path)
+{
+ visit_outer_attrs (path);
+ visit (path.get_qualified_path_type ());
+
+ for (auto &segment : path.get_segments ())
+ visit (segment);
+}
+
+void
+PointerVisitor::visit (AST::QualifiedPathType &path)
+{
+ reseat (path.get_type_ptr ());
+ if (path.has_as_clause ())
+ visit (path.get_as_type_path ());
+}
+
+void
+PointerVisitor::visit (AST::QualifiedPathInType &path)
+{
+ visit (path.get_qualified_path_type ());
+ visit (path.get_associated_segment ());
+
+ for (auto &segment : path.get_segments ())
+ visit (segment);
+}
+
+void
+PointerVisitor::visit (AST::LiteralExpr &expr)
+{
+ visit_outer_attrs (expr);
+}
+
+void
+PointerVisitor::visit (AST::AttrInputLiteral &attr_input)
+{
+ visit (attr_input.get_literal ());
+}
+
+void
+PointerVisitor::visit (AST::AttrInputMacro &attr_input)
+{
+ visit (attr_input.get_macro ());
+}
+
+void
+PointerVisitor::visit (AST::MetaItemLitExpr &meta_item)
+{
+ visit (meta_item.get_literal ());
+}
+
+void
+PointerVisitor::visit (AST::SimplePath &path)
+{
+ for (auto &segment : path.get_segments ())
+ visit (segment);
+}
+
+void
+PointerVisitor::visit (AST::MetaItemPathExpr &meta_item)
+{
+ visit (meta_item.get_path ());
+ reseat (meta_item.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::BorrowExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_borrowed_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::DereferenceExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_dereferenced_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ErrorPropagationExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_propagating_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::NegationExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_negated_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ArithmeticOrLogicalExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_left_expr_ptr ());
+ reseat (expr.get_right_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ComparisonExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_left_expr_ptr ());
+ reseat (expr.get_right_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::LazyBooleanExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_left_expr_ptr ());
+ reseat (expr.get_right_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TypeCastExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_casted_expr_ptr ());
+ reseat (expr.get_type_to_cast_to_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::AssignmentExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_left_expr_ptr ());
+ reseat (expr.get_right_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::CompoundAssignmentExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_left_expr_ptr ());
+ reseat (expr.get_right_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::GroupedExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ reseat (expr.get_expr_in_parens_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ArrayElemsValues &elems)
+{
+ for (auto &value : elems.get_values ())
+ reseat (value);
+}
+
+void
+PointerVisitor::visit (AST::ArrayElemsCopied &elems)
+{
+ reseat (elems.get_elem_to_copy_ptr ());
+ reseat (elems.get_num_copies_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ArrayExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ visit (expr.get_array_elems ());
+}
+
+void
+PointerVisitor::visit (AST::ArrayIndexExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_array_expr_ptr ());
+ reseat (expr.get_index_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TupleExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ for (auto &elem : expr.get_tuple_elems ())
+ reseat (elem);
+}
+
+void
+PointerVisitor::visit (AST::TupleIndexExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_tuple_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructExprStruct &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ visit (expr.get_struct_name ());
+}
+
+void
+PointerVisitor::visit (AST::StructExprFieldIdentifier &field)
+{}
+
+void
+PointerVisitor::visit (AST::StructExprFieldIdentifierValue &field)
+{
+ reseat (field.get_value_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructExprFieldIndexValue &field)
+{
+ reseat (field.get_value_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructBase &base)
+{
+ reseat (base.get_base_struct_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructExprStructFields &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ visit (expr.get_struct_name ());
+ if (expr.has_struct_base ())
+ visit (expr.get_struct_base ());
+ for (auto &field : expr.get_fields ())
+ visit (field);
+}
+
+void
+PointerVisitor::visit (AST::StructExprStructBase &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ visit (expr.get_struct_name ());
+ visit (expr.get_struct_base ());
+}
+
+void
+PointerVisitor::visit (AST::CallExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_function_expr_ptr ());
+ for (auto &param : expr.get_params ())
+ reseat (param);
+}
+
+void
+PointerVisitor::visit (AST::MethodCallExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_receiver_expr_ptr ());
+ visit (expr.get_method_name ());
+ for (auto &param : expr.get_params ())
+ reseat (param);
+}
+
+void
+PointerVisitor::visit (AST::FieldAccessExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_receiver_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ClosureExprInner &expr)
+{
+ visit_outer_attrs (expr);
+
+ // TODO: Actually we need to handle macro invocations as closure parameters so
+ // this needs to be a reseat
+ for (auto &param : expr.get_params ())
+ visit (param);
+
+ reseat (expr.get_definition_expr_ptr ());
+}
+
+void
+PointerVisitor::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 ())
+ reseat (stmt);
+
+ if (expr.has_tail_expr ())
+ reseat (expr.get_tail_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ConstBlock &expr)
+{
+ visit (expr.get_const_expr ());
+}
+
+void
+PointerVisitor::visit (AST::AnonConst &expr)
+{
+ if (!expr.is_deferred ())
+ reseat (expr.get_inner_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ClosureExprInnerTyped &expr)
+{
+ visit_outer_attrs (expr);
+
+ // TODO: Same as ClosureExprInner
+ for (auto &param : expr.get_params ())
+ visit (param);
+
+ reseat (expr.get_return_type_ptr ());
+
+ reseat (expr.get_definition_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ClosureParam &param)
+{
+ visit_outer_attrs (param);
+ reseat (param.get_pattern_ptr ());
+ if (param.has_type_given ())
+ reseat (param.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ContinueExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_label ())
+ visit (expr.get_label_unchecked ());
+}
+
+void
+PointerVisitor::visit (AST::BreakExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_label ())
+ visit (expr.get_label_unchecked ());
+
+ if (expr.has_break_expr ())
+ reseat (expr.get_break_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::RangeFromToExpr &expr)
+{
+ reseat (expr.get_from_expr_ptr ());
+ reseat (expr.get_to_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::RangeFromExpr &expr)
+{
+ reseat (expr.get_from_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::RangeToExpr &expr)
+{
+ reseat (expr.get_to_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::RangeFullExpr &expr)
+{}
+
+void
+PointerVisitor::visit (AST::RangeFromToInclExpr &expr)
+{
+ reseat (expr.get_from_expr_ptr ());
+ reseat (expr.get_to_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::RangeToInclExpr &expr)
+{
+ reseat (expr.get_to_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ReturnExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_returned_expr ())
+ reseat (expr.get_returned_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TryExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_block_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::BoxExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_boxed_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::UnsafeBlockExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_block_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::LoopLabel &label)
+{
+ visit (label.get_lifetime ());
+}
+
+void
+PointerVisitor::visit (AST::LoopExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
+ reseat (expr.get_loop_block_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::WhileLoopExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
+ reseat (expr.get_predicate_expr_ptr ());
+ reseat (expr.get_loop_block_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::WhileLetLoopExpr &expr)
+{
+ visit_outer_attrs (expr);
+ for (auto &pattern : expr.get_patterns ())
+ reseat (pattern);
+
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
+
+ reseat (expr.get_scrutinee_expr_ptr ());
+ reseat (expr.get_loop_block_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ForLoopExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_pattern_ptr ());
+ reseat (expr.get_iterator_expr_ptr ());
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
+ reseat (expr.get_loop_block_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::IfExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_condition_expr_ptr ());
+ visit (expr.get_if_block ());
+}
+
+void
+PointerVisitor::visit (AST::IfExprConseqElse &expr)
+{
+ visit (reinterpret_cast<AST::IfExpr &> (expr));
+ visit (expr.get_else_block ());
+}
+
+void
+PointerVisitor::visit (AST::IfLetExpr &expr)
+{
+ visit_outer_attrs (expr);
+ for (auto &pattern : expr.get_patterns ())
+ reseat (pattern);
+ reseat (expr.get_value_expr_ptr ());
+ visit (expr.get_if_block ());
+}
+
+void
+PointerVisitor::visit (AST::IfLetExprConseqElse &expr)
+{
+ visit (reinterpret_cast<AST::IfLetExpr &> (expr));
+ visit (expr.get_else_block ());
+}
+
+void
+PointerVisitor::visit (AST::MatchArm &arm)
+{
+ visit_outer_attrs (arm);
+ for (auto &pattern : arm.get_patterns ())
+ reseat (pattern);
+ if (arm.has_match_arm_guard ())
+ reseat (arm.get_guard_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::MatchCase &arm)
+{
+ visit (arm.get_arm ());
+ reseat (arm.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::MatchExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ reseat (expr.get_scrutinee_expr_ptr ());
+ for (auto &arm : expr.get_match_cases ())
+ visit (arm);
+}
+
+void
+PointerVisitor::visit (AST::AwaitExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_awaited_expr ());
+}
+
+void
+PointerVisitor::visit (AST::AsyncBlockExpr &expr)
+{
+ visit_outer_attrs (expr);
+ reseat (expr.get_block_expr ());
+}
+
+void
+PointerVisitor::visit (AST::InlineAsm &expr)
+{
+ visit_outer_attrs (expr);
+ using RegisterType = AST::InlineAsmOperand::RegisterType;
+ for (auto &operand : expr.get_operands ())
+ {
+ switch (operand.get_register_type ())
+ {
+ case RegisterType::In:
+ {
+ reseat (operand.get_in ().expr);
+ break;
+ }
+ case RegisterType::Out:
+ {
+ reseat (operand.get_out ().expr);
+ break;
+ }
+ case RegisterType::InOut:
+ {
+ reseat (operand.get_in_out ().expr);
+ break;
+ }
+ case RegisterType::SplitInOut:
+ {
+ auto split = operand.get_split_in_out ();
+ reseat (split.in_expr);
+ reseat (split.out_expr);
+ break;
+ }
+ case RegisterType::Const:
+ {
+ reseat (operand.get_const ().anon_const.get_inner_expr_ptr ());
+ break;
+ }
+ case RegisterType::Sym:
+ {
+ reseat (operand.get_sym ().expr);
+ break;
+ }
+ case RegisterType::Label:
+ {
+ reseat (operand.get_label ().expr);
+ break;
+ }
+ }
+ }
+}
+
+void
+PointerVisitor::visit (AST::LlvmInlineAsm &expr)
+{
+ for (auto &output : expr.get_outputs ())
+ reseat (output.expr);
+
+ for (auto &input : expr.get_inputs ())
+ reseat (input.expr);
+}
+
+void
+PointerVisitor::visit (AST::TypeParam &param)
+{
+ visit_outer_attrs (param);
+ // FIXME: Can we do macro expansion here?
+ for (auto &bound : param.get_type_param_bounds ())
+ visit (bound);
+ if (param.has_type ())
+ reseat (param.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::LifetimeWhereClauseItem &item)
+{
+ visit (item.get_lifetime ());
+ for (auto &bound : item.get_lifetime_bounds ())
+ visit (bound);
+}
+
+void
+PointerVisitor::visit (AST::TypeBoundWhereClauseItem &item)
+{
+ for (auto &lifetime : item.get_for_lifetimes ())
+ visit (lifetime);
+ reseat (item.get_type_ptr ());
+ // FIXME: Likewise?
+ for (auto &param : item.get_type_param_bounds ())
+ visit (param);
+}
+
+void
+PointerVisitor::visit (AST::Visibility &vis)
+{
+ if (vis.has_path ())
+ visit (vis.get_path ());
+}
+
+void
+PointerVisitor::visit (AST::WhereClause &where)
+{
+ for (auto &item : where.get_items ())
+ visit (item);
+}
+
+void
+PointerVisitor::visit (AST::FunctionParam &param)
+{
+ visit_outer_attrs (param);
+ if (param.has_name ())
+ reseat (param.get_pattern_ptr ());
+
+ reseat (param.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::SelfParam &param)
+{
+ visit_outer_attrs (param);
+
+ if (param.has_lifetime ())
+ visit (param.get_lifetime ());
+
+ if (param.has_type ())
+ reseat (param.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::Module &module)
+{
+ visit_outer_attrs (module);
+ visit (module.get_visibility ());
+ visit_inner_attrs (module);
+ for (auto &item : module.get_items ())
+ reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::ExternCrate &crate)
+{
+ visit_outer_attrs (crate);
+ visit (crate.get_visibility ());
+}
+
+void
+PointerVisitor::visit (AST::UseTreeGlob &use_tree)
+{
+ visit (use_tree.get_path ());
+}
+
+void
+PointerVisitor::visit (AST::UseTreeList &use_tree)
+{
+ visit (use_tree.get_path ());
+}
+
+void
+PointerVisitor::visit (AST::UseTreeRebind &use_tree)
+{
+ visit (use_tree.get_path ());
+}
+
+void
+PointerVisitor::visit (AST::UseDeclaration &use_decl)
+{
+ visit (use_decl.get_visibility ());
+ visit (use_decl.get_tree ());
+}
+
+void
+PointerVisitor::visit_function_params (AST::Function &function)
+{
+ for (auto &param : function.get_function_params ())
+ visit (param);
+}
+
+void
+PointerVisitor::visit (AST::Function &function)
+{
+ visit_outer_attrs (function);
+ visit (function.get_visibility ());
+ visit (function.get_qualifiers ());
+ for (auto &generic : function.get_generic_params ())
+ visit (generic);
+
+ visit_function_params (function);
+
+ if (function.has_return_type ())
+ reseat (function.get_return_type_ptr ());
+ if (function.has_where_clause ())
+ visit (function.get_where_clause ());
+ if (function.has_body ())
+ reseat (*function.get_definition ());
+}
+
+void
+PointerVisitor::visit (AST::TypeAlias &type_alias)
+{
+ visit_outer_attrs (type_alias);
+ visit (type_alias.get_visibility ());
+ for (auto &generic : type_alias.get_generic_params ())
+ visit (generic);
+ if (type_alias.has_where_clause ())
+ visit (type_alias.get_where_clause ());
+ reseat (type_alias.get_type_aliased_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructField &field)
+{
+ visit_outer_attrs (field);
+ visit (field.get_visibility ());
+ reseat (field.get_field_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructStruct &struct_item)
+{
+ visit_outer_attrs (struct_item);
+ visit (struct_item.get_visibility ());
+ for (auto &generic : struct_item.get_generic_params ())
+ visit (generic);
+ if (struct_item.has_where_clause ())
+ visit (struct_item.get_where_clause ());
+ for (auto &field : struct_item.get_fields ())
+ visit (field);
+}
+
+void
+PointerVisitor::visit (AST::TupleField &field)
+{
+ visit_outer_attrs (field);
+ visit (field.get_visibility ());
+ reseat (field.get_field_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TupleStruct &tuple_struct)
+{
+ visit_outer_attrs (tuple_struct);
+ visit (tuple_struct.get_visibility ());
+ for (auto &generic : tuple_struct.get_generic_params ())
+ visit (generic);
+ if (tuple_struct.has_where_clause ())
+ visit (tuple_struct.get_where_clause ());
+ for (auto &field : tuple_struct.get_fields ())
+ visit (field);
+}
+
+void
+PointerVisitor::visit (AST::EnumItem &item)
+{
+ visit_outer_attrs (item);
+ visit (item.get_visibility ());
+}
+
+void
+PointerVisitor::visit (AST::EnumItemTuple &item)
+{
+ PointerVisitor::visit (static_cast<EnumItem &> (item));
+ for (auto &field : item.get_tuple_fields ())
+ visit (field);
+}
+
+void
+PointerVisitor::visit (AST::EnumItemStruct &item)
+{
+ PointerVisitor::visit (static_cast<EnumItem &> (item));
+ for (auto &field : item.get_struct_fields ())
+ visit (field);
+}
+
+void
+PointerVisitor::visit (AST::EnumItemDiscriminant &item)
+{
+ PointerVisitor::visit (static_cast<EnumItem &> (item));
+ reseat (item.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::Enum &enum_item)
+{
+ visit_outer_attrs (enum_item);
+ visit (enum_item.get_visibility ());
+ for (auto &generic : enum_item.get_generic_params ())
+ visit (generic);
+ if (enum_item.has_where_clause ())
+ visit (enum_item.get_where_clause ());
+ for (auto &item : enum_item.get_variants ())
+ visit (item);
+}
+
+void
+PointerVisitor::visit (AST::Union &union_item)
+{
+ visit_outer_attrs (union_item);
+ visit (union_item.get_visibility ());
+ for (auto &generic : union_item.get_generic_params ())
+ visit (generic);
+ if (union_item.has_where_clause ())
+ visit (union_item.get_where_clause ());
+ for (auto &variant : union_item.get_variants ())
+ visit (variant);
+}
+
+void
+PointerVisitor::visit (AST::ConstantItem &const_item)
+{
+ visit_outer_attrs (const_item);
+ visit (const_item.get_visibility ());
+ reseat (const_item.get_type_ptr ());
+ if (const_item.has_expr ())
+ reseat (const_item.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StaticItem &static_item)
+{
+ visit_outer_attrs (static_item);
+ visit (static_item.get_visibility ());
+ reseat (static_item.get_type_ptr ());
+ reseat (static_item.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TraitItemType &item)
+{
+ visit_outer_attrs (item);
+ for (auto &bound : item.get_type_param_bounds ())
+ visit (bound);
+}
+
+void
+PointerVisitor::visit (AST::Trait &trait)
+{
+ visit_outer_attrs (trait);
+ visit (trait.get_visibility ());
+
+ visit_inner_attrs (trait);
+
+ 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);
+
+ for (auto &item : trait.get_trait_items ())
+ reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::InherentImpl &impl)
+{
+ visit_outer_attrs (impl);
+ visit (impl.get_visibility ());
+
+ for (auto &generic : impl.get_generic_params ())
+ visit (generic);
+ if (impl.has_where_clause ())
+ visit (impl.get_where_clause ());
+ reseat (impl.get_type_ptr ());
+ visit_inner_attrs (impl);
+ for (auto &item : impl.get_impl_items ())
+ reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::TraitImpl &impl)
+{
+ visit_outer_attrs (impl);
+ visit (impl.get_visibility ());
+
+ for (auto &generic : impl.get_generic_params ())
+ visit (generic);
+ if (impl.has_where_clause ())
+ visit (impl.get_where_clause ());
+ reseat (impl.get_type_ptr ());
+ visit (impl.get_trait_path ());
+ visit_inner_attrs (impl);
+ for (auto &item : impl.get_impl_items ())
+ reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::ExternalTypeItem &item)
+{
+ visit_outer_attrs (item);
+ visit (item.get_visibility ());
+}
+
+void
+PointerVisitor::visit (AST::ExternalStaticItem &item)
+{
+ visit_outer_attrs (item);
+ visit (item.get_visibility ());
+ reseat (item.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ExternBlock &block)
+{
+ visit_outer_attrs (block);
+ visit (block.get_visibility ());
+ visit_inner_attrs (block);
+ for (auto &item : block.get_extern_items ())
+ reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::MacroMatchFragment &match)
+{}
+
+void
+PointerVisitor::visit (AST::MacroMatchRepetition &match)
+{
+ for (auto &m : match.get_matches ())
+ visit (m);
+}
+
+void
+PointerVisitor::visit (AST::MacroMatcher &matcher)
+{
+ for (auto &m : matcher.get_matches ())
+ visit (m);
+}
+
+void
+PointerVisitor::visit (AST::MacroTranscriber &transcriber)
+{
+ visit (transcriber.get_token_tree ());
+}
+
+void
+PointerVisitor::visit (AST::MacroRule &rule)
+{
+ visit (rule.get_matcher ());
+ visit (rule.get_transcriber ());
+}
+
+void
+PointerVisitor::visit (AST::MacroRulesDefinition &rules_def)
+{
+ visit_outer_attrs (rules_def);
+ for (auto &rule : rules_def.get_macro_rules ())
+ visit (rule);
+}
+
+void
+PointerVisitor::visit (AST::MacroInvocData &data)
+{
+ visit (data.get_path ());
+ visit (data.get_delim_tok_tree ());
+}
+
+void
+PointerVisitor::visit (AST::MacroInvocation &macro_invoc)
+{
+ visit_outer_attrs (macro_invoc);
+ visit (macro_invoc.get_invoc_data ());
+}
+
+void
+PointerVisitor::visit (AST::MetaItemPath &meta_item)
+{
+ visit (meta_item.get_path ());
+}
+
+void
+PointerVisitor::visit (AST::MetaItemSeq &meta_item)
+{
+ visit (meta_item.get_path ());
+ for (auto &inner : meta_item.get_seq ())
+ visit (inner);
+}
+
+void
+PointerVisitor::visit (AST::MetaListPaths &meta_item)
+{
+ for (auto &path : meta_item.get_paths ())
+ visit (path);
+}
+
+void
+PointerVisitor::visit (AST::MetaListNameValueStr &meta_item)
+{
+ for (auto &str : meta_item.get_values ())
+ visit (str);
+}
+
+void
+PointerVisitor::visit (AST::IdentifierPattern &pattern)
+{
+ if (pattern.has_subpattern ())
+ reseat (pattern.get_subpattern_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::RangePatternBoundPath &bound)
+{
+ visit (bound.get_path ());
+}
+
+void
+PointerVisitor::visit (AST::RangePatternBoundQualPath &bound)
+{
+ visit (bound.get_qualified_path ());
+}
+
+void
+PointerVisitor::visit (AST::RangePattern &pattern)
+{
+ // FIXME: So should this be reseat() instead? Can we have macro invocations as
+ // patterns in range patterns?
+ if (pattern.get_has_lower_bound ())
+ visit (pattern.get_lower_bound ());
+ if (pattern.get_has_upper_bound ())
+ visit (pattern.get_upper_bound ());
+}
+
+void
+PointerVisitor::visit (AST::ReferencePattern &pattern)
+{
+ reseat (pattern.get_referenced_pattern_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructPatternFieldTuplePat &field)
+{
+ visit_outer_attrs (field);
+ reseat (field.get_index_pattern_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructPatternFieldIdentPat &field)
+{
+ visit_outer_attrs (field);
+ reseat (field.get_ident_pattern_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructPatternFieldIdent &field)
+{
+ visit_outer_attrs (field);
+}
+
+void
+PointerVisitor::visit (AST::StructPatternElements &spe)
+{
+ for (auto &field : spe.get_struct_pattern_fields ())
+ visit (field);
+ for (auto &attribute : spe.get_etc_outer_attrs ())
+ visit (attribute);
+}
+
+void
+PointerVisitor::visit (AST::StructPattern &pattern)
+{
+ visit (pattern.get_path ());
+ visit (pattern.get_struct_pattern_elems ());
+}
+
+void
+PointerVisitor::visit (AST::TupleStructItemsNoRest &tuple_items)
+{
+ for (auto &pattern : tuple_items.get_patterns ())
+ reseat (pattern);
+}
+
+void
+PointerVisitor::visit (AST::TupleStructItemsHasRest &tuple_items)
+{
+ for (auto &lower : tuple_items.get_lower_patterns ())
+ reseat (lower);
+ for (auto &upper : tuple_items.get_upper_patterns ())
+ reseat (upper);
+}
+
+void
+PointerVisitor::visit (AST::TupleStructPattern &pattern)
+{
+ visit (pattern.get_path ());
+ visit (pattern.get_items ());
+}
+
+void
+PointerVisitor::visit (AST::TuplePatternItemsNoRest &tuple_items)
+{
+ for (auto &pattern : tuple_items.get_patterns ())
+ reseat (pattern);
+}
+
+void
+PointerVisitor::visit (AST::TuplePatternItemsHasRest &tuple_items)
+{
+ for (auto &lower : tuple_items.get_lower_patterns ())
+ reseat (lower);
+ for (auto &upper : tuple_items.get_upper_patterns ())
+ reseat (upper);
+}
+
+void
+PointerVisitor::visit (AST::TuplePattern &pattern)
+{
+ visit (pattern.get_items ());
+}
+
+void
+PointerVisitor::visit (AST::GroupedPattern &pattern)
+{
+ reseat (pattern.get_pattern_in_parens_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::SlicePatternItemsNoRest &items)
+{
+ for (auto &item : items.get_patterns ())
+ reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::SlicePatternItemsHasRest &items)
+{
+ for (auto &item : items.get_lower_patterns ())
+ reseat (item);
+ for (auto &item : items.get_upper_patterns ())
+ reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::SlicePattern &pattern)
+{
+ visit (pattern.get_items ());
+}
+
+void
+PointerVisitor::visit (AST::AltPattern &pattern)
+{
+ for (auto &alt : pattern.get_alts ())
+ reseat (alt);
+}
+
+void
+PointerVisitor::visit (AST::EmptyStmt &stmt)
+{}
+
+void
+PointerVisitor::visit (AST::LetStmt &stmt)
+{
+ visit_outer_attrs (stmt);
+ reseat (stmt.get_pattern_ptr ());
+ if (stmt.has_type ())
+ reseat (stmt.get_type_ptr ());
+ if (stmt.has_init_expr ())
+ reseat (stmt.get_init_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ExprStmt &stmt)
+{
+ reseat (stmt.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TraitBound &bound)
+{
+ for (auto &lifetime : bound.get_for_lifetimes ())
+ visit (lifetime);
+ visit (bound.get_type_path ());
+}
+
+void
+PointerVisitor::visit (AST::ImplTraitType &type)
+{
+ for (auto &bound : type.get_type_param_bounds ())
+ visit (bound);
+}
+
+void
+PointerVisitor::visit (AST::TraitObjectType &type)
+{
+ for (auto &bound : type.get_type_param_bounds ())
+ visit (bound);
+}
+
+void
+PointerVisitor::visit (AST::ParenthesisedType &type)
+{
+ reseat (type.get_type_in_parens ());
+}
+
+void
+PointerVisitor::visit (AST::ImplTraitTypeOneBound &type)
+{
+ // FIXME: Do we need to reseat here?
+ visit (type.get_trait_bound ());
+}
+
+void
+PointerVisitor::visit (AST::TraitObjectTypeOneBound &type)
+{
+ // FIXME: Do we need to reseat here?
+ visit (type.get_trait_bound ());
+}
+
+void
+PointerVisitor::visit (AST::TupleType &type)
+{
+ for (auto &elem : type.get_elems ())
+ reseat (elem);
+}
+
+void
+PointerVisitor::visit (AST::NeverType &type)
+{}
+
+void
+PointerVisitor::visit (AST::RawPointerType &type)
+{
+ reseat (type.get_type_pointed_to_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ReferenceType &type)
+{
+ visit (type.get_lifetime ());
+ reseat (type.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ArrayType &type)
+{
+ reseat (type.get_elem_type_ptr ());
+ visit (type.get_size_expr ());
+}
+
+void
+PointerVisitor::visit (AST::SliceType &type)
+{
+ reseat (type.get_elem_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::InferredType &type)
+{}
+
+void
+PointerVisitor::visit (AST::MaybeNamedParam &param)
+{
+ visit_outer_attrs (param);
+ reseat (param.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::BareFunctionType &type)
+{
+ for (auto &lifetime : type.get_for_lifetimes ())
+ visit (lifetime);
+ visit (type.get_function_qualifiers ());
+ for (auto &param : type.get_function_params ())
+ visit (param);
+ if (type.is_variadic ())
+ for (auto attr : type.get_variadic_attr ())
+ visit (attr);
+ if (type.has_return_type ())
+ reseat (type.get_return_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::FormatArgs &)
+{
+ // FIXME: Do we have anything to do? any subnodes to visit? Probably, right?
+}
+
+void
+PointerVisitor::visit (AST::OffsetOf &offset_of)
+{
+ reseat (offset_of.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::VariadicParam &param)
+{
+ if (param.has_pattern ())
+ reseat (param.get_pattern_ptr ());
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-pointer-visitor.h b/gcc/rust/ast/rust-ast-pointer-visitor.h
new file mode 100644
index 0000000..8c12b4e
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-pointer-visitor.h
@@ -0,0 +1,234 @@
+// 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_AST_POINTER_VISITOR_H
+#define RUST_AST_POINTER_VISITOR_H
+
+#include "rust-ast-visitor.h"
+#include "rust-ast.h"
+#include "rust-item.h"
+
+namespace Rust {
+namespace AST {
+
+/**
+ * Regular AST visitor which may reseat pointers when necessary.
+ */
+class PointerVisitor : public DefaultASTVisitor
+{
+public:
+ using DefaultASTVisitor::visit;
+
+ virtual void reseat (std::unique_ptr<AST::Expr> &ptr) { visit (ptr); }
+ virtual void reseat (std::unique_ptr<AST::BlockExpr> &ptr) { visit (ptr); }
+
+ virtual void reseat (std::unique_ptr<AST::Stmt> &ptr) { visit (ptr); }
+
+ virtual void reseat (std::unique_ptr<AST::Item> &ptr) { visit (ptr); }
+
+ virtual void reseat (std::unique_ptr<AST::AssociatedItem> &ptr)
+ {
+ visit (ptr);
+ }
+
+ virtual void reseat (std::unique_ptr<AST::ExternalItem> &ptr) { visit (ptr); }
+
+ virtual void reseat (std::unique_ptr<AST::Type> &ptr) { visit (ptr); }
+
+ virtual void reseat (std::unique_ptr<AST::TypeNoBounds> &ptr) { visit (ptr); }
+
+ virtual void reseat (std::unique_ptr<AST::Pattern> &ptr) { visit (ptr); }
+
+ void visit (AST::Crate &crate) override;
+ void visit (AST::AttrInputMetaItemContainer &input) override;
+ void visit (AST::IdentifierExpr &ident_expr) override;
+ void visit (AST::LifetimeParam &lifetime_param) override;
+ void visit (AST::ConstGenericParam &const_param) override;
+ void visit (AST::PathInExpression &path) override;
+ void visit (GenericArgsBinding &binding) override;
+ void visit (AST::TypePathSegmentGeneric &segment) override;
+ void visit (AST::TypePathFunction &tpf) override;
+ void visit (AST::TypePathSegmentFunction &segment) override;
+ void visit (AST::GenericArgs &args) override;
+ void visit (AST::PathExprSegment &segment) override;
+ void visit (AST::TypePath &path) override;
+ void visit (AST::QualifiedPathInExpression &path) override;
+ void visit (AST::QualifiedPathType &path) override;
+ void visit (AST::QualifiedPathInType &path) override;
+ void visit (AST::LiteralExpr &expr) override;
+ void visit (AST::AttrInputLiteral &attr_input) override;
+ void visit (AST::AttrInputMacro &attr_input) override;
+ void visit (AST::MetaItemLitExpr &meta_item) override;
+ void visit (AST::SimplePath &path) 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;
+ void visit (AST::NegationExpr &expr) override;
+ void visit (AST::ArithmeticOrLogicalExpr &expr) override;
+ void visit (AST::ComparisonExpr &expr) override;
+ void visit (AST::LazyBooleanExpr &expr) override;
+ void visit (AST::TypeCastExpr &expr) override;
+ void visit (AST::AssignmentExpr &expr) override;
+ void visit (AST::CompoundAssignmentExpr &expr) override;
+ void visit (AST::GroupedExpr &expr) override;
+ void visit (AST::ArrayElemsValues &elems) override;
+ void visit (AST::ArrayElemsCopied &elems) override;
+ void visit (AST::ArrayExpr &expr) override;
+ void visit (AST::ArrayIndexExpr &expr) override;
+ void visit (AST::TupleExpr &expr) override;
+ void visit (AST::TupleIndexExpr &expr) override;
+ void visit (AST::StructExprStruct &expr) override;
+ void visit (AST::StructExprFieldIdentifier &field) override;
+ void visit (AST::StructExprFieldIdentifierValue &field) override;
+ void visit (AST::StructExprFieldIndexValue &field) override;
+ void visit (AST::StructBase &base) override;
+ void visit (AST::StructExprStructFields &expr) override;
+ void visit (AST::StructExprStructBase &expr) override;
+ void visit (AST::CallExpr &expr) override;
+ void visit (AST::MethodCallExpr &expr) override;
+ void visit (AST::FieldAccessExpr &expr) override;
+ void visit (AST::ClosureExprInner &expr) override;
+ void visit (AST::BlockExpr &expr) override;
+ void visit (AST::ConstBlock &expr) override;
+ void visit (AST::AnonConst &expr) override;
+ void visit (AST::ClosureExprInnerTyped &expr) override;
+ void visit (AST::ClosureParam &param) override;
+ void visit (AST::ContinueExpr &expr) override;
+ void visit (AST::BreakExpr &expr) override;
+ void visit (AST::RangeFromToExpr &expr) override;
+ void visit (AST::RangeFromExpr &expr) override;
+ void visit (AST::RangeToExpr &expr) override;
+ void visit (AST::RangeFullExpr &expr) override;
+ void visit (AST::RangeFromToInclExpr &expr) override;
+ void visit (AST::RangeToInclExpr &expr) override;
+ void visit (AST::ReturnExpr &expr) override;
+ void visit (AST::TryExpr &expr) override;
+ void visit (AST::BoxExpr &expr) override;
+ void visit (AST::UnsafeBlockExpr &expr) override;
+ void visit (AST::LoopLabel &label) override;
+ void visit (AST::LoopExpr &expr) override;
+ void visit (AST::WhileLoopExpr &expr) override;
+ void visit (AST::WhileLetLoopExpr &expr) override;
+ void visit (AST::ForLoopExpr &expr) override;
+ void visit (AST::IfExpr &expr) override;
+ void visit (AST::IfExprConseqElse &expr) override;
+ void visit (AST::IfLetExpr &expr) override;
+ void visit (AST::IfLetExprConseqElse &expr) override;
+ void visit (AST::MatchArm &arm) override;
+ void visit (AST::MatchCase &arm) override;
+ void visit (AST::MatchExpr &expr) override;
+ void visit (AST::AwaitExpr &expr) override;
+ void visit (AST::AsyncBlockExpr &expr) override;
+ void visit (AST::InlineAsm &expr) override;
+ void visit (AST::LlvmInlineAsm &expr) override;
+ void visit (AST::TypeParam &param) override;
+ void visit (AST::LifetimeWhereClauseItem &item) override;
+ void visit (AST::TypeBoundWhereClauseItem &item) override;
+ void visit (AST::Visibility &vis) override;
+ void visit (AST::WhereClause &where) override;
+ void visit (AST::FunctionParam &param) override;
+ void visit (AST::SelfParam &param) override;
+ void visit (AST::Module &module) override;
+ void visit (AST::ExternCrate &crate) override;
+ void visit (AST::UseTreeGlob &use_tree) override;
+ void visit (AST::UseTreeList &use_tree) override;
+ void visit (AST::UseTreeRebind &use_tree) override;
+ void visit (AST::UseDeclaration &use_decl) override;
+ void visit_function_params (AST::Function &function) override;
+ void visit (AST::Function &function) override;
+ void visit (AST::TypeAlias &type_alias) override;
+ void visit (AST::StructField &field) override;
+ void visit (AST::StructStruct &struct_item) override;
+ void visit (AST::TupleField &field) override;
+ void visit (AST::TupleStruct &tuple_struct) override;
+ void visit (AST::EnumItem &item) override;
+ void visit (AST::EnumItemTuple &item) override;
+ void visit (AST::EnumItemStruct &item) override;
+ void visit (AST::EnumItemDiscriminant &item) override;
+ void visit (AST::Enum &enum_item) override;
+ void visit (AST::Union &union_item) override;
+ void visit (AST::ConstantItem &const_item) override;
+ void visit (AST::StaticItem &static_item) override;
+ void visit (AST::TraitItemType &item) override;
+ void visit (AST::Trait &trait) override;
+ void visit (AST::InherentImpl &impl) override;
+ void visit (AST::TraitImpl &impl) override;
+ void visit (AST::ExternalTypeItem &item) override;
+ void visit (AST::ExternalStaticItem &item) override;
+ void visit (AST::ExternBlock &block) override;
+ void visit (AST::MacroMatchFragment &match) override;
+ void visit (AST::MacroMatchRepetition &match) override;
+ void visit (AST::MacroMatcher &matcher) override;
+ void visit (AST::MacroTranscriber &transcriber) override;
+ void visit (AST::MacroRule &rule) override;
+ void visit (AST::MacroRulesDefinition &rules_def) override;
+ void visit (AST::MacroInvocData &data) override;
+ void visit (AST::MacroInvocation &macro_invoc) override;
+ void visit (AST::MetaItemPath &meta_item) override;
+ void visit (AST::MetaItemSeq &meta_item) override;
+ void visit (AST::MetaListPaths &meta_item) override;
+ void visit (AST::MetaListNameValueStr &meta_item) override;
+ void visit (AST::IdentifierPattern &pattern) override;
+ void visit (AST::RangePatternBoundPath &bound) override;
+ void visit (AST::RangePatternBoundQualPath &bound) override;
+ void visit (AST::RangePattern &pattern) override;
+ void visit (AST::ReferencePattern &pattern) override;
+ void visit (AST::StructPatternFieldTuplePat &field) override;
+ void visit (AST::StructPatternFieldIdentPat &field) override;
+ void visit (AST::StructPatternFieldIdent &field) override;
+ void visit (AST::StructPatternElements &spe) override;
+ void visit (AST::StructPattern &pattern) override;
+ void visit (AST::TupleStructItemsNoRest &tuple_items) override;
+ void visit (AST::TupleStructItemsHasRest &tuple_items) override;
+ void visit (AST::TupleStructPattern &pattern) override;
+ void visit (AST::TuplePatternItemsNoRest &tuple_items) override;
+ void visit (AST::TuplePatternItemsHasRest &tuple_items) override;
+ void visit (AST::TuplePattern &pattern) 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;
+ void visit (AST::EmptyStmt &stmt) override;
+ void visit (AST::LetStmt &stmt) override;
+ void visit (AST::ExprStmt &stmt) override;
+ void visit (AST::TraitBound &bound) override;
+ void visit (AST::ImplTraitType &type) override;
+ void visit (AST::TraitObjectType &type) override;
+ void visit (AST::ParenthesisedType &type) override;
+ void visit (AST::ImplTraitTypeOneBound &type) override;
+ void visit (AST::TraitObjectTypeOneBound &type) override;
+ void visit (AST::TupleType &type) override;
+ void visit (AST::NeverType &type) override;
+ void visit (AST::RawPointerType &type) override;
+ void visit (AST::ReferenceType &type) override;
+ void visit (AST::ArrayType &type) override;
+ void visit (AST::SliceType &type) override;
+ void visit (AST::InferredType &type) override;
+ void visit (AST::MaybeNamedParam &param) override;
+ void visit (AST::BareFunctionType &type) override;
+ void visit (AST::FormatArgs &) override;
+ void visit (AST::OffsetOf &offset_of) override;
+ void visit (AST::VariadicParam &param) override;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index ba5f87b..afdd2b1 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"
@@ -82,7 +83,7 @@ DefaultASTVisitor::visit (AST::ConstGenericParam &const_param)
if (const_param.has_type ())
visit (const_param.get_type ());
if (const_param.has_default_value ())
- visit (const_param.get_default_value ());
+ visit (const_param.get_default_value_unchecked ());
}
void
@@ -108,7 +109,8 @@ DefaultASTVisitor::visit (GenericArgsBinding &binding)
void
DefaultASTVisitor::visit (AST::TypePathSegmentGeneric &segment)
{
- visit (segment.get_generic_args ());
+ if (segment.has_generic_args ())
+ visit (segment.get_generic_args ());
}
void
@@ -222,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
@@ -246,6 +248,7 @@ void
DefaultASTVisitor::visit (AST::ErrorPropagationExpr &expr)
{
visit_outer_attrs (expr);
+ visit (expr.get_propagating_expr ());
}
void
@@ -448,20 +451,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
@@ -477,7 +498,8 @@ void
DefaultASTVisitor::visit (AST::ContinueExpr &expr)
{
visit_outer_attrs (expr);
- visit (expr.get_label ());
+ if (expr.has_label ())
+ visit (expr.get_label_unchecked ());
}
void
@@ -485,7 +507,7 @@ DefaultASTVisitor::visit (AST::BreakExpr &expr)
{
visit_outer_attrs (expr);
if (expr.has_label ())
- visit (expr.get_label ());
+ visit (expr.get_label_unchecked ());
if (expr.has_break_expr ())
visit (expr.get_break_expr ());
@@ -536,6 +558,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);
@@ -559,7 +588,8 @@ void
DefaultASTVisitor::visit (AST::LoopExpr &expr)
{
visit_outer_attrs (expr);
- visit (expr.get_loop_label ());
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
visit (expr.get_loop_block ());
}
@@ -567,8 +597,9 @@ void
DefaultASTVisitor::visit (AST::WhileLoopExpr &expr)
{
visit_outer_attrs (expr);
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
visit (expr.get_predicate_expr ());
- visit (expr.get_loop_label ());
visit (expr.get_loop_block ());
}
@@ -578,8 +609,11 @@ DefaultASTVisitor::visit (AST::WhileLetLoopExpr &expr)
visit_outer_attrs (expr);
for (auto &pattern : expr.get_patterns ())
visit (pattern);
+
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
+
visit (expr.get_scrutinee_expr ());
- visit (expr.get_loop_label ());
visit (expr.get_loop_block ());
}
@@ -589,7 +623,8 @@ DefaultASTVisitor::visit (AST::ForLoopExpr &expr)
visit_outer_attrs (expr);
visit (expr.get_pattern ());
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 ());
}
@@ -675,33 +710,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;
}
@@ -710,6 +752,16 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr)
}
void
+DefaultASTVisitor::visit (AST::LlvmInlineAsm &expr)
+{
+ for (auto &output : expr.get_outputs ())
+ visit (output.expr);
+
+ for (auto &input : expr.get_inputs ())
+ visit (input.expr);
+}
+
+void
DefaultASTVisitor::visit (AST::TypeParam &param)
{
visit_outer_attrs (param);
@@ -740,7 +792,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
@@ -813,10 +866,18 @@ DefaultASTVisitor::visit (AST::UseTreeRebind &use_tree)
void
DefaultASTVisitor::visit (AST::UseDeclaration &use_decl)
{
+ visit (use_decl.get_visibility ());
visit (use_decl.get_tree ());
}
void
+DefaultASTVisitor::visit_function_params (AST::Function &function)
+{
+ for (auto &param : function.get_function_params ())
+ visit (param);
+}
+
+void
DefaultASTVisitor::visit (AST::Function &function)
{
visit_outer_attrs (function);
@@ -824,10 +885,9 @@ DefaultASTVisitor::visit (AST::Function &function)
visit (function.get_qualifiers ());
for (auto &generic : function.get_generic_params ())
visit (generic);
- if (function.has_self_param ())
- visit (function.get_self_param ());
- for (auto &param : function.get_function_params ())
- visit (param);
+
+ visit_function_params (function);
+
if (function.has_return_type ())
visit (function.get_return_type ());
if (function.has_where_clause ())
@@ -900,7 +960,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);
}
@@ -908,7 +968,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);
}
@@ -916,7 +976,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 ());
}
@@ -966,15 +1026,6 @@ DefaultASTVisitor::visit (AST::StaticItem &static_item)
}
void
-DefaultASTVisitor::visit (AST::TraitItemConst &item)
-{
- visit_outer_attrs (item);
- visit (item.get_type ());
- if (item.has_expr ())
- visit (item.get_expr ());
-}
-
-void
DefaultASTVisitor::visit (AST::TraitItemType &item)
{
visit_outer_attrs (item);
@@ -1157,8 +1208,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
@@ -1237,14 +1288,14 @@ DefaultASTVisitor::visit (AST::StructPattern &pattern)
}
void
-DefaultASTVisitor::visit (AST::TupleStructItemsNoRange &tuple_items)
+DefaultASTVisitor::visit (AST::TupleStructItemsNoRest &tuple_items)
{
for (auto &pattern : tuple_items.get_patterns ())
visit (pattern);
}
void
-DefaultASTVisitor::visit (AST::TupleStructItemsRange &tuple_items)
+DefaultASTVisitor::visit (AST::TupleStructItemsHasRest &tuple_items)
{
for (auto &lower : tuple_items.get_lower_patterns ())
visit (lower);
@@ -1260,14 +1311,14 @@ DefaultASTVisitor::visit (AST::TupleStructPattern &pattern)
}
void
-DefaultASTVisitor::visit (AST::TuplePatternItemsMultiple &tuple_items)
+DefaultASTVisitor::visit (AST::TuplePatternItemsNoRest &tuple_items)
{
for (auto &pattern : tuple_items.get_patterns ())
visit (pattern);
}
void
-DefaultASTVisitor::visit (AST::TuplePatternItemsRanged &tuple_items)
+DefaultASTVisitor::visit (AST::TuplePatternItemsHasRest &tuple_items)
{
for (auto &lower : tuple_items.get_lower_patterns ())
visit (lower);
@@ -1288,13 +1339,28 @@ DefaultASTVisitor::visit (AST::GroupedPattern &pattern)
}
void
-DefaultASTVisitor::visit (AST::SlicePattern &pattern)
+DefaultASTVisitor::visit (AST::SlicePatternItemsNoRest &items)
{
- for (auto &item : pattern.get_items ())
+ for (auto &item : items.get_patterns ())
visit (item);
}
void
+DefaultASTVisitor::visit (AST::SlicePatternItemsHasRest &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 ())
@@ -1432,6 +1498,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 51661df..a7a2ac4 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;
@@ -131,6 +134,7 @@ public:
virtual void visit (AwaitExpr &expr) = 0;
virtual void visit (AsyncBlockExpr &expr) = 0;
virtual void visit (InlineAsm &expr) = 0;
+ virtual void visit (LlvmInlineAsm &expr) = 0;
// rust-item.h
virtual void visit (TypeParam &param) = 0;
@@ -160,7 +164,6 @@ public:
virtual void visit (Union &union_item) = 0;
virtual void visit (ConstantItem &const_item) = 0;
virtual void visit (StaticItem &static_item) = 0;
- virtual void visit (TraitItemConst &item) = 0;
virtual void visit (TraitItemType &item) = 0;
virtual void visit (Trait &trait) = 0;
virtual void visit (InherentImpl &impl) = 0;
@@ -200,14 +203,16 @@ public:
virtual void visit (StructPatternFieldIdent &field) = 0;
virtual void visit (StructPattern &pattern) = 0;
// virtual void visit(TupleStructItems& tuple_items) = 0;
- virtual void visit (TupleStructItemsNoRange &tuple_items) = 0;
- virtual void visit (TupleStructItemsRange &tuple_items) = 0;
+ virtual void visit (TupleStructItemsNoRest &tuple_items) = 0;
+ virtual void visit (TupleStructItemsHasRest &tuple_items) = 0;
virtual void visit (TupleStructPattern &pattern) = 0;
// virtual void visit(TuplePatternItems& tuple_items) = 0;
- virtual void visit (TuplePatternItemsMultiple &tuple_items) = 0;
- virtual void visit (TuplePatternItemsRanged &tuple_items) = 0;
+ virtual void visit (TuplePatternItemsNoRest &tuple_items) = 0;
+ virtual void visit (TuplePatternItemsHasRest &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;
@@ -234,6 +239,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
};
@@ -241,6 +247,8 @@ public:
class DefaultASTVisitor : public ASTVisitor
{
public:
+ virtual void visit_function_params (AST::Function &function);
+
virtual void visit (AST::Crate &crate);
virtual void visit (AST::Token &tok) override;
@@ -261,7 +269,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;
@@ -290,6 +298,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;
@@ -300,6 +310,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;
@@ -314,6 +325,7 @@ public:
virtual void visit (AST::AwaitExpr &expr) override;
virtual void visit (AST::AsyncBlockExpr &expr) override;
virtual void visit (InlineAsm &expr) override;
+ virtual void visit (LlvmInlineAsm &expr) override;
virtual void visit (AST::TypeParam &param) override;
virtual void visit (AST::LifetimeWhereClauseItem &item) override;
@@ -336,7 +348,6 @@ public:
virtual void visit (AST::Union &union_item) override;
virtual void visit (AST::ConstantItem &const_item) override;
virtual void visit (AST::StaticItem &static_item) override;
- virtual void visit (AST::TraitItemConst &item) override;
virtual void visit (AST::TraitItemType &item) override;
virtual void visit (AST::Trait &trait) override;
virtual void visit (AST::InherentImpl &impl) override;
@@ -368,13 +379,15 @@ public:
virtual void visit (AST::StructPatternFieldIdentPat &field) override;
virtual void visit (AST::StructPatternFieldIdent &field) override;
virtual void visit (AST::StructPattern &pattern) override;
- virtual void visit (AST::TupleStructItemsNoRange &tuple_items) override;
- virtual void visit (AST::TupleStructItemsRange &tuple_items) override;
+ virtual void visit (AST::TupleStructItemsNoRest &tuple_items) override;
+ virtual void visit (AST::TupleStructItemsHasRest &tuple_items) override;
virtual void visit (AST::TupleStructPattern &pattern) override;
- virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) override;
- virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override;
+ virtual void visit (AST::TuplePatternItemsNoRest &tuple_items) override;
+ virtual void visit (AST::TuplePatternItemsHasRest &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;
@@ -398,6 +411,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 ab82303..851f7ea 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
@@ -47,29 +48,33 @@ SingleASTNode::SingleASTNode (SingleASTNode const &other)
kind = other.kind;
switch (kind)
{
- case EXPRESSION:
+ case Kind::Expr:
expr = other.expr->clone_expr ();
break;
- case ITEM:
+ case Kind::Item:
item = other.item->clone_item ();
break;
- case STMT:
+ case Kind::Stmt:
stmt = other.stmt->clone_stmt ();
break;
- case EXTERN:
+ case Kind::Extern:
external_item = other.external_item->clone_external_item ();
break;
- case ASSOC_ITEM:
+ case Kind::Assoc:
assoc_item = other.assoc_item->clone_associated_item ();
break;
- case TYPE:
+ case Kind::Type:
type = other.type->clone_type ();
break;
+
+ case Kind::Pattern:
+ pattern = other.pattern->clone_pattern ();
+ break;
}
}
@@ -79,29 +84,33 @@ SingleASTNode::operator= (SingleASTNode const &other)
kind = other.kind;
switch (kind)
{
- case EXPRESSION:
+ case Kind::Expr:
expr = other.expr->clone_expr ();
break;
- case ITEM:
+ case Kind::Item:
item = other.item->clone_item ();
break;
- case STMT:
+ case Kind::Stmt:
stmt = other.stmt->clone_stmt ();
break;
- case EXTERN:
+ case Kind::Extern:
external_item = other.external_item->clone_external_item ();
break;
- case ASSOC_ITEM:
+ case Kind::Assoc:
assoc_item = other.assoc_item->clone_associated_item ();
break;
- case TYPE:
+ case Kind::Type:
type = other.type->clone_type ();
break;
+
+ case Kind::Pattern:
+ pattern = other.pattern->clone_pattern ();
+ break;
}
return *this;
}
@@ -111,29 +120,33 @@ SingleASTNode::accept_vis (ASTVisitor &vis)
{
switch (kind)
{
- case EXPRESSION:
+ case Kind::Expr:
expr->accept_vis (vis);
break;
- case ITEM:
+ case Kind::Item:
item->accept_vis (vis);
break;
- case STMT:
+ case Kind::Stmt:
stmt->accept_vis (vis);
break;
- case EXTERN:
+ case Kind::Extern:
external_item->accept_vis (vis);
break;
- case ASSOC_ITEM:
+ case Kind::Assoc:
assoc_item->accept_vis (vis);
break;
- case TYPE:
+ case Kind::Type:
type->accept_vis (vis);
break;
+
+ case Kind::Pattern:
+ pattern->accept_vis (vis);
+ break;
}
}
@@ -142,18 +155,20 @@ SingleASTNode::is_error ()
{
switch (kind)
{
- case EXPRESSION:
+ case Kind::Expr:
return expr == nullptr;
- case ITEM:
+ case Kind::Item:
return item == nullptr;
- case STMT:
+ case Kind::Stmt:
return stmt == nullptr;
- case EXTERN:
+ case Kind::Extern:
return external_item == nullptr;
- case ASSOC_ITEM:
+ case Kind::Assoc:
return assoc_item == nullptr;
- case TYPE:
+ case Kind::Type:
return type == nullptr;
+ case Kind::Pattern:
+ return pattern == nullptr;
}
rust_unreachable ();
@@ -165,18 +180,20 @@ SingleASTNode::as_string () const
{
switch (kind)
{
- case EXPRESSION:
+ case Kind::Expr:
return "Expr: " + expr->as_string ();
- case ITEM:
+ case Kind::Item:
return "Item: " + item->as_string ();
- case STMT:
+ case Kind::Stmt:
return "Stmt: " + stmt->as_string ();
- case EXTERN:
+ case Kind::Extern:
return "External Item: " + external_item->as_string ();
- case ASSOC_ITEM:
+ case Kind::Assoc:
return "Associated Item: " + assoc_item->as_string ();
- case TYPE:
+ case Kind::Type:
return "Type: " + type->as_string ();
+ case Kind::Pattern:
+ return "Pattern: " + pattern->as_string ();
}
rust_unreachable ();
@@ -231,7 +248,7 @@ Attribute::as_string () const
bool
Attribute::is_derive () const
{
- return has_attr_input () && get_path () == "derive";
+ return has_attr_input () && get_path () == Values::Attributes::DERIVE_ATTR;
}
/**
@@ -249,27 +266,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 +304,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:
@@ -384,7 +405,7 @@ DelimTokenTree::as_string () const
std::string
Token::as_string () const
{
- if (tok_ref->has_str ())
+ if (tok_ref->should_have_str ())
{
std::string str = tok_ref->get_str ();
@@ -620,7 +641,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)
@@ -631,14 +652,8 @@ ConstantItem::as_string () const
}
str += "\n Type: " + type->as_string ();
- // DEBUG: null pointer check
- if (const_expr == nullptr)
- {
- rust_debug ("something really terrible has gone wrong - null "
- "pointer expr in const item.");
- return "NULL_POINTER_MARK";
- }
- str += "\n Expression: " + const_expr->as_string ();
+ if (has_expr ())
+ str += "\n Expression: " + const_expr->as_string ();
return str + "\n";
}
@@ -782,7 +797,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 +821,8 @@ UseTreeList::as_string () const
case GLOBAL:
path_str = "::{";
break;
- case PATH_PREFIXED: {
+ case PATH_PREFIXED:
+ {
path_str = path.as_string () + "::{";
break;
}
@@ -1068,7 +1085,7 @@ Function::Function (Function const &other)
: VisItem (other), ExternalItem (other.get_node_id ()),
qualifiers (other.qualifiers), function_name (other.function_name),
where_clause (other.where_clause), locus (other.locus),
- is_default (other.is_default),
+ has_default (other.has_default),
is_external_function (other.is_external_function)
{
// guard to prevent null dereference (always required)
@@ -1100,7 +1117,7 @@ Function::operator= (Function const &other)
// visibility = other.visibility->clone_visibility();
// outer_attrs = other.outer_attrs;
locus = other.locus;
- is_default = other.is_default;
+ has_default = other.has_default;
is_external_function = other.is_external_function;
// guard to prevent null dereference (always required)
@@ -1272,6 +1289,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 +1655,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 ();
@@ -1631,7 +1680,7 @@ ContinueExpr::as_string () const
std::string str ("continue ");
if (has_label ())
- str += label.as_string ();
+ str += get_label_unchecked ().as_string ();
return str;
}
@@ -2095,7 +2144,7 @@ WhileLoopExpr::as_string () const
if (!has_loop_label ())
str += "none";
else
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
str += "\n Conditional expr: " + condition->as_string ();
@@ -2115,7 +2164,7 @@ WhileLetLoopExpr::as_string () const
if (!has_loop_label ())
str += "none";
else
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
str += "\n Match arm patterns: ";
if (match_arm_patterns.empty ())
@@ -2146,7 +2195,7 @@ LoopExpr::as_string () const
if (!has_loop_label ())
str += "none";
else
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
str += "\n Loop block: " + loop_block->as_string ();
@@ -2183,7 +2232,7 @@ BreakExpr::as_string () const
std::string str ("break ");
if (has_label ())
- str += label.as_string () + " ";
+ str += get_label_unchecked ().as_string () + " ";
if (has_break_expr ())
str += break_expr->as_string ();
@@ -2485,9 +2534,6 @@ MacroMatchRepetition::as_string () const
std::string
Lifetime::as_string () const
{
- if (is_error ())
- return "error lifetime";
-
switch (lifetime_type)
{
case NAMED:
@@ -2545,7 +2591,7 @@ ForLoopExpr::as_string () const
if (!has_loop_label ())
str += "none";
else
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
str += "\n Pattern: " + pattern->as_string ();
@@ -2612,7 +2658,7 @@ ReferenceType::as_string () const
std::string str ("&");
if (has_lifetime ())
- str += lifetime.as_string () + " ";
+ str += get_lifetime ().as_string () + " ";
if (has_mut)
str += "mut ";
@@ -2717,7 +2763,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
@@ -2739,7 +2785,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
@@ -2998,26 +3044,24 @@ ExternalStaticItem::as_string () const
}
std::string
-TraitItemConst::as_string () const
-{
- // TODO: rewrite to work with non-linearisable exprs
- std::string str = append_attributes (outer_attrs, OUTER);
-
- str += "\nconst " + name.as_string () + " : " + type->as_string ();
-
- if (has_expression ())
- str += " = " + expr->as_string ();
-
- return str;
-}
-
-std::string
TraitItemType::as_string () const
{
std::string str = append_attributes (outer_attrs, OUTER);
str += "\ntype " + name.as_string ();
+ if (has_generics ())
+ {
+ str += "<";
+ for (size_t i = 0; i < generic_params.size (); i++)
+ {
+ if (i > 0)
+ str += ", ";
+ str += generic_params[i]->as_string ();
+ }
+ str += ">";
+ }
+
str += "\n Type param bounds: ";
if (!has_type_param_bounds ())
{
@@ -3070,7 +3114,7 @@ SelfParam::as_string () const
else if (has_lifetime ())
{
// ref and lifetime
- std::string str = "&" + lifetime.as_string () + " ";
+ std::string str = "&" + get_lifetime ().as_string () + " ";
if (is_mut)
str += "mut ";
@@ -3331,7 +3375,13 @@ void
Module::process_file_path ()
{
rust_assert (kind == Module::ModuleKind::UNLOADED);
- rust_assert (module_file.empty ());
+
+ if (!module_file.empty ())
+ {
+ rust_error_at (locus, "error handling module file for %qs",
+ module_name.as_string ().c_str ());
+ return;
+ }
// This corresponds to the path of the file 'including' the module. So the
// file that contains the 'mod <file>;' directive
@@ -3480,13 +3530,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:
@@ -3507,48 +3568,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
@@ -3558,16 +3617,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 ();
}
@@ -3646,49 +3705,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;
}
}
@@ -3698,41 +3754,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;
}
@@ -3755,130 +3811,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
@@ -3901,6 +3846,9 @@ MetaItemLitExpr::check_cfg_predicate (const Session &) const
{
/* as far as I can tell, a literal expr can never be a valid cfg body, so
* false */
+ rust_error_at (this->get_locus (), "'%s' predicate key cannot be a literal",
+ this->as_string ().c_str ());
+
return false;
}
@@ -4087,10 +4035,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>>
@@ -4178,8 +4128,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)));
}
@@ -4197,6 +4149,12 @@ AttrInputMetaItemContainer::separate_cfg_attrs () const
for (auto it = items.begin () + 1; it != items.end (); ++it)
{
+ if ((*it)->get_kind () == MetaItemInner::Kind::MetaItem
+ && static_cast<MetaItem &> (**it).get_item_kind ()
+ == MetaItem::ItemKind::PathExpr
+ && !static_cast<MetaItemPathExpr &> (**it).get_expr ().is_literal ())
+ continue;
+
Attribute attr = (*it)->to_attribute ();
if (attr.is_empty ())
{
@@ -4214,18 +4172,13 @@ AttrInputMetaItemContainer::separate_cfg_attrs () const
bool
Attribute::check_cfg_predicate (const Session &session) const
{
+ auto string_path = path.as_string ();
/* assume that cfg predicate actually can exist, i.e. attribute has cfg or
* cfg_attr path */
- if (!has_attr_input ()
- || (path.as_string () != Values::Attributes::CFG
- && path.as_string () != Values::Attributes::CFG_ATTR))
+ if (!has_attr_input ())
{
- // DEBUG message
- rust_debug (
- "tried to check cfg predicate on attr that either has no input "
- "or invalid path. attr: '%s'",
- as_string ().c_str ());
-
+ rust_error_at (path.get_locus (), "%qs is not followed by parentheses",
+ string_path.c_str ());
return false;
}
@@ -4234,6 +4187,20 @@ Attribute::check_cfg_predicate (const Session &session) const
return false;
auto &meta_item = static_cast<AttrInputMetaItemContainer &> (*attr_input);
+ if (meta_item.get_items ().empty ())
+ {
+ rust_error_at (path.get_locus (), "malformed %<%s%> attribute input",
+ string_path.c_str ());
+ return false;
+ }
+
+ if (string_path == Values::Attributes::CFG
+ && meta_item.get_items ().size () != 1)
+ {
+ rust_error_at (path.get_locus (), "multiple %qs predicates are specified",
+ path.as_string ().c_str ());
+ return false;
+ }
return meta_item.get_items ().front ()->check_cfg_predicate (session);
}
@@ -4282,11 +4249,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
@@ -4348,7 +4316,7 @@ MetaItemLitExpr::accept_vis (ASTVisitor &vis)
}
void
-MetaItemPathLit::accept_vis (ASTVisitor &vis)
+MetaItemPathExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
@@ -4516,6 +4484,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);
@@ -4576,6 +4556,12 @@ ReturnExpr::accept_vis (ASTVisitor &vis)
}
void
+TryExpr::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
UnsafeBlockExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
@@ -4654,6 +4640,12 @@ InlineAsm::accept_vis (ASTVisitor &vis)
}
void
+LlvmInlineAsm::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
TypeParam::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
@@ -4780,12 +4772,6 @@ StaticItem::accept_vis (ASTVisitor &vis)
}
void
-TraitItemConst::accept_vis (ASTVisitor &vis)
-{
- vis.visit (*this);
-}
-
-void
TraitItemType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
@@ -5007,6 +4993,12 @@ FormatArgs::accept_vis (ASTVisitor &vis)
vis.visit (*this);
}
+void
+OffsetOf::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
std::string
FormatArgs::as_string () const
{
@@ -5014,6 +5006,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
{
@@ -5044,7 +5042,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 ();
}
@@ -5057,6 +5056,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 4d7d23d..8610ade 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -57,13 +57,19 @@ public:
bool empty () const { return ident.empty (); }
+ bool operator== (const Identifier &other) const
+ {
+ 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
@@ -77,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
{
@@ -146,17 +184,6 @@ class Token : public TokenTree, public MacroMatch
{
// A token is a kind of token tree (except delimiter tokens)
// A token is a kind of MacroMatch (except $ and delimiter tokens)
-#if 0
- // TODO: improve member variables - current ones are the same as lexer token
- // Token kind.
- TokenId token_id;
- // Token location.
- location_t locus;
- // Associated text (if any) of token.
- std::string str;
- // Token type hint (if any).
- PrimitiveCoreType type_hint;
-#endif
const_TokenPtr tok_ref;
@@ -171,53 +198,7 @@ public:
return std::unique_ptr<Token> (clone_token_impl ());
}
-#if 0
- /* constructor from general text - avoid using if lexer const_TokenPtr is
- * available */
- Token (TokenId token_id, location_t locus, std::string str,
- PrimitiveCoreType type_hint)
- : token_id (token_id), locus (locus), str (std::move (str)),
- type_hint (type_hint)
- {}
-#endif
- // not doable with new implementation - will have to make a const_TokenPtr
-
// Constructor from lexer const_TokenPtr
-#if 0
- /* TODO: find workaround for std::string being nullptr - probably have to
- * introduce new method in lexer Token, or maybe make conversion method
- * there */
- Token (const_TokenPtr lexer_token_ptr)
- : token_id (lexer_token_ptr->get_id ()),
- locus (lexer_token_ptr->get_locus ()), str (""),
- type_hint (lexer_token_ptr->get_type_hint ())
- {
- // FIXME: change to "should have str" later?
- if (lexer_token_ptr->has_str ())
- {
- str = lexer_token_ptr->get_str ();
-
- // DEBUG
- rust_debug ("ast token created with str '%s'", str.c_str ());
- }
- else
- {
- // FIXME: is this returning correct thing?
- str = lexer_token_ptr->get_token_description ();
-
- // DEBUG
- rust_debug ("ast token created with string '%s'", str.c_str ());
- }
-
- // DEBUG
- if (lexer_token_ptr->should_have_str () && !lexer_token_ptr->has_str ())
- {
- rust_debug (
- "BAD: for token '%s', should have string but does not!",
- lexer_token_ptr->get_token_description ());
- }
- }
-#endif
Token (const_TokenPtr lexer_tok_ptr) : tok_ref (std::move (lexer_tok_ptr)) {}
bool is_string_lit () const
@@ -245,6 +226,7 @@ public:
std::vector<std::unique_ptr<Token>> to_token_stream () const override;
TokenId get_id () const { return tok_ref->get_id (); }
+ bool should_have_str () const { return tok_ref->should_have_str (); }
const std::string &get_str () const { return tok_ref->get_str (); }
location_t get_locus () const { return tok_ref->get_locus (); }
@@ -398,15 +380,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 ()),
@@ -657,6 +639,9 @@ public:
// Returns whether the attribute is considered an "empty" attribute.
bool is_empty () const { return attr_input == nullptr && path.is_empty (); }
+ // Returns whether the attribute has no input
+ bool empty_input () const { return !attr_input; }
+
location_t get_locus () const { return locus; }
AttrInput &get_attr_input () const { return *attr_input; }
@@ -1015,6 +1000,7 @@ public:
}
DelimType get_delim_type () const { return delim_type; }
+ location_t get_locus () const { return locus; }
};
/* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr
@@ -1030,7 +1016,7 @@ public:
Path,
Word,
NameValueStr,
- PathLit,
+ PathExpr,
Seq,
ListPaths,
ListNameValueStr,
@@ -1048,7 +1034,7 @@ public:
class MetaItemLitExpr;
// Forward decl - defined in rust-expr.h
-class MetaItemPathLit;
+class MetaItemPathExpr;
// Forward decl - defined in rust-macro.h
class MetaItemPath;
@@ -1094,7 +1080,9 @@ public:
virtual void mark_for_strip () = 0;
virtual bool is_marked_for_strip () const = 0;
- NodeId get_node_id () const { return node_id; }
+
+ // TODO: put this in a virtual base class?
+ virtual NodeId get_node_id () const { return node_id; }
virtual Kind get_stmt_kind () = 0;
@@ -1247,6 +1235,8 @@ public:
FieldAccess,
Closure,
Block,
+ ConstExpr,
+ ConstBlock,
Continue,
Break,
Range,
@@ -1260,8 +1250,10 @@ public:
Await,
AsyncBlock,
InlineAsm,
+ LlvmInlineAsm,
Identifier,
FormatArgs,
+ OffsetOf,
MacroInvocation,
Borrow,
Dereference,
@@ -1273,6 +1265,7 @@ public:
TypeCast,
Assignment,
CompoundAssignment,
+ Try,
};
virtual Kind get_expr_kind () const = 0;
@@ -1467,6 +1460,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 () {}
@@ -1484,12 +1481,15 @@ public:
virtual location_t get_locus () const = 0;
- NodeId get_node_id () const { return node_id; }
+ // TODO: put this in a virtual base class?
+ virtual 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;
@@ -1505,6 +1505,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;
@@ -1539,6 +1546,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; }
@@ -1547,10 +1559,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;
@@ -1587,17 +1603,9 @@ public:
lifetime_name (std::move (name)), locus (locus)
{}
- // Creates an "error" lifetime.
- static Lifetime error () { return Lifetime (NAMED, ""); }
-
static Lifetime elided () { return Lifetime (WILDCARD, ""); }
// Returns true if the lifetime is in an error state.
- bool is_error () const
- {
- return lifetime_type == NAMED && lifetime_name.empty ();
- }
-
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
@@ -1620,6 +1628,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
@@ -1688,15 +1700,6 @@ public:
// Returns whether the lifetime param has an outer attribute.
bool has_outer_attribute () const { return !outer_attrs.empty (); }
- // Creates an error state lifetime param.
- static LifetimeParam create_error ()
- {
- return LifetimeParam (Lifetime::error (), {}, {}, UNDEF_LOCATION);
- }
-
- // Returns whether the lifetime param is in an error state.
- bool is_error () const { return lifetime.is_error (); }
-
// Constructor
LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds,
AST::AttrVec outer_attrs, location_t locus)
@@ -1742,6 +1745,8 @@ public:
virtual bool is_marked_for_strip () const = 0;
virtual location_t get_locus () const = 0;
+
+ virtual NodeId get_node_id () const = 0;
};
// Item used in trait declarations - abstract base class
@@ -1772,7 +1777,7 @@ public:
return std::unique_ptr<TraitItem> (clone_associated_item_impl ());
}
- NodeId get_node_id () const { return node_id; }
+ NodeId get_node_id () const override { return node_id; }
location_t get_locus () const override { return locus; }
};
@@ -1886,7 +1891,6 @@ public:
{
parsed_items = std::move (new_items);
}
- // TODO: mutable getter seems kinda dodgy
std::vector<std::unique_ptr<MetaItemInner>> &get_meta_items ()
{
return parsed_items;
@@ -1900,18 +1904,19 @@ public:
class SingleASTNode : public Visitable
{
public:
- enum NodeType
- {
- EXPRESSION,
- ITEM,
- STMT,
- EXTERN,
- ASSOC_ITEM,
- TYPE,
+ enum class Kind
+ {
+ Expr,
+ Item,
+ Stmt,
+ Extern,
+ Assoc,
+ Type,
+ Pattern,
};
private:
- NodeType kind;
+ Kind kind;
// FIXME make this a union
std::unique_ptr<Expr> expr;
@@ -1920,30 +1925,35 @@ private:
std::unique_ptr<ExternalItem> external_item;
std::unique_ptr<AssociatedItem> assoc_item;
std::unique_ptr<Type> type;
+ std::unique_ptr<Pattern> pattern;
public:
SingleASTNode (std::unique_ptr<Expr> expr)
- : kind (EXPRESSION), expr (std::move (expr))
+ : kind (Kind::Expr), expr (std::move (expr))
{}
SingleASTNode (std::unique_ptr<Item> item)
- : kind (ITEM), item (std::move (item))
+ : kind (Kind::Item), item (std::move (item))
{}
SingleASTNode (std::unique_ptr<Stmt> stmt)
- : kind (STMT), stmt (std::move (stmt))
+ : kind (Kind::Stmt), stmt (std::move (stmt))
{}
SingleASTNode (std::unique_ptr<ExternalItem> item)
- : kind (EXTERN), external_item (std::move (item))
+ : kind (Kind::Extern), external_item (std::move (item))
{}
SingleASTNode (std::unique_ptr<AssociatedItem> item)
- : kind (ASSOC_ITEM), assoc_item (std::move (item))
+ : kind (Kind::Assoc), assoc_item (std::move (item))
{}
SingleASTNode (std::unique_ptr<Type> type)
- : kind (TYPE), type (std::move (type))
+ : kind (Kind::Type), type (std::move (type))
+ {}
+
+ SingleASTNode (std::unique_ptr<Pattern> pattern)
+ : kind (Kind::Pattern), pattern (std::move (pattern))
{}
SingleASTNode (SingleASTNode const &other);
@@ -1953,23 +1963,23 @@ public:
SingleASTNode (SingleASTNode &&other) = default;
SingleASTNode &operator= (SingleASTNode &&other) = default;
- NodeType get_kind () const { return kind; }
+ Kind get_kind () const { return kind; }
std::unique_ptr<Expr> &get_expr ()
{
- rust_assert (kind == EXPRESSION);
+ rust_assert (kind == Kind::Expr);
return expr;
}
std::unique_ptr<Item> &get_item ()
{
- rust_assert (kind == ITEM);
+ rust_assert (kind == Kind::Item);
return item;
}
std::unique_ptr<Stmt> &get_stmt ()
{
- rust_assert (kind == STMT);
+ rust_assert (kind == Kind::Stmt);
return stmt;
}
@@ -2014,6 +2024,12 @@ public:
return std::move (type);
}
+ std::unique_ptr<Pattern> take_pattern ()
+ {
+ rust_assert (!is_error ());
+ return std::move (pattern);
+ }
+
void accept_vis (ASTVisitor &vis) override;
bool is_error ();
@@ -2109,6 +2125,19 @@ template <> struct less<Rust::Identifier>
return lhs.as_string () < rhs.as_string ();
}
};
+
+template <> struct hash<Rust::Identifier>
+{
+ std::size_t operator() (const Rust::Identifier &k) const
+ {
+ using std::hash;
+ using std::size_t;
+ using std::string;
+
+ return hash<string> () (k.as_string ()) ^ (hash<int> () (k.get_locus ()));
+ }
+};
+
} // namespace std
#endif
diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h
index 3684092..c784ad6 100644
--- a/gcc/rust/ast/rust-builtin-ast-nodes.h
+++ b/gcc/rust/ast/rust-builtin-ast-nodes.h
@@ -134,6 +134,7 @@ public:
FormatArgumentKind get_kind () const { return kind; }
const Expr &get_expr () const { return *expr; }
+ Expr &get_expr () { return *expr; }
private:
FormatArgument (FormatArgumentKind::Kind kind, tl::optional<Identifier> ident,
@@ -164,6 +165,11 @@ public:
void push (FormatArgument &&elt) { args.emplace_back (std::move (elt)); }
const FormatArgument at (size_t idx) const { return args.at (idx); }
+ const std::vector<FormatArgument> &get_args () const { return args; }
+ std::vector<FormatArgument> &get_args () { return args; }
+ size_t size () const { return args.size (); }
+ bool empty () const { return args.empty (); }
+
private:
std::vector<FormatArgument> args;
};
@@ -200,6 +206,7 @@ public:
const Fmt::Pieces &get_template () const { return template_pieces; }
const FormatArguments &get_arguments () const { return arguments; }
+ FormatArguments &get_arguments () { return arguments; }
virtual location_t get_locus () const override;
Expr::Kind get_expr_kind () const override { return Expr::Kind::FormatArgs; }
@@ -225,6 +232,60 @@ 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; }
+ std::unique_ptr<Type> &get_type_ptr () { 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..1efe26f 100644
--- a/gcc/rust/ast/rust-collect-lang-items.cc
+++ b/gcc/rust/ast/rust-collect-lang-items.cc
@@ -43,18 +43,16 @@ get_lang_item_attr (const T &maybe_lang_item)
continue;
}
- bool is_lang_item = str_path == Values::Attributes::LANG
- && attr.has_attr_input ()
- && attr.get_attr_input ().get_attr_input_type ()
- == AST::AttrInput::AttrInputType::LITERAL;
+ bool is_lang_item = str_path == Values::Attributes::LANG;
if (is_lang_item)
{
- auto &literal
- = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
- const auto &lang_item_type_str = literal.get_literal ().as_string ();
+ auto lang_item_type_str
+ = Analysis::Attributes::extract_string_literal (attr);
- return LangItem::Parse (lang_item_type_str);
+ rust_assert (lang_item_type_str.has_value ());
+
+ return LangItem::Parse (*lang_item_type_str);
}
}
@@ -109,5 +107,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..5d5fba5 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.
@@ -91,9 +91,13 @@ class ConfigurationAll : public ConfigurationPredicate
predicate_list; // inlined form
public:
+ ConfigurationAll (const ConfigurationAll &) = delete;
+
+ ConfigurationAll (ConfigurationAll &&) = default;
+
ConfigurationAll (
std::vector<std::unique_ptr<ConfigurationPredicate>> predicate_list)
- : predicate_list (predicate_list)
+ : predicate_list (std::move (predicate_list))
{}
void accept_vis (ASTVisitor &vis) override;
@@ -103,7 +107,14 @@ protected:
* than base */
ConfigurationAll *clone_configuration_predicate_impl () const override
{
- return new ConfigurationAll (*this);
+ decltype (predicate_list) predicate_list_clone = {};
+ predicate_list_clone.reserve (predicate_list.size ());
+
+ for (const auto &predicate : predicate_list)
+ predicate_list_clone.push_back (
+ predicate->clone_configuration_predicate ());
+
+ return new ConfigurationAll (std::move (predicate_list_clone));
}
};
@@ -114,9 +125,13 @@ class ConfigurationAny : public ConfigurationPredicate
predicate_list; // inlined form
public:
+ ConfigurationAny (const ConfigurationAny &) = delete;
+
+ ConfigurationAny (ConfigurationAny &&) = default;
+
ConfigurationAny (
std::vector<std::unique_ptr<ConfigurationPredicate>> predicate_list)
- : predicate_list (predicate_list)
+ : predicate_list (std::move (predicate_list))
{}
void accept_vis (ASTVisitor &vis) override;
@@ -126,7 +141,14 @@ protected:
* than base */
ConfigurationAny *clone_configuration_predicate_impl () const override
{
- return new ConfigurationAny (*this);
+ decltype (predicate_list) predicate_list_clone = {};
+ predicate_list_clone.reserve (predicate_list.size ());
+
+ for (const auto &predicate : predicate_list)
+ predicate_list_clone.push_back (
+ predicate->clone_configuration_predicate ());
+
+ return new ConfigurationAny (std::move (predicate_list_clone));
}
};
@@ -226,7 +248,7 @@ public:
CfgAttrAttribute (CfgAttrAttribute const &other)
: config_to_include (
other.config_to_include->clone_configuration_predicate ()),
- cfg_attrs (cfg_attrs)
+ cfg_attrs (other.cfg_attrs)
{}
// Overloaded assignment operator to clone
diff --git a/gcc/rust/ast/rust-desugar-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc
new file mode 100644
index 0000000..de34e15
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-apit.cc
@@ -0,0 +1,530 @@
+// 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.emplace_back (
+ 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;
+ bounds.reserve (type.get_type_param_bounds ().size ());
+
+ 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.emplace_back (
+ 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;
+ type_param_bounds.reserve (
+ tp.get_type_param_bounds ().size ());
+
+ 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.emplace_back (
+ 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 5e5cbbc..9a12423 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,36 +30,14 @@ 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 = std::unique_ptr<Expr> (
- new BreakExpr (Lifetime::error (), nullptr, {}, loc));
+ auto break_expr
+ = std::unique_ptr<Expr> (new BreakExpr (tl::nullopt, nullptr, {}, loc));
return MatchCase (std::move (arm), std::move (break_expr));
}
@@ -74,12 +51,12 @@ DesugarForLoops::DesugarCtx::make_continue_arm ()
patterns.emplace_back (std::move (val));
auto pattern_item = std::unique_ptr<TupleStructItems> (
- new TupleStructItemsNoRange (std::move (patterns)));
+ new TupleStructItemsNoRest (std::move (patterns)));
auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern (
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..20a4903 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
@@ -84,7 +55,7 @@ ok_case (Builder &builder)
patterns.emplace_back (std::move (val));
auto pattern_item = std::unique_ptr<TupleStructItems> (
- new TupleStructItemsNoRange (std::move (patterns)));
+ new TupleStructItemsNoRest (std::move (patterns)));
auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern (
builder.path_in_expression (LangItem::Kind::RESULT_OK),
std::move (pattern_item)));
@@ -99,13 +70,19 @@ 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>> ();
patterns.emplace_back (std::move (val));
auto pattern_item = std::unique_ptr<TupleStructItems> (
- new TupleStructItemsNoRange (std::move (patterns)));
+ new TupleStructItemsNoRest (std::move (patterns)));
auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern (
builder.path_in_expression (LangItem::Kind::RESULT_ERR),
std::move (pattern_item)));
@@ -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 cff09fe..3c36238 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"
@@ -31,11 +32,6 @@ public:
{}
// Returns whether the LoopLabel is in an error state.
- bool is_error () const { return label.is_error (); }
-
- // Creates an error state LoopLabel.
- static LoopLabel error () { return LoopLabel (Lifetime::error ()); }
-
location_t get_locus () const { return locus; }
Lifetime &get_lifetime () { return label; }
@@ -187,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;
@@ -249,40 +249,60 @@ 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; }
+ Expr &get_expr () { return *expr; }
- LiteralExpr &get_literal () { return lit; }
+ std::unique_ptr<Expr> &get_expr_ptr () { 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.
- location_t get_locus () const override { return UNKNOWN_LOCATION; }
+ location_t get_locus () const override
+ {
+ rust_unreachable ();
+ return UNKNOWN_LOCATION;
+ }
void accept_vis (ASTVisitor &vis) override;
@@ -294,9 +314,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);
}
};
@@ -400,6 +420,14 @@ public:
return *main_or_left_expr;
}
+ std::unique_ptr<Expr> &get_borrowed_expr_ptr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ 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; }
@@ -439,6 +467,12 @@ public:
return *main_or_left_expr;
}
+ std::unique_ptr<Expr> &get_dereferenced_expr_ptr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
+
Expr::Kind get_expr_kind () const override { return Expr::Kind::Dereference; }
protected:
@@ -472,6 +506,12 @@ public:
return *main_or_left_expr;
}
+ std::unique_ptr<Expr> &get_propagating_expr_ptr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
+
Expr::Kind get_expr_kind () const override
{
return Expr::Kind::ErrorPropagation;
@@ -520,6 +560,12 @@ public:
return *main_or_left_expr;
}
+ std::unique_ptr<Expr> &get_negated_expr_ptr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
+
Expr::Kind get_expr_kind () const override { return Expr::Kind::Negation; }
protected:
@@ -849,6 +895,12 @@ public:
return *main_or_left_expr;
}
+ std::unique_ptr<Expr> &get_casted_expr_ptr ()
+ {
+ rust_assert (main_or_left_expr != nullptr);
+ return main_or_left_expr;
+ }
+
// TODO: is this better? Or is a "vis_block" better?
TypeNoBounds &get_type_to_cast_to ()
{
@@ -856,6 +908,12 @@ public:
return *type_to_convert_to;
}
+ std::unique_ptr<TypeNoBounds> &get_type_to_cast_to_ptr ()
+ {
+ rust_assert (type_to_convert_to != nullptr);
+ return type_to_convert_to;
+ }
+
Expr::Kind get_expr_kind () const override { return Expr::Kind::TypeCast; }
protected:
@@ -1165,11 +1223,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)
{}
@@ -1197,14 +1255,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 (); }
@@ -1219,6 +1279,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;
@@ -1251,6 +1313,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?
@@ -1260,6 +1324,12 @@ public:
return *elem_to_copy;
}
+ std::unique_ptr<Expr> &get_elem_to_copy_ptr ()
+ {
+ rust_assert (elem_to_copy != nullptr);
+ return elem_to_copy;
+ }
+
// TODO: is this better? Or is a "vis_block" better?
Expr &get_num_copies ()
{
@@ -1267,6 +1337,12 @@ public:
return *num_copies;
}
+ std::unique_ptr<Expr> &get_num_copies_ptr ()
+ {
+ rust_assert (num_copies != nullptr);
+ return num_copies;
+ }
+
protected:
ArrayElemsCopied *clone_array_elems_impl () const override
{
@@ -1446,6 +1522,12 @@ public:
return *array_expr;
}
+ std::unique_ptr<Expr> &get_array_expr_ptr ()
+ {
+ rust_assert (array_expr != nullptr);
+ return array_expr;
+ }
+
// TODO: is this better? Or is a "vis_block" better?
Expr &get_index_expr ()
{
@@ -1453,6 +1535,12 @@ public:
return *index_expr;
}
+ std::unique_ptr<Expr> &get_index_expr_ptr ()
+ {
+ rust_assert (index_expr != nullptr);
+ return index_expr;
+ }
+
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
@@ -1477,7 +1565,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?
@@ -1497,7 +1585,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)),
@@ -1548,14 +1636,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; }
@@ -1580,6 +1665,7 @@ class TupleIndexExpr : public ExprWithoutBlock
TupleIndex tuple_index;
location_t locus;
+ bool to_strip;
// i.e. pair.0
@@ -1591,13 +1677,15 @@ public:
TupleIndexExpr (std::unique_ptr<Expr> tuple_expr, TupleIndex index,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
- tuple_expr (std::move (tuple_expr)), tuple_index (index), locus (locus)
+ tuple_expr (std::move (tuple_expr)), tuple_index (index), locus (locus),
+ to_strip (false)
{}
// Copy constructor requires a clone for tuple_expr
TupleIndexExpr (TupleIndexExpr const &other)
: ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
- tuple_index (other.tuple_index), locus (other.locus)
+ tuple_index (other.tuple_index), locus (other.locus),
+ to_strip (other.to_strip)
{
// guard to prevent null dereference (only required if error state)
if (other.tuple_expr != nullptr)
@@ -1611,6 +1699,7 @@ public:
tuple_index = other.tuple_index;
locus = other.locus;
outer_attrs = other.outer_attrs;
+ to_strip = other.to_strip;
// guard to prevent null dereference (only required if error state)
if (other.tuple_expr != nullptr)
@@ -1630,8 +1719,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
// Invalid if tuple expr is null, so base stripping on that.
- void mark_for_strip () override { tuple_expr = nullptr; }
- bool is_marked_for_strip () const override { return tuple_expr == nullptr; }
+ void mark_for_strip () override { to_strip = true; }
+ bool is_marked_for_strip () const override { return to_strip; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_tuple_expr ()
@@ -1640,6 +1729,12 @@ public:
return *tuple_expr;
}
+ std::unique_ptr<Expr> &get_tuple_expr_ptr ()
+ {
+ rust_assert (tuple_expr != nullptr);
+ return tuple_expr;
+ }
+
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
@@ -1780,12 +1875,20 @@ 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 ()
{
rust_assert (base_struct != nullptr);
return *base_struct;
}
+
+ std::unique_ptr<Expr> &get_base_struct_ptr ()
+ {
+ rust_assert (base_struct != nullptr);
+ return base_struct;
+ }
};
/* Base AST node for a single struct expression field (in struct instance
@@ -1902,6 +2005,12 @@ public:
rust_assert (value != nullptr);
return *value;
}
+
+ std::unique_ptr<Expr> &get_value_ptr ()
+ {
+ rust_assert (value != nullptr);
+ return value;
+ }
};
// Identifier and value variant of StructExprField AST node
@@ -1977,7 +2086,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;
@@ -1990,8 +2099,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),
@@ -2028,11 +2137,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;
}
@@ -2089,7 +2198,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:
@@ -2098,7 +2207,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)),
@@ -2155,11 +2264,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 ()
@@ -2195,7 +2304,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:
@@ -2203,7 +2312,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)),
@@ -2259,11 +2368,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 ()
@@ -2272,6 +2381,12 @@ public:
return *receiver;
}
+ std::unique_ptr<Expr> &get_receiver_expr_ptr ()
+ {
+ rust_assert (receiver != nullptr);
+ return receiver;
+ }
+
const PathExprSegment &get_method_name () const { return method_name; }
PathExprSegment &get_method_name () { return method_name; }
@@ -2360,6 +2475,12 @@ public:
return *receiver;
}
+ std::unique_ptr<Expr> &get_receiver_expr_ptr ()
+ {
+ rust_assert (receiver != nullptr);
+ return receiver;
+ }
+
Identifier get_field_name () const { return field; }
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
@@ -2459,6 +2580,12 @@ public:
return *pattern;
}
+ std::unique_ptr<Pattern> &get_pattern_ptr ()
+ {
+ rust_assert (pattern != nullptr);
+ return pattern;
+ }
+
Type &get_type ()
{
rust_assert (has_type_given ());
@@ -2509,6 +2636,9 @@ 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;
+ virtual std::unique_ptr<Expr> &get_definition_expr_ptr () = 0;
};
// Represents a non-type-specified closure expression AST node
@@ -2568,12 +2698,18 @@ public:
return closure_inner == nullptr;
}
- Expr &get_definition_expr ()
+ Expr &get_definition_expr () override
{
rust_assert (closure_inner != nullptr);
return *closure_inner;
}
+ std::unique_ptr<Expr> &get_definition_expr_ptr () override
+ {
+ rust_assert (closure_inner != nullptr);
+ return closure_inner;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2588,9 +2724,9 @@ 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;
- LoopLabel label;
+ tl::optional<LoopLabel> label;
location_t start_locus;
location_t end_locus;
bool marked_for_strip = false;
@@ -2604,11 +2740,12 @@ 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, LoopLabel label,
- location_t start_locus, location_t end_locus)
+ std::vector<Attribute> outer_attribs,
+ tl::optional<LoopLabel> label, location_t start_locus,
+ location_t end_locus)
: outer_attrs (std::move (outer_attribs)),
inner_attrs (std::move (inner_attribs)),
statements (std::move (block_statements)), expr (std::move (block_expr)),
@@ -2682,11 +2819,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 ()
@@ -2727,8 +2864,8 @@ public:
outer_attrs = std::move (new_attrs);
}
- bool has_label () { return !label.is_error (); }
- LoopLabel &get_label () { return label; }
+ bool has_label () { return label.has_value (); }
+ LoopLabel &get_label () { return label.value (); }
Expr::Kind get_expr_kind () const override { return Expr::Kind::Block; }
@@ -2748,13 +2885,163 @@ 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 ();
+ }
+
+ std::unique_ptr<Expr> &get_inner_expr_ptr ()
+ {
+ 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
{
// TODO: spec says typenobounds
std::unique_ptr<Type> return_type;
- std::unique_ptr<BlockExpr>
- expr; // only used because may be polymorphic in future
+ std::unique_ptr<Expr> expr; // only used because may be polymorphic in future
public:
std::string as_string () const override;
@@ -2778,7 +3065,7 @@ public:
{
// guard to prevent null dereference (only required if error state)
if (other.expr != nullptr)
- expr = other.expr->clone_block_expr ();
+ expr = other.expr->clone_expr ();
if (other.return_type != nullptr)
return_type = other.return_type->clone_type ();
}
@@ -2793,7 +3080,7 @@ public:
// guard to prevent null dereference (only required if error state)
if (other.expr != nullptr)
- expr = other.expr->clone_block_expr ();
+ expr = other.expr->clone_expr ();
else
expr = nullptr;
if (other.return_type != nullptr)
@@ -2816,12 +3103,19 @@ 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 ()
+ Expr &get_definition_expr () override
{
rust_assert (expr != nullptr);
return *expr;
}
+ std::unique_ptr<Expr> &get_definition_expr_ptr () override
+ {
+ rust_assert (expr != nullptr);
+
+ return expr;
+ }
+
// TODO: is this better? Or is a "vis_block" better?
Type &get_return_type ()
{
@@ -2848,7 +3142,7 @@ protected:
class ContinueExpr : public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
- Lifetime label;
+ tl::optional<Lifetime> label;
location_t locus;
// TODO: find another way to store this to save memory?
@@ -2858,11 +3152,11 @@ public:
std::string as_string () const override;
// Returns true if the continue expr has a label.
- bool has_label () const { return !label.is_error (); }
+ bool has_label () const { return label.has_value (); }
// Constructor for a ContinueExpr with a label.
- ContinueExpr (Lifetime label, std::vector<Attribute> outer_attribs,
- location_t locus)
+ ContinueExpr (tl::optional<Lifetime> label,
+ std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)), label (std::move (label)),
locus (locus)
{}
@@ -2883,7 +3177,11 @@ public:
outer_attrs = std::move (new_attrs);
}
- Lifetime &get_label () { return label; }
+ Lifetime &get_label_unchecked () { return label.value (); }
+ const Lifetime &get_label_unchecked () const { return label.value (); }
+
+ tl::optional<Lifetime> &get_label () { return label; }
+ const tl::optional<Lifetime> &get_label () const { return label; }
Expr::Kind get_expr_kind () const override { return Expr::Kind::Continue; }
@@ -2901,7 +3199,7 @@ protected:
class BreakExpr : public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
- LoopLabel label;
+ tl::optional<LoopLabel> label;
std::unique_ptr<Expr> break_expr;
location_t locus;
@@ -2912,14 +3210,15 @@ public:
std::string as_string () const override;
// Returns whether the break expression has a label or not.
- bool has_label () const { return !label.is_error (); }
+ bool has_label () const { return label.has_value (); }
/* Returns whether the break expression has an expression used in the break or
* not. */
bool has_break_expr () const { return break_expr != nullptr; }
// Constructor for a break expression
- BreakExpr (LoopLabel break_label, std::unique_ptr<Expr> expr_in_break,
+ BreakExpr (tl::optional<LoopLabel> break_label,
+ std::unique_ptr<Expr> expr_in_break,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)), label (std::move (break_label)),
break_expr (std::move (expr_in_break)), locus (locus)
@@ -2973,6 +3272,12 @@ public:
return *break_expr;
}
+ std::unique_ptr<Expr> &get_break_expr_ptr ()
+ {
+ rust_assert (has_break_expr ());
+ return break_expr;
+ }
+
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
@@ -2981,7 +3286,11 @@ public:
outer_attrs = std::move (new_attrs);
}
- LoopLabel &get_label () { return label; }
+ LoopLabel &get_label_unchecked () { return label.value (); }
+ const LoopLabel &get_label_unchecked () const { return label.value (); }
+
+ tl::optional<LoopLabel> &get_label () { return label; }
+ const tl::optional<LoopLabel> &get_label () const { return label; }
Expr::Kind get_expr_kind () const override { return Expr::Kind::Break; }
@@ -2999,6 +3308,10 @@ class RangeExpr : public ExprWithoutBlock
{
location_t locus;
+ // Some visitors still check for attributes on RangeExprs, and they will need
+ // to be supported in the future - so keep that for now
+ std::vector<Attribute> empty_attributes = {};
+
protected:
// outer attributes not allowed before range expressions
RangeExpr (location_t locus) : locus (locus) {}
@@ -3008,15 +3321,11 @@ public:
std::vector<Attribute> &get_outer_attrs () override final
{
- // RangeExpr cannot have any outer attributes
- rust_assert (false);
+ return empty_attributes;
}
// should never be called - error if called
- void set_outer_attrs (std::vector<Attribute> /* new_attrs */) override
- {
- rust_assert (false);
- }
+ void set_outer_attrs (std::vector<Attribute> /* new_attrs */) override {}
Expr::Kind get_expr_kind () const override { return Expr::Kind::Range; }
};
@@ -3096,6 +3405,18 @@ public:
return *to;
}
+ std::unique_ptr<Expr> &get_from_expr_ptr ()
+ {
+ rust_assert (from != nullptr);
+ return from;
+ }
+
+ std::unique_ptr<Expr> &get_to_expr_ptr ()
+ {
+ rust_assert (to != nullptr);
+ return to;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3157,6 +3478,12 @@ public:
return *from;
}
+ std::unique_ptr<Expr> &get_from_expr_ptr ()
+ {
+ rust_assert (from != nullptr);
+ return from;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3219,6 +3546,12 @@ public:
return *to;
}
+ std::unique_ptr<Expr> &get_to_expr_ptr ()
+ {
+ rust_assert (to != nullptr);
+ return to;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3332,6 +3665,18 @@ public:
return *to;
}
+ std::unique_ptr<Expr> &get_from_expr_ptr ()
+ {
+ rust_assert (from != nullptr);
+ return from;
+ }
+
+ std::unique_ptr<Expr> &get_to_expr_ptr ()
+ {
+ rust_assert (to != nullptr);
+ return to;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3394,6 +3739,12 @@ public:
return *to;
}
+ std::unique_ptr<Expr> &get_to_expr_ptr ()
+ {
+ rust_assert (to != nullptr);
+ return to;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3467,6 +3818,12 @@ public:
return *expr;
}
+ std::unique_ptr<Expr> &get_boxed_expr_ptr ()
+ {
+ rust_assert (expr != nullptr);
+ return expr;
+ }
+
Expr::Kind get_expr_kind () const override { return Expr::Kind::Box; }
protected:
@@ -3548,6 +3905,12 @@ public:
return *return_expr;
}
+ std::unique_ptr<Expr> &get_returned_expr_ptr ()
+ {
+ rust_assert (return_expr != nullptr);
+ return return_expr;
+ }
+
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
@@ -3567,6 +3930,83 @@ 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; }
+ std::unique_ptr<BlockExpr> &get_block_expr_ptr () { 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;
@@ -3632,6 +4072,12 @@ public:
return *expr;
}
+ std::unique_ptr<BlockExpr> &get_block_expr_ptr ()
+ {
+ rust_assert (expr != nullptr);
+ return expr;
+ }
+
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
@@ -3657,7 +4103,7 @@ class BaseLoopExpr : public ExprWithBlock
protected:
// protected to allow subclasses better use of them
std::vector<Attribute> outer_attrs;
- LoopLabel loop_label;
+ tl::optional<LoopLabel> loop_label;
std::unique_ptr<BlockExpr> loop_block;
private:
@@ -3666,7 +4112,7 @@ private:
protected:
// Constructor for BaseLoopExpr
BaseLoopExpr (std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs
= std::vector<Attribute> ())
: outer_attrs (std::move (outer_attribs)),
@@ -3706,9 +4152,10 @@ protected:
BaseLoopExpr &operator= (BaseLoopExpr &&other) = default;
public:
- bool has_loop_label () const { return !loop_label.is_error (); }
+ bool has_loop_label () const { return loop_label.has_value (); }
- LoopLabel &get_loop_label () { return loop_label; }
+ LoopLabel &get_loop_label () { return loop_label.value (); }
+ const LoopLabel &get_loop_label () const { return loop_label.value (); }
location_t get_locus () const override final { return locus; }
@@ -3723,6 +4170,12 @@ public:
return *loop_block;
}
+ std::unique_ptr<BlockExpr> &get_loop_block_ptr ()
+ {
+ rust_assert (loop_block != nullptr);
+ return loop_block;
+ }
+
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
@@ -3752,7 +4205,7 @@ public:
// Constructor for LoopExpr
LoopExpr (std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
: BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
std::move (outer_attribs))
@@ -3785,7 +4238,7 @@ public:
// Constructor for while loop with loop label
WhileLoopExpr (std::unique_ptr<Expr> loop_condition,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs
= std::vector<Attribute> ())
: BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
@@ -3823,6 +4276,12 @@ public:
return *condition;
}
+ std::unique_ptr<Expr> &get_predicate_expr_ptr ()
+ {
+ rust_assert (condition != nullptr);
+ return condition;
+ }
+
BaseLoopExpr::Kind get_loop_kind () const override
{
return BaseLoopExpr::Kind::While;
@@ -3841,17 +4300,17 @@ 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,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs
= std::vector<Attribute> ())
: BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
@@ -3901,12 +4360,18 @@ public:
return *scrutinee;
}
+ std::unique_ptr<Expr> &get_scrutinee_expr_ptr ()
+ {
+ rust_assert (scrutinee != nullptr);
+ return scrutinee;
+ }
+
// 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;
}
@@ -3938,7 +4403,7 @@ public:
ForLoopExpr (std::unique_ptr<Pattern> loop_pattern,
std::unique_ptr<Expr> iterator_expr,
std::unique_ptr<BlockExpr> loop_body, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
: BaseLoopExpr (std::move (loop_body), locus, std::move (loop_label),
std::move (outer_attribs)),
@@ -3978,6 +4443,12 @@ public:
return *iterator_expr;
}
+ std::unique_ptr<Expr> &get_iterator_expr_ptr ()
+ {
+ rust_assert (iterator_expr != nullptr);
+ return iterator_expr;
+ }
+
// TODO: is this better? Or is a "vis_block" better?
Pattern &get_pattern ()
{
@@ -3985,6 +4456,12 @@ public:
return *pattern;
}
+ std::unique_ptr<Pattern> &get_pattern_ptr ()
+ {
+ rust_assert (pattern != nullptr);
+ return pattern;
+ }
+
BaseLoopExpr::Kind get_loop_kind () const override
{
return BaseLoopExpr::Kind::For;
@@ -4189,7 +4666,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;
@@ -4197,7 +4674,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)),
@@ -4291,11 +4768,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;
}
@@ -4335,11 +4812,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))
@@ -4392,7 +4869,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
@@ -4405,7 +4882,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)),
@@ -4457,7 +4934,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;
@@ -4479,11 +4956,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;
}
@@ -4637,6 +5114,12 @@ public:
return *branch_value;
}
+ std::unique_ptr<Expr> &get_scrutinee_expr_ptr ()
+ {
+ rust_assert (branch_value != nullptr);
+ return branch_value;
+ }
+
const std::vector<MatchCase> &get_match_cases () const { return match_arms; }
std::vector<MatchCase> &get_match_cases () { return match_arms; }
@@ -4830,29 +5313,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
@@ -4879,6 +5339,27 @@ struct InlineAsmRegOrRegClass
location_t locus;
};
+struct LlvmOperand
+{
+ std::string constraint;
+ std::unique_ptr<Expr> expr;
+
+ LlvmOperand (std::string constraint, std::unique_ptr<Expr> &&expr)
+ : constraint (constraint), expr (std::move (expr))
+ {}
+
+ LlvmOperand (const LlvmOperand &other)
+ : constraint (other.constraint), expr (other.expr->clone_expr ())
+ {}
+ LlvmOperand &operator= (const LlvmOperand &other)
+ {
+ constraint = other.constraint;
+ expr = other.expr->clone_expr ();
+
+ return *this;
+ }
+};
+
class InlineAsmOperand
{
public:
@@ -5241,6 +5722,8 @@ struct InlineAsmTemplatePiece
struct TupleClobber
{
+ TupleClobber (std::string symbol, location_t loc) : symbol (symbol), loc (loc)
+ {}
// as gccrs still doesn't contain a symbol class I have put them as strings
std::string symbol;
location_t loc;
@@ -5252,6 +5735,7 @@ struct TupleTemplateStr
location_t loc;
std::string symbol;
+ location_t get_locus () { return loc; }
TupleTemplateStr (location_t loc, const std::string &symbol)
: loc (loc), symbol (symbol)
{}
@@ -5260,6 +5744,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
@@ -5283,7 +5781,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;
@@ -5314,7 +5812,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
{
@@ -5322,6 +5820,111 @@ 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
+{
+ // llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
+ // Asm, Outputs, Inputs, Clobbers, Options,
+
+public:
+ enum class Dialect
+ {
+ Att,
+ Intel,
+ };
+
+private:
+ location_t locus;
+ std::vector<Attribute> outer_attrs;
+ std::vector<LlvmOperand> inputs;
+ std::vector<LlvmOperand> outputs;
+ std::vector<TupleTemplateStr> templates;
+ std::vector<TupleClobber> clobbers;
+ bool volatility;
+ bool align_stack;
+ Dialect dialect;
+
+public:
+ LlvmInlineAsm (location_t locus) : locus (locus) {}
+
+ Dialect get_dialect () { return dialect; }
+
+ location_t get_locus () const override { return locus; }
+
+ void mark_for_strip () override {}
+
+ bool is_marked_for_strip () const override { return false; }
+
+ std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ std::string as_string () const override { return "InlineAsm AST Node"; }
+
+ void set_outer_attrs (std::vector<Attribute> v) override { outer_attrs = v; }
+
+ LlvmInlineAsm *clone_expr_without_block_impl () const override
+ {
+ return new LlvmInlineAsm (*this);
+ }
+
+ std::vector<TupleTemplateStr> &get_templates () { return templates; }
+ const std::vector<TupleTemplateStr> &get_templates () const
+ {
+ return templates;
+ }
+
+ Expr::Kind get_expr_kind () const override
+ {
+ return Expr::Kind::LlvmInlineAsm;
+ }
+
+ void set_align_stack (bool align_stack) { this->align_stack = align_stack; }
+ bool is_stack_aligned () { return align_stack; }
+
+ void set_volatile (bool volatility) { this->volatility = volatility; }
+ bool is_volatile () { return volatility; }
+
+ void set_dialect (Dialect dialect) { this->dialect = dialect; }
+
+ void set_inputs (std::vector<LlvmOperand> operands) { inputs = operands; }
+ void set_outputs (std::vector<LlvmOperand> operands) { outputs = operands; }
+
+ std::vector<LlvmOperand> &get_inputs () { return inputs; }
+ const std::vector<LlvmOperand> &get_inputs () const { return inputs; }
+ std::vector<LlvmOperand> &get_outputs () { return outputs; }
+ const std::vector<LlvmOperand> &get_outputs () const { return outputs; }
+
+ std::vector<TupleClobber> &get_clobbers () { return clobbers; }
+ const std::vector<TupleClobber> &get_clobbers () const { return clobbers; }
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-expression-yeast.cc b/gcc/rust/ast/rust-expression-yeast.cc
new file mode 100644
index 0000000..7626abc
--- /dev/null
+++ b/gcc/rust/ast/rust-expression-yeast.cc
@@ -0,0 +1,77 @@
+// 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-desugar-while-let.h"
+#include "rust-expr.h"
+
+namespace Rust {
+namespace AST {
+
+void
+ExpressionYeast::go (AST::Crate &crate)
+{
+ PointerVisitor::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::reseat (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;
+ }
+
+ visit (expr);
+}
+
+} // 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..3f64b1d
--- /dev/null
+++ b/gcc/rust/ast/rust-expression-yeast.h
@@ -0,0 +1,49 @@
+// 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-pointer-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::PointerVisitor
+{
+ using AST::PointerVisitor::reseat;
+ using AST::PointerVisitor::visit;
+
+public:
+ void go (AST::Crate &);
+
+private:
+ // Dispatch to the proper desugar
+ void reseat (std::unique_ptr<Expr> &expr) override;
+
+ void dispatch_loops (std::unique_ptr<Expr> &loop_expr);
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_EXPRESSION_YEAST
diff --git a/gcc/rust/ast/rust-fmt.cc b/gcc/rust/ast/rust-fmt.cc
index a29c820..21f4f03 100644
--- a/gcc/rust/ast/rust-fmt.cc
+++ b/gcc/rust/ast/rust-fmt.cc
@@ -32,41 +32,11 @@ Pieces
Pieces::collect (const std::string &to_parse, bool append_newline,
ffi::ParseMode parse_mode)
{
- auto handle
- = ffi::collect_pieces (to_parse.c_str (), append_newline, parse_mode);
-
- // this performs multiple copies, can we avoid them maybe?
- // TODO: Instead of just creating a vec of, basically, `ffi::Piece`s, we
- // should transform them into the proper C++ type which we can work with. so
- // transform all the strings into C++ strings? all the Option<T> into
- // tl::optional<T>?
- auto pieces_vector = std::vector<ffi::Piece> (handle.piece_slice.base_ptr,
- handle.piece_slice.base_ptr
- + handle.piece_slice.len);
-
- return Pieces (handle, std::move (pieces_vector));
-}
-
-Pieces::~Pieces () { ffi::destroy_pieces (handle); }
-
-Pieces::Pieces (const Pieces &other) : pieces_vector (other.pieces_vector)
-{
- handle = ffi::clone_pieces (other.handle);
+ Pieces ret (to_parse, ffi::FFIVec<ffi::Piece> ());
+ ret.data->second = ffi::collect_pieces (ffi::RustHamster (ret.data->first),
+ append_newline, parse_mode);
+ return ret;
}
-Pieces &
-Pieces::operator= (const Pieces &other)
-{
- handle = ffi::clone_pieces (other.handle);
- pieces_vector = other.pieces_vector;
-
- return *this;
-}
-
-Pieces::Pieces (Pieces &&other)
- : pieces_vector (std::move (other.pieces_vector)),
- handle (clone_pieces (other.handle))
-{}
-
} // namespace Fmt
} // namespace Rust
diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h
index a54faec..13dc7be 100644
--- a/gcc/rust/ast/rust-fmt.h
+++ b/gcc/rust/ast/rust-fmt.h
@@ -20,20 +20,174 @@
#define RUST_FMT_H
#include "rust-system.h"
+#include "optional.h"
-// FIXME: How to encode Option?
+// PR122498 "rust-enabled bootstrap is broken after r16-4897"
+#pragma GCC diagnostic warning "-Warray-bounds"
namespace Rust {
namespace Fmt {
namespace ffi {
+extern "C" {
+
+unsigned char *rust_ffi_alloc (size_t count, size_t elem_size, size_t align);
+
+void rust_ffi_dealloc (unsigned char *data, size_t count, size_t elem_size,
+ size_t align);
+
+} // extern "C"
+
+template <typename T> class FFIVec
+{
+ T *data;
+ size_t len;
+ size_t cap;
+
+public:
+ FFIVec () : data ((T *) alignof (T)), len (0), cap (0) {}
+
+ FFIVec (const FFIVec &) = delete;
+ FFIVec &operator= (const FFIVec &) = delete;
+
+ FFIVec (FFIVec &&other) : data (other.data), len (other.len), cap (other.cap)
+ {
+ other.data = (T *) alignof (T);
+ other.len = 0;
+ other.cap = 0;
+ }
+
+ FFIVec &operator= (FFIVec &&other)
+ {
+ this->~FFIVec ();
+ new (this) FFIVec (std::move (other));
+ return *this;
+ }
+
+ ~FFIVec ()
+ {
+ // T can't be zero-sized
+ if (cap)
+ rust_ffi_dealloc ((unsigned char *) data, cap, sizeof (T), alignof (T));
+ }
+
+ size_t size () const { return len; }
+
+ const T &operator[] (size_t idx) const
+ {
+ rust_assert (idx <= len);
+ return data[idx];
+ }
+
+ T *begin () { return data; }
+ const T *begin () const { return data; }
+ T *end () { return data + len; }
+ const T *end () const { return data + len; }
+};
+
+// https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md
+template <typename T,
+ typename =
+ typename std::enable_if<std::is_standard_layout<T>::value>::type>
+class FFIOpt
+{
+public:
+ template <typename U>
+ FFIOpt (U &&val) : some{Some::KIND, std::forward<U> (val)}
+ {}
+
+ FFIOpt () : none{None::KIND} {}
+
+ FFIOpt (const FFIOpt &other)
+ {
+ if (other.has_value ())
+ new (&some) Some{Some::KIND, other.some.val};
+ else
+ new (&none) None{None::KIND};
+ }
+
+ FFIOpt (FFIOpt &&other)
+ {
+ if (other.has_value ())
+ new (&some) Some{Some::KIND, std::move (other.some.val)};
+ else
+ new (&none) None{None::KIND};
+ }
+
+ ~FFIOpt ()
+ {
+ if (has_value ())
+ some.~Some ();
+ else
+ none.~None ();
+ }
+
+ FFIOpt &operator= (const FFIOpt &other)
+ {
+ this->~FFIOpt ();
+ new (this) FFIOpt (other);
+ return *this;
+ }
+
+ FFIOpt &operator= (FFIOpt &&other)
+ {
+ this->~FFIOpt ();
+ new (this) FFIOpt (std::move (other));
+ return *this;
+ }
+
+ tl::optional<std::reference_wrapper<T>> get_opt ()
+ {
+ if (has_value ())
+ return std::ref (some.val);
+ else
+ return tl::nullopt;
+ }
+
+ tl::optional<std::reference_wrapper<const T>> get_opt () const
+ {
+ if (has_value ())
+ return std::ref (some.val);
+ else
+ return tl::nullopt;
+ }
+
+ bool has_value () const { return some.kind == Some::KIND; }
+
+ operator bool () const { return has_value (); }
+
+private:
+ struct Some
+ {
+ static constexpr uint8_t KIND = 0;
+ uint8_t kind;
+ T val;
+ };
+
+ struct None
+ {
+ static constexpr uint8_t KIND = 1;
+ uint8_t kind;
+ };
+
+ union
+ {
+ Some some;
+ None none;
+ };
+};
+
struct RustHamster
{
const char *ptr;
size_t len;
std::string to_string () const;
+
+ explicit RustHamster (const std::string &str)
+ : ptr (str.data ()), len (str.size ())
+ {}
};
/// Enum of alignments which are supported.
@@ -166,33 +320,33 @@ struct Count
struct FormatSpec
{
/// Optionally specified character to fill alignment with.
- const uint32_t *fill;
+ FFIOpt<uint32_t> fill;
/// Span of the optionally specified fill character.
- const InnerSpan *fill_span;
+ FFIOpt<InnerSpan> fill_span;
/// Optionally specified alignment.
Alignment align;
/// The `+` or `-` flag.
- const Sign *sign;
+ FFIOpt<Sign> sign;
/// The `#` flag.
bool alternate;
/// The `0` flag.
bool zero_pad;
/// The `x` or `X` flag. (Only for `Debug`.)
- const DebugHex *debug_hex;
+ FFIOpt<DebugHex> debug_hex;
/// The integer precision to use.
Count precision;
/// The span of the precision formatting flag (for diagnostics).
- const InnerSpan *precision_span;
+ FFIOpt<InnerSpan> precision_span;
/// The string width requested for the resulting format.
Count width;
/// The span of the width formatting flag (for diagnostics).
- const InnerSpan *width_span;
+ FFIOpt<InnerSpan> width_span;
/// The descriptor string representing the name of the format desired for
/// this argument, this can be empty or any number of characters, although
/// it is required to be one word.
RustHamster ty;
/// The span of the descriptor string (for diagnostics).
- const InnerSpan *ty_span;
+ FFIOpt<InnerSpan> ty_span;
};
/// Representation of an argument specification.
@@ -238,26 +392,6 @@ struct Piece
};
};
-struct PieceSlice
-{
- const Piece *base_ptr;
- size_t len;
- size_t cap;
-};
-
-struct RustString
-{
- const unsigned char *ptr;
- size_t len;
- size_t cap;
-};
-
-struct FormatArgsHandle
-{
- PieceSlice piece_slice;
- RustString rust_string;
-};
-
enum ParseMode
{
Format = 0,
@@ -266,13 +400,10 @@ enum ParseMode
extern "C" {
-FormatArgsHandle
-collect_pieces (const char *input, bool append_newline, ParseMode parse_mode);
+FFIVec<Piece> collect_pieces (RustHamster input, bool append_newline,
+ ParseMode parse_mode);
-FormatArgsHandle
-clone_pieces (const FormatArgsHandle &);
-
-void destroy_pieces (FormatArgsHandle);
+FFIVec<Piece> clone_pieces (const FFIVec<Piece> &);
} // extern "C"
@@ -282,33 +413,20 @@ struct Pieces
{
static Pieces collect (const std::string &to_parse, bool append_newline,
ffi::ParseMode parse_mode);
- ~Pieces ();
-
- Pieces (const Pieces &other);
- Pieces &operator= (const Pieces &other);
- Pieces (Pieces &&other);
-
- const std::vector<ffi::Piece> &get_pieces () const { return pieces_vector; }
-
- // {
- // slice = clone_pieces (&other.slice);
- // to_parse = other.to_parse;
-
- // return *this;
- // }
+ const ffi::FFIVec<ffi::Piece> &get_pieces () const { return data->second; }
private:
- Pieces (ffi::FormatArgsHandle handle, std::vector<ffi::Piece> &&pieces_vector)
- : pieces_vector (std::move (pieces_vector)), handle (handle)
+ Pieces (std::string str, ffi::FFIVec<ffi::Piece> pieces)
+ : data (
+ std::make_shared<decltype (data)::element_type> (std::move (str),
+ std::move (pieces)))
{}
- std::vector<ffi::Piece> pieces_vector;
-
- // this memory is held for FFI reasons - it needs to be released and cloned
- // precisely, so try to not access it/modify it if possible. you should
- // instead work with `pieces_vector`
- ffi::FormatArgsHandle handle;
+ // makes copying simpler
+ // also, we'd need to keep the parsed string in a shared_ptr anyways
+ // since we store pointers into the parsed string
+ std::shared_ptr<std::pair<std::string, ffi::FFIVec<ffi::Piece>>> data;
};
} // namespace Fmt
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 8eb0cc5..3e3735c 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
@@ -434,13 +429,14 @@ class SelfParam : public Param
bool has_ref;
bool is_mut;
// bool has_lifetime; // only possible if also ref
- Lifetime lifetime;
+ tl::optional<Lifetime> lifetime;
// bool has_type; // only possible if not ref
std::unique_ptr<Type> type;
// Unrestricted constructor used for error state
- SelfParam (Lifetime lifetime, bool has_ref, bool is_mut, Type *type)
+ SelfParam (tl::optional<Lifetime> lifetime, bool has_ref, bool is_mut,
+ Type *type)
: Param ({}, UNDEF_LOCATION), has_ref (has_ref), is_mut (is_mut),
lifetime (std::move (lifetime)), type (type)
{}
@@ -453,7 +449,7 @@ public:
bool has_type () const { return type != nullptr; }
// Returns whether the self-param has a valid lifetime.
- bool has_lifetime () const { return !lifetime.is_error (); }
+ bool has_lifetime () const { return lifetime.has_value (); }
// Returns whether the self-param is in an error state.
bool is_error () const
@@ -472,11 +468,11 @@ public:
// Type-based self parameter (not ref, no lifetime)
SelfParam (std::unique_ptr<Type> type, bool is_mut, location_t locus)
: Param ({}, locus), has_ref (false), is_mut (is_mut),
- lifetime (Lifetime::error ()), type (std::move (type))
+ lifetime (tl::nullopt), type (std::move (type))
{}
// Lifetime-based self parameter (is ref, no type)
- SelfParam (Lifetime lifetime, bool is_mut, location_t locus)
+ SelfParam (tl::optional<Lifetime> lifetime, bool is_mut, location_t locus)
: Param ({}, locus), has_ref (true), is_mut (is_mut),
lifetime (std::move (lifetime))
{}
@@ -522,8 +518,8 @@ public:
bool get_has_ref () const { return has_ref; };
bool get_is_mut () const { return is_mut; }
- Lifetime get_lifetime () const { return lifetime; }
- Lifetime &get_lifetime () { return lifetime; }
+ Lifetime get_lifetime () const { return lifetime.value (); }
+ Lifetime &get_lifetime () { return lifetime.value (); }
NodeId get_node_id () const { return node_id; }
@@ -635,6 +631,12 @@ public:
return *param_name;
}
+ std::unique_ptr<Pattern> &get_pattern_ptr ()
+ {
+ rust_assert (param_name != nullptr);
+ return param_name;
+ }
+
const Pattern &get_pattern () const
{
rust_assert (param_name != nullptr);
@@ -718,6 +720,12 @@ public:
return *param_name;
}
+ std::unique_ptr<Pattern> &get_pattern_ptr ()
+ {
+ rust_assert (param_name != nullptr);
+ return param_name;
+ }
+
bool has_name () const { return param_name != nullptr; }
// TODO: is this better? Or is a "vis_block" better?
@@ -1330,7 +1338,7 @@ class Function : public VisItem, public AssociatedItem, public ExternalItem
WhereClause where_clause;
tl::optional<std::unique_ptr<BlockExpr>> function_body;
location_t locus;
- bool is_default;
+ bool has_default;
bool is_external_function;
public:
@@ -1355,6 +1363,8 @@ public:
bool has_body () const { return function_body.has_value (); }
+ bool is_default () const { return has_default; }
+
// Mega-constructor with all possible fields
Function (Identifier function_name, FunctionQualifiers qualifiers,
std::vector<std::unique_ptr<GenericParam>> generic_params,
@@ -1362,7 +1372,7 @@ public:
std::unique_ptr<Type> return_type, WhereClause where_clause,
tl::optional<std::unique_ptr<BlockExpr>> function_body,
Visibility vis, std::vector<Attribute> outer_attrs,
- location_t locus, bool is_default = false,
+ location_t locus, bool has_default = false,
bool is_external_function = false)
: VisItem (std::move (vis), std::move (outer_attrs)),
ExternalItem (Stmt::node_id), qualifiers (std::move (qualifiers)),
@@ -1372,7 +1382,7 @@ public:
return_type (std::move (return_type)),
where_clause (std::move (where_clause)),
function_body (std::move (function_body)), locus (locus),
- is_default (is_default), is_external_function (is_external_function)
+ has_default (has_default), is_external_function (is_external_function)
{}
// TODO: add constructor with less fields
@@ -1569,6 +1579,9 @@ public:
location_t get_locus () const override final { return locus; }
+ // needed to override AssociatedItem::get_node_id
+ NodeId get_node_id () const override final { return VisItem::get_node_id (); }
+
void accept_vis (ASTVisitor &vis) override;
// Invalid if existing type is null, so base stripping on that.
@@ -1597,6 +1610,12 @@ public:
return *existing_type;
}
+ std::unique_ptr<Type> &get_type_aliased_ptr ()
+ {
+ rust_assert (existing_type != nullptr);
+ return existing_type;
+ }
+
Identifier get_new_type_name () const { return new_type_name; }
Item::Kind get_item_kind () const override { return Item::Kind::TypeAlias; }
@@ -2452,7 +2471,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;
@@ -2462,7 +2481,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)),
@@ -2470,7 +2489,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)),
@@ -2513,13 +2532,16 @@ 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; }
+ // needed to override AssociatedItem::get_node_id
+ NodeId get_node_id () const override final { return VisItem::get_node_id (); }
+
void accept_vis (ASTVisitor &vis) override;
- // Invalid if type or expression are null, so base stripping on that.
+ // Invalid if type and expression are null, so base stripping on that.
void mark_for_strip () override
{
type = nullptr;
@@ -2530,7 +2552,7 @@ public:
return type == nullptr && const_expr == nullptr;
}
- bool has_expr () { return const_expr != nullptr; }
+ bool has_expr () const { return const_expr != nullptr; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_expr ()
@@ -2558,7 +2580,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
{
@@ -2697,123 +2719,6 @@ protected:
}
};
-// Constant item within traits
-class TraitItemConst : public TraitItem
-{
- std::vector<Attribute> outer_attrs;
- Identifier name;
- std::unique_ptr<Type> type;
-
- // bool has_expression;
- std::unique_ptr<Expr> expr;
-
-public:
- // Whether the constant item has an associated expression.
- bool has_expression () const { return expr != nullptr; }
-
- TraitItemConst (Identifier name, std::unique_ptr<Type> type,
- std::unique_ptr<Expr> expr,
- std::vector<Attribute> outer_attrs, location_t locus)
- : TraitItem (locus), outer_attrs (std::move (outer_attrs)),
- name (std::move (name)), type (std::move (type)), expr (std::move (expr))
- {}
-
- // Copy constructor with clones
- TraitItemConst (TraitItemConst const &other)
- : TraitItem (other.locus), outer_attrs (other.outer_attrs),
- name (other.name)
- {
- node_id = other.node_id;
-
- // guard to prevent null dereference
- if (other.expr != nullptr)
- expr = other.expr->clone_expr ();
-
- // guard to prevent null dereference (only for error state)
- if (other.type != nullptr)
- type = other.type->clone_type ();
- }
-
- // Overloaded assignment operator to clone
- TraitItemConst &operator= (TraitItemConst const &other)
- {
- TraitItem::operator= (other);
- outer_attrs = other.outer_attrs;
- name = other.name;
- locus = other.locus;
- node_id = other.node_id;
-
- // guard to prevent null dereference
- if (other.expr != nullptr)
- expr = other.expr->clone_expr ();
- else
- expr = nullptr;
-
- // guard to prevent null dereference (only for error state)
- if (other.type != nullptr)
- type = other.type->clone_type ();
- else
- type = nullptr;
-
- return *this;
- }
-
- // move constructors
- TraitItemConst (TraitItemConst &&other) = default;
- TraitItemConst &operator= (TraitItemConst &&other) = default;
-
- std::string as_string () const override;
-
- location_t get_locus () const override { return locus; }
-
- void accept_vis (ASTVisitor &vis) override;
-
- // Invalid if type is null, so base stripping on that.
- void mark_for_strip () override { type = nullptr; }
- bool is_marked_for_strip () const override { return type == nullptr; }
-
- // TODO: this mutable getter seems really dodgy. Think up better way.
- std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
- const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
-
- bool has_expr () const { return expr != nullptr; }
-
- // TODO: is this better? Or is a "vis_block" better?
- Expr &get_expr ()
- {
- rust_assert (has_expr ());
- return *expr;
- }
-
- std::unique_ptr<Expr> &get_expr_ptr ()
- {
- rust_assert (has_expr ());
- return expr;
- }
-
- // TODO: is this better? Or is a "vis_block" better?
- Type &get_type ()
- {
- rust_assert (type != nullptr);
- return *type;
- }
-
- std::unique_ptr<Type> &get_type_ptr ()
- {
- rust_assert (type != nullptr);
- return type;
- }
-
- Identifier get_identifier () const { return name; }
-
-protected:
- // Clone function implementation as (not pure) virtual method
- TraitItemConst *clone_associated_item_impl () const override
- {
- return new TraitItemConst (*this);
- }
-};
-
// Type items within traits
class TraitItemType : public TraitItem
{
@@ -2821,21 +2726,28 @@ class TraitItemType : public TraitItem
Identifier name;
+ // Generic parameters for GATs (Generic Associated Types)
+ std::vector<std::unique_ptr<GenericParam>> generic_params;
+
// bool has_type_param_bounds;
// TypeParamBounds type_param_bounds;
std::vector<std::unique_ptr<TypeParamBound>>
type_param_bounds; // inlined form
public:
+ bool has_generics () const { return !generic_params.empty (); }
+
// Returns whether trait item type has type param bounds.
bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
TraitItemType (Identifier name,
+ std::vector<std::unique_ptr<GenericParam>> generic_params,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
std::vector<Attribute> outer_attrs, Visibility vis,
location_t locus)
: TraitItem (vis, locus), outer_attrs (std::move (outer_attrs)),
- name (std::move (name)), type_param_bounds (std::move (type_param_bounds))
+ name (std::move (name)), generic_params (std::move (generic_params)),
+ type_param_bounds (std::move (type_param_bounds))
{}
// Copy constructor with vector clone
@@ -2844,6 +2756,9 @@ public:
name (other.name)
{
node_id = other.node_id;
+ generic_params.reserve (other.generic_params.size ());
+ for (const auto &e : other.generic_params)
+ generic_params.push_back (e->clone_generic_param ());
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
type_param_bounds.push_back (e->clone_type_param_bound ());
@@ -2858,6 +2773,9 @@ public:
locus = other.locus;
node_id = other.node_id;
+ generic_params.reserve (other.generic_params.size ());
+ for (const auto &e : other.generic_params)
+ generic_params.push_back (e->clone_generic_param ());
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
type_param_bounds.push_back (e->clone_type_param_bound ());
@@ -2881,7 +2799,15 @@ public:
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
- // TODO: mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
+ {
+ return generic_params;
+ }
+
std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
{
return type_param_bounds;
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index fc01e57..71de8f0 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
@@ -980,6 +993,10 @@ public:
return ident.as_string () + " = \"" + str + "\"";
}
+ const Identifier &get_name () const { return ident; }
+
+ const std::string &get_value () const { return str; }
+
void accept_vis (ASTVisitor &vis) override;
// HACK: used to simplify parsing - creates a copy of this
@@ -1108,16 +1125,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 +1141,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 69627be8..068e364 100644
--- a/gcc/rust/ast/rust-path.cc
+++ b/gcc/rust/ast/rust-path.cc
@@ -119,7 +119,7 @@ ConstGenericParam::as_string () const
str += "const " + name.as_string () + ": " + type->as_string ();
if (has_default_value ())
- str += " = " + get_default_value ().as_string ();
+ str += " = " + get_default_value_unchecked ().as_string ();
return str;
}
@@ -167,14 +167,13 @@ Path::convert_to_simple_path (bool with_opening_scope_resolution) const
for (const auto &segment : segments)
{
// return empty path if doesn't meet simple path segment requirements
- if (segment.is_error () || segment.has_generic_args ()
- || segment.as_string () == "Self")
+ if (segment.is_error () || segment.has_generic_args ())
return SimplePath::create_empty ();
// create segment and add to vector
std::string segment_str = segment.as_string ();
- simple_segments.push_back (
- SimplePathSegment (std::move (segment_str), segment.get_locus ()));
+ simple_segments.emplace_back (std::move (segment_str),
+ segment.get_locus ());
}
// kind of a HACK to get locus depending on opening scope resolution
@@ -258,14 +257,35 @@ TypePath::as_simple_path () const
// create segment and add to vector
std::string segment_str = segment->as_string ();
- simple_segments.push_back (
- SimplePathSegment (std::move (segment_str), segment->get_locus ()));
+ simple_segments.emplace_back (std::move (segment_str),
+ segment->get_locus ());
}
return SimplePath (std::move (simple_segments), has_opening_scope_resolution,
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 805be8e..be04882 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -167,17 +167,11 @@ public:
*/
enum class Kind
{
- Error,
Const, // A const value
Type, // A type argument (not discernable during parsing)
Either, // Either a type or a const value, cleared up during resolving
};
- static GenericArg create_error ()
- {
- return GenericArg (nullptr, nullptr, {""}, Kind::Error, UNDEF_LOCATION);
- }
-
static GenericArg create_const (std::unique_ptr<Expr> expression)
{
auto locus = expression->get_locus ();
@@ -222,8 +216,6 @@ public:
GenericArg (GenericArg &&other) = default;
GenericArg &operator= (GenericArg &&other) = default;
- bool is_error () const { return kind == Kind::Error; }
-
Kind get_kind () const { return kind; }
location_t get_locus () const { return locus; }
@@ -239,8 +231,6 @@ public:
break;
case Kind::Either:
break;
- case Kind::Error:
- rust_unreachable ();
}
}
@@ -283,8 +273,6 @@ public:
{
switch (get_kind ())
{
- case Kind::Error:
- rust_unreachable ();
case Kind::Either:
return "Ambiguous: " + path.as_string ();
case Kind::Const:
@@ -355,15 +343,15 @@ class ConstGenericParam : public GenericParam
/**
* Default value for the const generic parameter
*/
- GenericArg default_value;
+ tl::optional<GenericArg> default_value;
AST::AttrVec outer_attrs;
location_t locus;
public:
ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type,
- GenericArg default_value, AST::AttrVec outer_attrs,
- location_t locus)
+ tl::optional<GenericArg> default_value,
+ AST::AttrVec outer_attrs, location_t locus)
: name (name), type (std::move (type)),
default_value (std::move (default_value)), outer_attrs (outer_attrs),
locus (locus)
@@ -376,7 +364,7 @@ public:
{}
bool has_type () const { return type != nullptr; }
- bool has_default_value () const { return !default_value.is_error (); }
+ bool has_default_value () const { return default_value.has_value (); }
const Identifier &get_name () const { return name; }
@@ -389,17 +377,31 @@ public:
return *type;
}
- GenericArg &get_default_value ()
+ std::unique_ptr<AST::Type> &get_type_ptr ()
+ {
+ rust_assert (has_type ());
+
+ return type;
+ }
+
+ GenericArg &get_default_value_unchecked ()
{
rust_assert (has_default_value ());
- return default_value;
+ return default_value.value ();
}
- const GenericArg &get_default_value () const
+ const GenericArg &get_default_value_unchecked () const
{
rust_assert (has_default_value ());
+ return default_value.value ();
+ }
+
+ tl::optional<GenericArg> &get_default_value () { return default_value; }
+
+ const tl::optional<GenericArg> &get_default_value () const
+ {
return default_value;
}
@@ -453,9 +455,7 @@ public:
generic_args.clear ();
generic_args.reserve (other.generic_args.size ());
for (const auto &arg : other.generic_args)
- {
- generic_args.push_back (GenericArg (arg));
- }
+ generic_args.emplace_back (arg);
}
~GenericArgs () = default;
@@ -470,9 +470,7 @@ public:
generic_args.clear ();
generic_args.reserve (other.generic_args.size ());
for (const auto &arg : other.generic_args)
- {
- generic_args.push_back (GenericArg (arg));
- }
+ generic_args.emplace_back (arg);
return *this;
}
@@ -791,6 +789,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 () {}
@@ -802,6 +805,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)
@@ -826,6 +834,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),
@@ -980,11 +997,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
@@ -1161,6 +1174,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
@@ -1227,6 +1245,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;
@@ -1235,7 +1255,7 @@ public:
TraitBound *to_trait_bound (bool in_parens) const override;
location_t get_locus () const override final { return locus; }
- NodeId get_node_id () const { return node_id; }
+ NodeId get_node_id () const override { return node_id; }
void mark_for_strip () override {}
bool is_marked_for_strip () const override { return false; }
@@ -1450,6 +1470,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..80189d3 100644
--- a/gcc/rust/ast/rust-pattern.cc
+++ b/gcc/rust/ast/rust-pattern.cc
@@ -48,7 +48,7 @@ tokenid_to_rangekind (TokenId id)
std::string
LiteralPattern::as_string () const
{
- return lit.as_string ();
+ return (has_minus ? "-" : "") + lit.as_string ();
}
std::string
@@ -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;
}
@@ -186,8 +186,8 @@ StructPatternElements::as_string () const
str += "\n " + field->as_string ();
}
- str += "\n Etc: ";
- if (has_struct_pattern_etc)
+ str += "\n Has rest: ";
+ if (has_rest_pattern)
str += "true";
else
str += "false";
@@ -212,7 +212,7 @@ StructPattern::as_string () const
}
std::string
-TupleStructItemsNoRange::as_string () const
+TupleStructItemsNoRest::as_string () const
{
std::string str;
@@ -223,7 +223,7 @@ TupleStructItemsNoRange::as_string () const
}
std::string
-TupleStructItemsRange::as_string () const
+TupleStructItemsHasRest::as_string () const
{
std::string str ("\n Lower patterns: ");
@@ -264,7 +264,7 @@ TupleStructPattern::as_string () const
}
std::string
-TuplePatternItemsMultiple::as_string () const
+TuplePatternItemsNoRest::as_string () const
{
std::string str;
@@ -275,7 +275,7 @@ TuplePatternItemsMultiple::as_string () const
}
std::string
-TuplePatternItemsRanged::as_string () const
+TuplePatternItemsHasRest::as_string () const
{
std::string 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,13 +403,25 @@ 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);
}
void
-TuplePatternItemsRanged::accept_vis (ASTVisitor &vis)
+TuplePatternItemsHasRest::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
@@ -385,7 +433,7 @@ TuplePattern::accept_vis (ASTVisitor &vis)
}
void
-TuplePatternItemsMultiple::accept_vis (ASTVisitor &vis)
+TuplePatternItemsNoRest::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
@@ -469,13 +517,13 @@ StructPattern::accept_vis (ASTVisitor &vis)
}
void
-TupleStructItemsNoRange::accept_vis (ASTVisitor &vis)
+TupleStructItemsNoRest::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
-TupleStructItemsRange::accept_vis (ASTVisitor &vis)
+TupleStructItemsHasRest::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..3b1bd1c 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -20,6 +20,7 @@
#define RUST_AST_PATTERN_H
#include "rust-ast.h"
+#include "rust-path.h"
namespace Rust {
namespace AST {
@@ -29,6 +30,7 @@ class LiteralPattern : public Pattern
Literal lit;
location_t locus;
NodeId node_id;
+ bool has_minus;
public:
std::string as_string () const override;
@@ -36,17 +38,34 @@ public:
// Constructor for a literal pattern
LiteralPattern (Literal lit, location_t locus)
: lit (std::move (lit)), locus (locus),
- node_id (Analysis::Mappings::get ().get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ()),
+ has_minus (false)
+ {}
+
+ LiteralPattern (Literal lit, location_t locus, bool has_minus)
+ : lit (std::move (lit)), locus (locus),
+ node_id (Analysis::Mappings::get ().get_next_node_id ()),
+ has_minus (has_minus)
{}
LiteralPattern (std::string val, Literal::LitType type, location_t locus,
PrimitiveCoreType type_hint)
: lit (Literal (std::move (val), type, type_hint)), locus (locus),
- node_id (Analysis::Mappings::get ().get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ()),
+ has_minus (false)
+ {}
+
+ LiteralPattern (std::string val, Literal::LitType type, location_t locus,
+ PrimitiveCoreType type_hint, bool has_minus)
+ : lit (Literal (std::move (val), type, type_hint)), locus (locus),
+ node_id (Analysis::Mappings::get ().get_next_node_id ()),
+ has_minus (has_minus)
{}
location_t get_locus () const override final { return locus; }
+ bool get_has_minus () const { return has_minus; }
+
void accept_vis (ASTVisitor &vis) override;
NodeId get_node_id () const override { return node_id; }
@@ -74,7 +93,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 +101,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 +126,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 +140,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 +156,16 @@ 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;
+ }
+
+ std::unique_ptr<Pattern> &get_subpattern_ptr ()
+ {
+ rust_assert (has_subpattern ());
+ return subpattern;
}
Identifier get_ident () const { return variable_ident; }
@@ -375,8 +399,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
{
@@ -520,6 +543,12 @@ public:
return *pattern;
}
+ std::unique_ptr<Pattern> &get_referenced_pattern_ptr ()
+ {
+ rust_assert (pattern != nullptr);
+ return pattern;
+ }
+
bool is_double_reference () const { return has_two_amps; }
bool get_is_mut () const { return is_mut; }
@@ -683,6 +712,12 @@ public:
return *tuple_pattern;
}
+ std::unique_ptr<Pattern> &get_index_pattern_ptr ()
+ {
+ rust_assert (tuple_pattern != nullptr);
+ return tuple_pattern;
+ }
+
ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; }
protected:
@@ -763,6 +798,12 @@ public:
return *ident_pattern;
}
+ std::unique_ptr<Pattern> &get_ident_pattern_ptr ()
+ {
+ rust_assert (ident_pattern != nullptr);
+ return ident_pattern;
+ }
+
ItemType get_item_type () const override final { return ItemType::IDENT_PAT; }
protected:
@@ -820,7 +861,7 @@ class StructPatternElements
// bool has_struct_pattern_fields;
std::vector<std::unique_ptr<StructPatternField>> fields;
- bool has_struct_pattern_etc;
+ bool has_rest_pattern;
std::vector<Attribute> struct_pattern_etc_attrs;
// StructPatternEtc etc;
@@ -836,29 +877,29 @@ public:
* no etc). */
bool is_empty () const
{
- return !has_struct_pattern_fields () && !has_struct_pattern_etc;
+ return !has_struct_pattern_fields () && !has_rest_pattern;
}
- bool has_etc () const { return has_struct_pattern_etc; }
+ bool has_rest () const { return has_rest_pattern; }
// Constructor for StructPatternElements with both (potentially)
StructPatternElements (
std::vector<std::unique_ptr<StructPatternField>> fields,
std::vector<Attribute> etc_attrs)
- : fields (std::move (fields)), has_struct_pattern_etc (true),
+ : fields (std::move (fields)), has_rest_pattern (true),
struct_pattern_etc_attrs (std::move (etc_attrs))
{}
// Constructor for StructPatternElements with no StructPatternEtc
StructPatternElements (
std::vector<std::unique_ptr<StructPatternField>> fields)
- : fields (std::move (fields)), has_struct_pattern_etc (false),
+ : fields (std::move (fields)), has_rest_pattern (false),
struct_pattern_etc_attrs ()
{}
// Copy constructor with vector clone
StructPatternElements (StructPatternElements const &other)
- : has_struct_pattern_etc (other.has_struct_pattern_etc),
+ : has_rest_pattern (other.has_rest_pattern),
struct_pattern_etc_attrs (other.struct_pattern_etc_attrs)
{
fields.reserve (other.fields.size ());
@@ -870,7 +911,7 @@ public:
StructPatternElements &operator= (StructPatternElements const &other)
{
struct_pattern_etc_attrs = other.struct_pattern_etc_attrs;
- has_struct_pattern_etc = other.has_struct_pattern_etc;
+ has_rest_pattern = other.has_rest_pattern;
fields.clear ();
fields.reserve (other.fields.size ());
@@ -915,7 +956,7 @@ public:
void strip_etc ()
{
- has_struct_pattern_etc = false;
+ has_rest_pattern = false;
struct_pattern_etc_attrs.clear ();
struct_pattern_etc_attrs.shrink_to_fit ();
}
@@ -950,7 +991,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;
@@ -977,49 +1018,62 @@ protected:
}
};
-// Base abstract class for patterns used in TupleStructPattern
-class TupleStructItems
+// Base abstract class for TupleStructItems, TuplePatternItems &
+// SlicePatternItems
+class PatternItems
{
public:
enum ItemType
{
- RANGE,
- NO_RANGE
+ NO_REST,
+ HAS_REST,
};
- virtual ~TupleStructItems () {}
+ virtual ~PatternItems () {}
// TODO: should this store location data?
// Unique pointer custom clone function
- std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const
+ std::unique_ptr<PatternItems> clone_pattern_items () const
{
- return std::unique_ptr<TupleStructItems> (clone_tuple_struct_items_impl ());
+ return std::unique_ptr<PatternItems> (clone_pattern_items_impl ());
}
virtual std::string as_string () const = 0;
-
+ virtual ItemType get_item_type () const = 0;
virtual void accept_vis (ASTVisitor &vis) = 0;
- virtual ItemType get_item_type () const = 0;
+protected:
+ virtual PatternItems *clone_pattern_items_impl () const = 0;
+};
+
+// Base abstract class for patterns used in TupleStructPattern
+class TupleStructItems : public PatternItems
+{
+public:
+ // Unique pointer custom clone function
+ std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const
+ {
+ return std::unique_ptr<TupleStructItems> (clone_pattern_items_impl ());
+ }
protected:
// pure virtual clone implementation
- virtual TupleStructItems *clone_tuple_struct_items_impl () const = 0;
+ virtual TupleStructItems *clone_pattern_items_impl () const = 0;
};
// Class for non-ranged tuple struct pattern patterns
-class TupleStructItemsNoRange : public TupleStructItems
+class TupleStructItemsNoRest : public TupleStructItems
{
std::vector<std::unique_ptr<Pattern>> patterns;
public:
- TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern>> patterns)
+ TupleStructItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
: patterns (std::move (patterns))
{}
// Copy constructor with vector clone
- TupleStructItemsNoRange (TupleStructItemsNoRange const &other)
+ TupleStructItemsNoRest (TupleStructItemsNoRest const &other)
{
patterns.reserve (other.patterns.size ());
for (const auto &e : other.patterns)
@@ -1027,7 +1081,7 @@ public:
}
// Overloaded assignment operator with vector clone
- TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other)
+ TupleStructItemsNoRest &operator= (TupleStructItemsNoRest const &other)
{
patterns.clear ();
patterns.reserve (other.patterns.size ());
@@ -1038,9 +1092,8 @@ public:
}
// move constructors
- TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default;
- TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other)
- = default;
+ TupleStructItemsNoRest (TupleStructItemsNoRest &&other) = default;
+ TupleStructItemsNoRest &operator= (TupleStructItemsNoRest &&other) = default;
std::string as_string () const override;
@@ -1053,32 +1106,32 @@ public:
return patterns;
}
- ItemType get_item_type () const override final { return ItemType::NO_RANGE; }
+ ItemType get_item_type () const override final { return ItemType::NO_REST; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- TupleStructItemsNoRange *clone_tuple_struct_items_impl () const override
+ TupleStructItemsNoRest *clone_pattern_items_impl () const override
{
- return new TupleStructItemsNoRange (*this);
+ return new TupleStructItemsNoRest (*this);
}
};
// Class for ranged tuple struct pattern patterns
-class TupleStructItemsRange : public TupleStructItems
+class TupleStructItemsHasRest : public TupleStructItems
{
std::vector<std::unique_ptr<Pattern>> lower_patterns;
std::vector<std::unique_ptr<Pattern>> upper_patterns;
public:
- TupleStructItemsRange (std::vector<std::unique_ptr<Pattern>> lower_patterns,
- std::vector<std::unique_ptr<Pattern>> upper_patterns)
+ TupleStructItemsHasRest (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
- TupleStructItemsRange (TupleStructItemsRange const &other)
+ TupleStructItemsHasRest (TupleStructItemsHasRest const &other)
{
lower_patterns.reserve (other.lower_patterns.size ());
for (const auto &e : other.lower_patterns)
@@ -1090,7 +1143,7 @@ public:
}
// Overloaded assignment operator to clone
- TupleStructItemsRange &operator= (TupleStructItemsRange const &other)
+ TupleStructItemsHasRest &operator= (TupleStructItemsHasRest const &other)
{
lower_patterns.clear ();
lower_patterns.reserve (other.lower_patterns.size ());
@@ -1106,8 +1159,9 @@ public:
}
// move constructors
- TupleStructItemsRange (TupleStructItemsRange &&other) = default;
- TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default;
+ TupleStructItemsHasRest (TupleStructItemsHasRest &&other) = default;
+ TupleStructItemsHasRest &operator= (TupleStructItemsHasRest &&other)
+ = default;
std::string as_string () const override;
@@ -1133,14 +1187,14 @@ public:
return upper_patterns;
}
- ItemType get_item_type () const override final { return ItemType::RANGE; }
+ ItemType get_item_type () const override final { return ItemType::HAS_REST; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- TupleStructItemsRange *clone_tuple_struct_items_impl () const override
+ TupleStructItemsHasRest *clone_pattern_items_impl () const override
{
- return new TupleStructItemsRange (*this);
+ return new TupleStructItemsHasRest (*this);
}
};
@@ -1223,49 +1277,32 @@ protected:
};
// Base abstract class representing TuplePattern patterns
-class TuplePatternItems
+class TuplePatternItems : public PatternItems
{
public:
- enum TuplePatternItemType
- {
- MULTIPLE,
- RANGED,
- };
-
- virtual ~TuplePatternItems () {}
-
- // TODO: should this store location data?
-
// Unique pointer custom clone function
std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const
{
- return std::unique_ptr<TuplePatternItems> (
- clone_tuple_pattern_items_impl ());
+ return std::unique_ptr<TuplePatternItems> (clone_pattern_items_impl ());
}
- virtual std::string as_string () const = 0;
-
- virtual void accept_vis (ASTVisitor &vis) = 0;
-
- virtual TuplePatternItemType get_pattern_type () const = 0;
-
protected:
// pure virtual clone implementation
- virtual TuplePatternItems *clone_tuple_pattern_items_impl () const = 0;
+ virtual TuplePatternItems *clone_pattern_items_impl () const = 0;
};
-// Class representing TuplePattern patterns where there are multiple patterns
-class TuplePatternItemsMultiple : public TuplePatternItems
+// Class representing TuplePattern patterns which contains no rest pattern
+class TuplePatternItemsNoRest : public TuplePatternItems
{
std::vector<std::unique_ptr<Pattern>> patterns;
public:
- TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern>> patterns)
+ TuplePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
: patterns (std::move (patterns))
{}
// Copy constructor with vector clone
- TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other)
+ TuplePatternItemsNoRest (TuplePatternItemsNoRest const &other)
{
patterns.reserve (other.patterns.size ());
for (const auto &e : other.patterns)
@@ -1273,7 +1310,7 @@ public:
}
// Overloaded assignment operator to vector clone
- TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other)
+ TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest const &other)
{
patterns.clear ();
patterns.reserve (other.patterns.size ());
@@ -1284,8 +1321,8 @@ public:
}
// move constructors
- TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default;
- TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other)
+ TuplePatternItemsNoRest (TuplePatternItemsNoRest &&other) = default;
+ TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest &&other)
= default;
std::string as_string () const override;
@@ -1299,35 +1336,33 @@ public:
return patterns;
}
- TuplePatternItemType get_pattern_type () const override
- {
- return TuplePatternItemType::MULTIPLE;
- }
+ ItemType get_item_type () const override { return ItemType::NO_REST; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- TuplePatternItemsMultiple *clone_tuple_pattern_items_impl () const override
+ TuplePatternItemsNoRest *clone_pattern_items_impl () const override
{
- return new TuplePatternItemsMultiple (*this);
+ return new TuplePatternItemsNoRest (*this);
}
};
-// Class representing TuplePattern patterns where there are a range of patterns
-class TuplePatternItemsRanged : public TuplePatternItems
+// Class representing TuplePattern patterns which contains a rest pattern
+class TuplePatternItemsHasRest : public TuplePatternItems
{
std::vector<std::unique_ptr<Pattern>> lower_patterns;
std::vector<std::unique_ptr<Pattern>> upper_patterns;
public:
- TuplePatternItemsRanged (std::vector<std::unique_ptr<Pattern>> lower_patterns,
- std::vector<std::unique_ptr<Pattern>> upper_patterns)
+ TuplePatternItemsHasRest (
+ 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
- TuplePatternItemsRanged (TuplePatternItemsRanged const &other)
+ TuplePatternItemsHasRest (TuplePatternItemsHasRest const &other)
{
lower_patterns.reserve (other.lower_patterns.size ());
for (const auto &e : other.lower_patterns)
@@ -1339,7 +1374,7 @@ public:
}
// Overloaded assignment operator to clone
- TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other)
+ TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest const &other)
{
lower_patterns.clear ();
lower_patterns.reserve (other.lower_patterns.size ());
@@ -1355,8 +1390,8 @@ public:
}
// move constructors
- TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default;
- TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other)
+ TuplePatternItemsHasRest (TuplePatternItemsHasRest &&other) = default;
+ TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest &&other)
= default;
std::string as_string () const override;
@@ -1383,17 +1418,14 @@ public:
return upper_patterns;
}
- TuplePatternItemType get_pattern_type () const override
- {
- return TuplePatternItemType::RANGED;
- }
+ ItemType get_item_type () const override { return ItemType::HAS_REST; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- TuplePatternItemsRanged *clone_tuple_pattern_items_impl () const override
+ TuplePatternItemsHasRest *clone_pattern_items_impl () const override
{
- return new TuplePatternItemsRanged (*this);
+ return new TuplePatternItemsHasRest (*this);
}
};
@@ -1510,6 +1542,12 @@ public:
return *pattern_in_parens;
}
+ std::unique_ptr<Pattern> &get_pattern_in_parens_ptr ()
+ {
+ rust_assert (pattern_in_parens != nullptr);
+ return pattern_in_parens;
+ }
+
NodeId get_node_id () const override { return node_id; }
Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Grouped; }
@@ -1523,41 +1561,194 @@ protected:
}
};
+// Base abstract class representing patterns in a SlicePattern
+class SlicePatternItems : public PatternItems
+{
+public:
+ // Unique pointer custom clone function
+ std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const
+ {
+ return std::unique_ptr<SlicePatternItems> (clone_pattern_items_impl ());
+ }
+
+protected:
+ // pure virtual clone implementation
+ virtual SlicePatternItems *clone_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;
+ }
+
+ ItemType get_item_type () const override { return ItemType::NO_REST; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ SlicePatternItemsNoRest *clone_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;
+ }
+
+ ItemType get_item_type () const override { return ItemType::HAS_REST; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ SlicePatternItemsHasRest *clone_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 +1761,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-stmt.h b/gcc/rust/ast/rust-stmt.h
index f843a79..5fb00ef 100644
--- a/gcc/rust/ast/rust-stmt.h
+++ b/gcc/rust/ast/rust-stmt.h
@@ -201,6 +201,12 @@ public:
return *variables_pattern;
}
+ std::unique_ptr<Pattern> &get_pattern_ptr ()
+ {
+ rust_assert (variables_pattern != nullptr);
+ return variables_pattern;
+ }
+
Type &get_type ()
{
rust_assert (has_type ());
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 20e0232..38a3474 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)
@@ -158,7 +177,6 @@ public:
void accept_vis (ASTVisitor &vis) override;
- // TODO: mutable getter seems kinda dodgy
std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
{
return type_param_bounds;
@@ -184,6 +202,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 +218,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)
@@ -226,7 +249,6 @@ public:
bool is_dyn () const { return has_dyn; }
- // TODO: mutable getter seems kinda dodgy
std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
{
return type_param_bounds;
@@ -251,6 +273,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 +331,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 +378,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,
@@ -429,7 +461,6 @@ public:
void accept_vis (ASTVisitor &vis) override;
- // TODO: mutable getter seems kinda dodgy
std::vector<std::unique_ptr<Type> > &get_elems () { return elems; }
const std::vector<std::unique_ptr<Type> > &get_elems () const
{
@@ -443,6 +474,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 +494,10 @@ protected:
{
return new NeverType (*this);
}
+ NeverType *reconstruct_impl () const override
+ {
+ return new NeverType (locus);
+ }
public:
NeverType (location_t locus) : locus (locus) {}
@@ -529,6 +568,15 @@ public:
return *type;
}
+ std::unique_ptr<TypeNoBounds> &get_type_pointed_to_ptr ()
+ {
+ rust_assert (type != nullptr);
+ 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,13 +584,17 @@ 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
class ReferenceType : public TypeNoBounds
{
// bool has_lifetime; // TODO: handle in lifetime or something?
- Lifetime lifetime;
+ tl::optional<Lifetime> lifetime;
bool has_mut;
std::unique_ptr<TypeNoBounds> type;
@@ -553,11 +605,12 @@ public:
bool is_mut () const { return has_mut; }
// Returns whether the reference has a lifetime.
- bool has_lifetime () const { return !lifetime.is_error (); }
+ bool has_lifetime () const { return lifetime.has_value (); }
// Constructor
ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds,
- location_t locus, Lifetime lifetime = Lifetime::elided ())
+ location_t locus,
+ tl::optional<Lifetime> lifetime = Lifetime::elided ())
: lifetime (std::move (lifetime)), has_mut (is_mut),
type (std::move (type_no_bounds)), locus (locus)
{}
@@ -596,12 +649,22 @@ public:
return *type;
}
+ std::unique_ptr<TypeNoBounds> &get_type_referenced_ptr ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
bool get_has_mut () const { return has_mut; }
- Lifetime &get_lifetime () { return lifetime; }
+ Lifetime &get_lifetime () { return lifetime.value (); }
+ const Lifetime &get_lifetime () const { return lifetime.value (); }
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 */
@@ -609,33 +672,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;
}
@@ -657,13 +729,22 @@ public:
return *elem_type;
}
+ std::unique_ptr<Type> &get_elem_type_ptr ()
+ {
+ rust_assert (elem_type != nullptr);
+ return elem_type;
+ }
+
// 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 */
@@ -671,6 +752,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
@@ -717,13 +804,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
@@ -734,13 +828,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) {}
@@ -899,7 +1001,7 @@ public:
return_type (std::move (type)), locus (locus)
{
if (!variadic_attrs.empty ())
- is_variadic = true;
+ _is_variadic = true;
}
// Copy constructor with clone
@@ -957,11 +1059,29 @@ public:
return *return_type;
}
+ std::unique_ptr<TypeNoBounds> &get_return_type_ptr ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; }
+ BareFunctionType *reconstruct_impl () const override
+ {
+ std::unique_ptr<TypeNoBounds> ret_type = nullptr;
+ if (return_type != nullptr)
+ ret_type = return_type->reconstruct ();
+
+ return new BareFunctionType (
+ for_lifetimes, function_qualifiers, params,
+ /* FIXME: Should params be reconstruct() as well? */
+ _is_variadic, variadic_attrs, std::move (ret_type), 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);
@@ -978,13 +1098,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 22498bc..b7143a8 100644
--- a/gcc/rust/backend/rust-compile-asm.cc
+++ b/gcc/rust/backend/rust-compile-asm.cc
@@ -1,5 +1,7 @@
#include "rust-compile-asm.h"
#include "rust-compile-expr.h"
+#include "rust-system.h"
+
namespace Rust {
namespace Compile {
@@ -72,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;
}
@@ -141,5 +180,57 @@ CompileAsm::asm_construct_label_tree (HIR::InlineAsm &expr)
return NULL_TREE;
}
+CompileLlvmAsm::CompileLlvmAsm (Context *ctx) : HIRCompileBase (ctx) {}
+
+tree
+CompileLlvmAsm::construct_operands (std::vector<HIR::LlvmOperand> operands)
+{
+ tree head = NULL_TREE;
+ for (auto &operand : operands)
+ {
+ tree t = CompileExpr::Compile (*operand.expr, this->ctx);
+ auto name = build_string (operand.constraint.size () + 1,
+ operand.constraint.c_str ());
+ head = chainon (head,
+ build_tree_list (build_tree_list (NULL_TREE, name), t));
+ }
+ return head;
+}
+
+tree
+CompileLlvmAsm::construct_clobbers (std::vector<AST::TupleClobber> clobbers)
+{
+ tree head = NULL_TREE;
+ for (auto &clobber : clobbers)
+ {
+ auto name
+ = build_string (clobber.symbol.size () + 1, clobber.symbol.c_str ());
+ head = chainon (head, build_tree_list (NULL_TREE, name));
+ }
+ return head;
+}
+
+tree
+CompileLlvmAsm::tree_codegen_asm (HIR::LlvmInlineAsm &expr)
+{
+ tree ret = make_node (ASM_EXPR);
+ TREE_TYPE (ret) = void_type_node;
+ SET_EXPR_LOCATION (ret, expr.get_locus ());
+ ASM_VOLATILE_P (ret) = expr.options.is_volatile;
+
+ std::stringstream ss;
+ for (const auto &template_str : expr.templates)
+ {
+ ss << template_str.symbol << "\n";
+ }
+
+ ASM_STRING (ret) = Backend::string_constant_expression (ss.str ());
+ ASM_INPUTS (ret) = construct_operands (expr.inputs);
+ ASM_OUTPUTS (ret) = construct_operands (expr.outputs);
+ ASM_CLOBBERS (ret) = construct_clobbers (expr.get_clobbers ());
+
+ return ret;
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-asm.h b/gcc/rust/backend/rust-compile-asm.h
index 4abd24e..22be94a 100644
--- a/gcc/rust/backend/rust-compile-asm.h
+++ b/gcc/rust/backend/rust-compile-asm.h
@@ -56,6 +56,20 @@ public:
tree tree_codegen_asm (HIR::InlineAsm &);
};
+
+class CompileLlvmAsm : private HIRCompileBase
+{
+private:
+ tree construct_operands (std::vector<HIR::LlvmOperand> operands);
+
+ tree construct_clobbers (std::vector<AST::TupleClobber>);
+
+public:
+ CompileLlvmAsm (Context *ctx);
+
+ tree tree_codegen_asm (HIR::LlvmInlineAsm &);
+};
+
} // namespace Compile
} // namespace Rust
#endif // RUST_COMPILE_ASM
diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc
index fdbca7f..d1db58e 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -32,6 +32,7 @@
#include "rust-type-util.h"
#include "rust-compile-implitem.h"
#include "rust-attribute-values.h"
+#include "rust-attributes.h"
#include "rust-immutable-name-resolution-context.h"
#include "fold-const.h"
@@ -251,25 +252,21 @@ void
HIRCompileBase::handle_link_section_attribute_on_fndecl (
tree fndecl, const AST::Attribute &attr)
{
- if (!attr.has_attr_input ())
+ auto msg_str = Analysis::Attributes::extract_string_literal (attr);
+
+ if (!msg_str.has_value ())
{
rust_error_at (attr.get_locus (),
- "%<link_section%> expects exactly one argment");
+ "malformed %<link_section%> attribute input");
return;
}
- rust_assert (attr.get_attr_input ().get_attr_input_type ()
- == AST::AttrInput::AttrInputType::LITERAL);
-
- auto &literal = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
- const auto &msg_str = literal.get_literal ().as_string ();
-
if (decl_section_name (fndecl))
{
rust_warning_at (attr.get_locus (), 0, "section name redefined");
}
- set_decl_section_name (fndecl, msg_str.c_str ());
+ set_decl_section_name (fndecl, msg_str->c_str ());
}
void
@@ -416,13 +413,10 @@ HIRCompileBase::handle_must_use_attribute_on_fndecl (tree fndecl,
if (attr.has_attr_input ())
{
- rust_assert (attr.get_attr_input ().get_attr_input_type ()
- == AST::AttrInput::AttrInputType::LITERAL);
+ auto msg_str = Analysis::Attributes::extract_string_literal (attr);
+ rust_assert (msg_str.has_value ());
- auto &literal
- = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
- const auto &msg_str = literal.get_literal ().as_string ();
- tree message = build_string (msg_str.size (), msg_str.c_str ());
+ tree message = build_string (msg_str->size (), msg_str->c_str ());
value = tree_cons (nodiscard, message, NULL_TREE);
}
@@ -549,7 +543,7 @@ HIRCompileBase::mark_addressable (tree exp, location_t locus)
}
tree
-HIRCompileBase::address_expression (tree expr, location_t location)
+HIRCompileBase::address_expression (tree expr, location_t location, tree ptrty)
{
if (expr == error_mark_node)
return error_mark_node;
@@ -557,7 +551,10 @@ HIRCompileBase::address_expression (tree expr, location_t location)
if (!mark_addressable (expr, location))
return error_mark_node;
- return build_fold_addr_expr_loc (location, expr);
+ if (ptrty == NULL || ptrty == error_mark_node)
+ ptrty = build_pointer_type (TREE_TYPE (expr));
+
+ return build_fold_addr_expr_with_type_loc (location, expr, ptrty);
}
tree
@@ -573,6 +570,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)
@@ -663,7 +679,8 @@ get_abi (const AST::AttrVec &outer_attrs,
tree
HIRCompileBase::compile_function (
- const std::string &fn_name, HIR::SelfParam &self_param,
+ bool is_root_item, const std::string &fn_name,
+ tl::optional<HIR::SelfParam> &self_param,
std::vector<HIR::FunctionParam> &function_params,
const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility,
AST::AttrVec &outer_attrs, location_t locus, HIR::BlockExpr *function_body,
@@ -673,8 +690,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;
+ 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);
@@ -683,14 +704,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);
@@ -710,24 +726,24 @@ HIRCompileBase::compile_function (
// setup the params
TyTy::BaseType *tyret = fntype->get_return_type ();
std::vector<Bvariable *> param_vars;
- if (!self_param.is_error ())
+ if (self_param)
{
rust_assert (fntype->is_method ());
TyTy::BaseType *self_tyty_lookup = fntype->get_self_type ();
tree self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup);
Bvariable *compiled_self_param
- = CompileSelfParam::compile (ctx, fndecl, self_param, self_type,
- self_param.get_locus ());
+ = CompileSelfParam::compile (ctx, fndecl, self_param.value (),
+ self_type, self_param->get_locus ());
param_vars.push_back (compiled_self_param);
- ctx->insert_var_decl (self_param.get_mappings ().get_hirid (),
+ ctx->insert_var_decl (self_param->get_mappings ().get_hirid (),
compiled_self_param);
}
// offset from + 1 for the TyTy::FnType being used when this is a method to
// skip over Self on the FnType
- bool is_method = !self_param.is_error ();
+ bool is_method = self_param.has_value ();
size_t i = is_method ? 1 : 0;
for (auto &referenced_param : function_params)
{
@@ -808,11 +824,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 4b4f8b0..3bf26af 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -29,7 +29,8 @@ class HIRCompileBase
public:
virtual ~HIRCompileBase () {}
- static tree address_expression (tree expr, location_t locus);
+ static tree address_expression (tree expr, location_t locus,
+ tree ptrty = NULL_TREE);
static tree compile_constant_expr (
Context *ctx, HirId coercion_id, TyTy::BaseType *resolved_type,
@@ -37,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) {}
@@ -52,7 +56,7 @@ protected:
TyTy::BaseType *expected, location_t lvalue_locus,
location_t rvalue_locus);
- tree coerce_to_dyn_object (tree compiled_ref, const TyTy::BaseType *actual,
+ tree coerce_to_dyn_object (tree compiled_ref, TyTy::BaseType *actual,
const TyTy::DynamicObjectType *ty,
location_t locus);
@@ -102,7 +106,8 @@ protected:
HIR::Expr &const_value_expr, location_t locus,
location_t expr_locus);
- tree compile_function (const std::string &fn_name, HIR::SelfParam &self_param,
+ tree compile_function (bool is_root_item, const std::string &fn_name,
+ tl::optional<HIR::SelfParam> &self_param,
std::vector<HIR::FunctionParam> &function_params,
const HIR::FunctionQualifiers &qualifiers,
HIR::Visibility &visibility, AST::AttrVec &outer_attrs,
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 37e3980..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 {}
@@ -100,6 +103,8 @@ public:
void visit (HIR::AwaitExpr &) override {}
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)
@@ -137,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 {}
@@ -182,6 +193,9 @@ public:
void visit (HIR::AwaitExpr &) override {}
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..e98bbc2 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -34,6 +34,10 @@ namespace Compile {
struct fncontext
{
+ fncontext (tree fndecl, ::Bvariable *ret_addr, TyTy::BaseType *retty)
+ : fndecl (fndecl), ret_addr (ret_addr), retty (retty)
+ {}
+
tree fndecl;
::Bvariable *ret_addr;
TyTy::BaseType *retty;
@@ -49,7 +53,7 @@ struct CustomDeriveInfo
class Context
{
public:
- Context ();
+ static Context *get ();
void setup_builtins ();
@@ -90,7 +94,6 @@ public:
return type;
}
- Resolver::Resolver *get_resolver () { return resolver; }
Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
Analysis::Mappings &get_mappings () { return mappings; }
@@ -155,7 +158,7 @@ public:
if (it == mono_fns.end ())
mono_fns[dId] = {};
- mono_fns[dId].push_back ({ref, fn});
+ mono_fns[dId].emplace_back (ref, fn);
}
void insert_closure_decl (const TyTy::ClosureType *ref, tree fn)
@@ -165,7 +168,7 @@ public:
if (it == mono_closure_fns.end ())
mono_closure_fns[dId] = {};
- mono_closure_fns[dId].push_back ({ref, fn});
+ mono_closure_fns[dId].emplace_back (ref, fn);
}
tree lookup_closure_decl (const TyTy::ClosureType *ref)
@@ -280,7 +283,7 @@ public:
void push_fn (tree fn, ::Bvariable *ret_addr, TyTy::BaseType *retty)
{
- fn_stack.push_back (fncontext{fn, ret_addr, retty});
+ fn_stack.emplace_back (fn, ret_addr, retty);
}
void pop_fn () { fn_stack.pop_back (); }
@@ -319,7 +322,13 @@ public:
void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); }
- Bvariable *peek_loop_context () { return loop_value_stack.back (); }
+ bool have_loop_context () const { return !loop_value_stack.empty (); }
+
+ Bvariable *peek_loop_context ()
+ {
+ rust_assert (!loop_value_stack.empty ());
+ return loop_value_stack.back ();
+ }
Bvariable *pop_loop_context ()
{
@@ -333,7 +342,11 @@ public:
loop_begin_labels.push_back (label);
}
- tree peek_loop_begin_label () { return loop_begin_labels.back (); }
+ tree peek_loop_begin_label ()
+ {
+ rust_assert (!loop_begin_labels.empty ());
+ return loop_begin_labels.back ();
+ }
tree pop_loop_begin_label ()
{
@@ -391,7 +404,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 e4ab9f0..9a9c315 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 {
@@ -170,7 +175,7 @@ CompileExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
}
auto receiver_tmp = NULL_TREE;
- auto receiver
+ Bvariable *receiver
= Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
TREE_TYPE (lhs), lhs, true,
expr.get_locus (), &receiver_tmp);
@@ -209,7 +214,7 @@ CompileExpr::visit (HIR::CompoundAssignmentExpr &expr)
if (ctx->in_fn () && !ctx->const_context_p ())
{
auto tmp = NULL_TREE;
- auto receiver
+ Bvariable *receiver
= Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
TREE_TYPE (lhs), lhs, true,
expr.get_locus (), &tmp);
@@ -368,6 +373,38 @@ CompileExpr::visit (HIR::InlineAsm &expr)
}
void
+CompileExpr::visit (HIR::LlvmInlineAsm &expr)
+{
+ CompileLlvmAsm asm_codegen (ctx);
+ ctx->add_statement (asm_codegen.tree_codegen_asm (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;
@@ -434,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);
@@ -464,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);
@@ -662,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))
{
@@ -669,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);
@@ -694,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);
@@ -736,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);
@@ -767,6 +828,10 @@ CompileExpr::visit (HIR::BreakExpr &expr)
{
tree compiled_expr = CompileExpr::Compile (expr.get_expr (), ctx);
+ translated = error_mark_node;
+ if (!ctx->have_loop_context ())
+ return;
+
Bvariable *loop_result_holder = ctx->peek_loop_context ();
tree result_reference
= Backend::var_expression (loop_result_holder,
@@ -780,25 +845,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 (),
@@ -839,29 +895,23 @@ CompileExpr::visit (HIR::BreakExpr &expr)
void
CompileExpr::visit (HIR::ContinueExpr &expr)
{
+ translated = error_mark_node;
+ if (!ctx->have_loop_context ())
+ return;
+
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 (),
@@ -905,7 +955,8 @@ CompileExpr::visit (HIR::BorrowExpr &expr)
&tyty))
return;
- translated = address_expression (main_expr, expr.get_locus ());
+ tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
+ translated = address_expression (main_expr, expr.get_locus (), expected_type);
}
void
@@ -1122,9 +1173,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);
@@ -1317,6 +1367,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
@@ -1583,37 +1655,39 @@ CompileExpr::compile_integer_literal (const HIR::LiteralExpr &expr,
const TyTy::BaseType *tyty)
{
rust_assert (expr.get_lit_type () == HIR::Literal::INT);
- const auto literal_value = expr.get_literal ();
-
+ const auto &literal_value = expr.get_literal ();
tree type = TyTyResolveCompile::compile (ctx, tyty);
+ std::string s = literal_value.as_string ();
+ s.erase (std::remove (s.begin (), s.end (), '_'), s.end ());
+
+ int base = 0;
mpz_t ival;
- if (mpz_init_set_str (ival, literal_value.as_string ().c_str (), 10) != 0)
+ if (mpz_init_set_str (ival, s.c_str (), base) != 0)
{
- rust_error_at (expr.get_locus (), "bad number in literal");
+ rust_error_at (expr.get_locus (), "failed to load number literal");
return error_mark_node;
}
+ if (expr.is_negative ())
+ mpz_neg (ival, ival);
- mpz_t type_min;
- mpz_t type_max;
+ mpz_t type_min, type_max;
mpz_init (type_min);
mpz_init (type_max);
get_type_static_bounds (type, type_min, type_max);
- if (expr.is_negative ())
- {
- mpz_neg (ival, ival);
- }
if (mpz_cmp (ival, type_min) < 0 || mpz_cmp (ival, type_max) > 0)
{
rust_error_at (expr.get_locus (),
"integer overflows the respective type %qs",
tyty->get_name ().c_str ());
+ mpz_clear (type_min);
+ mpz_clear (type_max);
+ mpz_clear (ival);
return error_mark_node;
}
tree result = wide_int_to_tree (type, wi::from_mpz (type, ival, true));
-
mpz_clear (type_min);
mpz_clear (type_max);
mpz_clear (ival);
@@ -1638,6 +1712,8 @@ CompileExpr::compile_float_literal (const HIR::LiteralExpr &expr,
rust_error_at (expr.get_locus (), "bad number in literal");
return error_mark_node;
}
+ if (expr.is_negative ())
+ mpfr_neg (fval, fval, MPFR_RNDN);
// taken from:
// see go/gofrontend/expressions.cc:check_float_type
@@ -1875,7 +1951,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
@@ -1935,13 +2012,25 @@ CompileExpr::array_copied_expr (location_t expr_locus,
return error_mark_node;
}
- ctx->push_const_context ();
- tree capacity_expr = CompileExpr::Compile (elems.get_num_copies_expr (), ctx);
- ctx->pop_const_context ();
+ auto capacity_ty = array_tyty.get_capacity ();
- if (!TREE_CONSTANT (capacity_expr))
+ // Check if capacity is a const type
+ if (capacity_ty->get_kind () != TyTy::TypeKind::CONST)
{
- rust_error_at (expr_locus, "non const num copies %qT", array_type);
+ rust_error_at (array_tyty.get_locus (),
+ "array capacity is not a const type");
+ return error_mark_node;
+ }
+
+ auto *capacity_const = capacity_ty->as_const_type ();
+
+ rust_assert (capacity_const->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Value);
+ auto &capacity_value = *static_cast<TyTy::ConstValueType *> (capacity_const);
+ auto cap_tree = capacity_value.get_value ();
+ if (error_operand_p (cap_tree) || !TREE_CONSTANT (cap_tree))
+ {
+ rust_error_at (expr_locus, "non const num copies %qT", cap_tree);
return error_mark_node;
}
@@ -1964,8 +2053,12 @@ CompileExpr::array_copied_expr (location_t expr_locus,
if (ctx->const_context_p ())
{
size_t idx = 0;
+
std::vector<unsigned long> indexes;
std::vector<tree> constructor;
+
+ indexes.reserve (len);
+ constructor.reserve (len);
for (unsigned HOST_WIDE_INT i = 0; i < len; i++)
{
constructor.push_back (translated_expr);
@@ -1990,9 +2083,9 @@ CompileExpr::array_copied_expr (location_t expr_locus,
ctx->push_block (init_block);
tree tmp;
- tree stmts = Backend::array_initializer (fndecl, init_block, array_type,
- capacity_expr, translated_expr,
- &tmp, expr_locus);
+ tree stmts
+ = Backend::array_initializer (fndecl, init_block, array_type, cap_tree,
+ translated_expr, &tmp, expr_locus);
ctx->add_statement (stmts);
tree block = ctx->pop_block ();
@@ -2020,7 +2113,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);
@@ -2139,11 +2233,10 @@ HIRCompileBase::resolve_unsized_dyn_adjustment (
tree rvalue = expression;
location_t rvalue_locus = locus;
- const TyTy::BaseType *actual = adjustment.get_actual ();
- const TyTy::BaseType *expected = adjustment.get_expected ();
+ auto actual = adjustment.get_actual ();
+ auto expected = adjustment.get_expected ();
- const TyTy::DynamicObjectType *dyn
- = static_cast<const TyTy::DynamicObjectType *> (expected);
+ const auto dyn = static_cast<const TyTy::DynamicObjectType *> (expected);
rust_debug ("resolve_unsized_dyn_adjustment actual={%s} dyn={%s}",
actual->debug_str ().c_str (), dyn->debug_str ().c_str ());
@@ -2462,23 +2555,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;
@@ -2558,15 +2640,15 @@ CompileExpr::generate_closure_fntype (HIR::ClosureExpr &expr,
TyTy::TypeBoundPredicateItem item = TyTy::TypeBoundPredicateItem::error ();
if (predicate.get_name ().compare ("FnOnce") == 0)
{
- item = predicate.lookup_associated_item ("call_once");
+ item = predicate.lookup_associated_item ("call_once").value ();
}
else if (predicate.get_name ().compare ("FnMut") == 0)
{
- item = predicate.lookup_associated_item ("call_mut");
+ item = predicate.lookup_associated_item ("call_mut").value ();
}
else if (predicate.get_name ().compare ("Fn") == 0)
{
- item = predicate.lookup_associated_item ("call");
+ item = predicate.lookup_associated_item ("call").value ();
}
else
{
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index dc78dee..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;
@@ -69,6 +71,8 @@ public:
void visit (HIR::RangeFromToInclExpr &expr) override;
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-extern.h b/gcc/rust/backend/rust-compile-extern.h
index bacd1c0..a78f9ee 100644
--- a/gcc/rust/backend/rust-compile-extern.h
+++ b/gcc/rust/backend/rust-compile-extern.h
@@ -24,6 +24,8 @@
#include "rust-compile-type.h"
#include "rust-diagnostics.h"
#include "rust-hir-full-decls.h"
+#include "rust-attributes.h"
+#include "rust-attribute-values.h"
namespace Rust {
namespace Compile {
@@ -34,16 +36,10 @@ class CompileExternItem : public HIRCompileBase,
public:
static tree compile (HIR::ExternalItem *item, Context *ctx,
TyTy::BaseType *concrete = nullptr,
- bool is_query_mode = false,
location_t ref_locus = UNDEF_LOCATION)
{
CompileExternItem compiler (ctx, concrete, ref_locus);
item->accept_vis (compiler);
-
- if (is_query_mode && compiler.reference == error_mark_node)
- rust_internal_error_at (ref_locus, "failed to compile extern item: %s",
- item->as_string ().c_str ());
-
return compiler.reference;
}
@@ -63,8 +59,7 @@ public:
rust_assert (ok);
std::string name = item.get_item_name ().as_string ();
- // FIXME this is assuming C ABI
- std::string asm_name = name;
+ GGC::Ident asm_name = get_link_name (item);
tree type = TyTyResolveCompile::compile (ctx, resolved_type);
bool is_external = true;
@@ -130,16 +125,7 @@ public:
tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
std::string ir_symbol_name = function.get_item_name ().as_string ();
- std::string asm_name = function.get_item_name ().as_string ();
- if (fntype->get_abi () == ABI::RUST)
- {
- // then we need to get the canonical path of it and mangle it
- auto canonical_path = ctx->get_mappings ().lookup_canonical_path (
- function.get_mappings ().get_nodeid ());
-
- ir_symbol_name = canonical_path->get () + fntype->subst_as_string ();
- asm_name = ctx->mangle_item (fntype, *canonical_path);
- }
+ GGC::Ident asm_name = get_link_name (function);
const unsigned int flags = Backend::function_is_declaration;
tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, asm_name,
@@ -164,6 +150,36 @@ private:
ref_locus (ref_locus)
{}
+ template <typename T> static GGC::Ident get_link_name (T &obj)
+ {
+ AST::Attribute *use_attr = nullptr;
+
+ for (auto &attr : obj.get_outer_attrs ())
+ {
+ if (attr.get_path ().as_string () == Values::Attributes::LINK_NAME)
+ {
+ // later attributes override earlier ones
+ // TODO: add warning -- should duplicate
+ // attributes be folded elsewhere?
+ use_attr = &attr;
+ }
+ }
+
+ if (use_attr)
+ {
+ auto link_name
+ = Analysis::Attributes::extract_string_literal (*use_attr);
+
+ if (!link_name.has_value ())
+ rust_error_at (use_attr->get_locus (),
+ "malformed %<link_name%> attribute input");
+ else
+ return *link_name;
+ }
+
+ return obj.get_item_name ();
+ }
+
TyTy::BaseType *concrete;
tree reference;
location_t ref_locus;
diff --git a/gcc/rust/backend/rust-compile-implitem.cc b/gcc/rust/backend/rust-compile-implitem.cc
index 71b3e8d..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,32 +85,21 @@ 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);
HIR::TraitFunctionDecl &function = func.get_decl ();
tree fndecl
- = compile_function (function.get_function_name ().as_string (),
+ = compile_function (false, function.get_function_name ().as_string (),
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-implitem.h b/gcc/rust/backend/rust-compile-implitem.h
index d2ef989..2d18dbf 100644
--- a/gcc/rust/backend/rust-compile-implitem.h
+++ b/gcc/rust/backend/rust-compile-implitem.h
@@ -30,16 +30,10 @@ class CompileInherentImplItem : public CompileItem
public:
static tree Compile (HIR::ImplItem *item, Context *ctx,
TyTy::BaseType *concrete = nullptr,
- bool is_query_mode = false,
location_t ref_locus = UNDEF_LOCATION)
{
CompileInherentImplItem compiler (ctx, concrete, ref_locus);
item->accept_vis (compiler);
-
- if (is_query_mode && compiler.reference == error_mark_node)
- rust_internal_error_at (ref_locus, "failed to compile impl item: %s",
- item->as_string ().c_str ());
-
return compiler.reference;
}
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 7ce9848..d908710 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,23 +103,22 @@ 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)
+ = nr_ctx.to_canonical_path (mappings.get_nodeid ());
+ if (constant_type->is<const TyTy::FnType> ())
{
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ if (concrete == nullptr)
+ return;
- 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 ();
+ rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
+ TyTy::FnType *concrete_fnty = static_cast<TyTy::FnType *> (concrete);
+
+ concrete_fnty->override_context ();
+ constant_type = expr_type = concrete_fnty->get_return_type ();
}
ctx->push_const_context ();
@@ -210,26 +197,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);
@@ -252,8 +224,12 @@ CompileItem::visit (HIR::Function &function)
if (function.get_qualifiers ().is_const ())
ctx->push_const_context ();
+ auto lookup_root_item = ctx->get_mappings ().lookup_hir_item (
+ function.get_mappings ().get_hirid ());
+ bool is_root_item = lookup_root_item.has_value ();
tree fndecl
- = compile_function (function.get_function_name ().as_string (),
+ = compile_function (is_root_item,
+ function.get_function_name ().as_string (),
function.get_self_param (),
function.get_function_params (),
function.get_qualifiers (), function.get_visibility (),
@@ -296,5 +272,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 eccb040..56baaab 100644
--- a/gcc/rust/backend/rust-compile-item.h
+++ b/gcc/rust/backend/rust-compile-item.h
@@ -35,10 +35,6 @@ public:
{
CompileItem compiler (ctx, concrete, ref_locus);
item->accept_vis (compiler);
-
- if (compiler.reference == error_mark_node)
- rust_debug ("failed to compile item: %s", item->as_string ().c_str ());
-
return compiler.reference;
}
@@ -48,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 {}
@@ -61,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..af5f453 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -22,6 +22,12 @@
#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"
+#include "tree.h"
namespace Rust {
namespace Compile {
@@ -81,6 +87,8 @@ CompilePatternCheckExpr::visit (HIR::LiteralPattern &pattern)
auto litexpr = std::make_unique<HIR::LiteralExpr> (
HIR::LiteralExpr (pattern.get_mappings (), pattern.get_literal (),
pattern.get_locus (), std::vector<AST::Attribute> ()));
+ if (pattern.get_has_minus ())
+ litexpr->set_negative ();
// Note: Floating point literals are currently accepted but will likely be
// forbidden in LiteralPatterns in a future version of Rust.
@@ -107,17 +115,21 @@ 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,
std::vector<AST::Attribute> ());
+ if (ref.get_has_minus ())
+ litexpr.set_negative ();
result = CompileExpr::Compile (litexpr, ctx);
}
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 +139,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);
@@ -150,13 +163,39 @@ CompilePatternCheckExpr::visit (HIR::RangePattern &pattern)
pattern.get_mappings (),
pattern.get_locus (), ctx);
+ rust_assert (
+ (TREE_CODE (upper) == REAL_CST && TREE_CODE (lower) == REAL_CST)
+ || (TREE_CODE (upper) == INTEGER_CST && TREE_CODE (lower) == INTEGER_CST));
+
+ bool error_E0579 = false;
+ if (TREE_CODE (upper) == REAL_CST)
+ {
+ const REAL_VALUE_TYPE *upper_r = TREE_REAL_CST_PTR (upper);
+ const REAL_VALUE_TYPE *lower_r = TREE_REAL_CST_PTR (lower);
+ if (real_compare (GE_EXPR, lower_r, upper_r))
+ error_E0579 = true;
+ }
+ else if (TREE_CODE (upper) == INTEGER_CST)
+ {
+ auto upper_wi = wi::to_wide (upper).to_shwi ();
+ auto lower_wi = wi::to_wide (lower).to_shwi ();
+ if (lower_wi >= upper_wi)
+ error_E0579 = true;
+ }
+
+ if (error_E0579)
+ rust_error_at (pattern.get_locus (), ErrorCode::E0579,
+ "lower range bound must be less than upper");
+
+ ComparisonOperator upper_cmp = pattern.is_inclusive_range ()
+ ? ComparisonOperator::LESS_OR_EQUAL
+ : ComparisonOperator::LESS_THAN;
tree check_lower
= Backend::comparison_expression (ComparisonOperator::GREATER_OR_EQUAL,
match_scrutinee_expr, lower,
pattern.get_locus ());
tree check_upper
- = Backend::comparison_expression (ComparisonOperator::LESS_OR_EQUAL,
- match_scrutinee_expr, upper,
+ = Backend::comparison_expression (upper_cmp, match_scrutinee_expr, upper,
pattern.get_locus ());
check_expr = Backend::arithmetic_or_logical_expression (
ArithmeticOrLogicalOperator::BITWISE_AND, check_lower, check_upper,
@@ -204,6 +243,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 +258,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 +267,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 +286,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 +295,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 +312,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 +325,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,36 +385,38 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern)
HIR::TupleStructItems &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case HIR::TupleStructItems::RANGED: {
- // TODO
- rust_unreachable ();
- }
- break;
+ case HIR::TupleStructItems::HAS_REST:
+ {
+ HIR::TupleStructItemsHasRest &items_has_rest
+ = static_cast<HIR::TupleStructItemsHasRest &> (items);
+ size_t num_patterns = items_has_rest.get_lower_patterns ().size ()
+ + items_has_rest.get_upper_patterns ().size ();
- 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 ());
+ // enums cases shouldn't reach here
+ rust_assert (num_patterns <= variant->num_fields ()
+ && (!adt->is_enum ()));
size_t tuple_field_index = 0;
- for (auto &pattern : items_no_range.get_patterns ())
+ for (auto &pattern : items_has_rest.get_lower_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,
+ 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 ());
+ }
+ tuple_field_index = variant->num_fields ()
+ - items_has_rest.get_upper_patterns ().size ();
+ for (auto &pattern : items_has_rest.get_upper_patterns ())
+ {
tree field_expr
- = Backend::struct_field_expression (variant_ref,
+ = 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 (
@@ -376,6 +425,64 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern)
}
}
break;
+
+ case HIR::TupleStructItems::NO_REST:
+ {
+ HIR::TupleStructItemsNoRest &items_no_range
+ = static_cast<HIR::TupleStructItemsNoRest &> (items);
+
+ rust_assert (items_no_range.get_patterns ().size ()
+ == variant->num_fields ());
+
+ if (adt->is_enum ())
+ {
+ 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 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 ());
+ }
+ }
+ 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;
+ }
}
}
@@ -386,15 +493,59 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern)
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::RANGED: {
- // TODO
- gcc_unreachable ();
+ case HIR::TuplePatternItems::HAS_REST:
+ {
+ auto &items
+ = static_cast<HIR::TuplePatternItemsHasRest &> (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: {
- auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
- pattern.get_items ());
+ case HIR::TuplePatternItems::NO_REST:
+ {
+ auto &items
+ = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ());
size_t tuple_field_index = 0;
for (auto &pat : items.get_patterns ())
@@ -414,6 +565,216 @@ 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);
+
+ // function ptr that points to either array_index_expression or
+ // slice_index_expression depending on the scrutinee's type
+ tree (*scrutinee_index_expr_func) (tree, tree, location_t) = nullptr;
+
+ switch (lookup->get_kind ())
+ {
+ case TyTy::TypeKind::ARRAY:
+ scrutinee_index_expr_func = Backend::array_index_expression;
+ 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)));
+ scrutinee_index_expr_func = Backend::slice_index_expression;
+ tree size_field
+ = Backend::struct_field_expression (match_scrutinee_expr, 1,
+ pattern.get_locus ());
+
+ // for slices, generate a dynamic size comparison expression tree
+ // because size checking is done at runtime.
+ switch (pattern.get_items ().get_item_type ())
+ {
+ case HIR::SlicePatternItems::ItemType::NO_REST:
+ {
+ auto &items = static_cast<HIR::SlicePatternItemsNoRest &> (
+ pattern.get_items ());
+ check_expr = Backend::comparison_expression (
+ ComparisonOperator::EQUAL, size_field,
+ build_int_cst (size_type_node, items.get_patterns ().size ()),
+ pattern.get_locus ());
+ }
+ break;
+ case HIR::SlicePatternItems::ItemType::HAS_REST:
+ {
+ auto &items = static_cast<HIR::SlicePatternItemsHasRest &> (
+ pattern.get_items ());
+ auto pattern_min_cap = items.get_lower_patterns ().size ()
+ + items.get_upper_patterns ().size ();
+ check_expr = Backend::comparison_expression (
+ ComparisonOperator::GREATER_OR_EQUAL, size_field,
+ build_int_cst (size_type_node, pattern_min_cap),
+ pattern.get_locus ());
+ }
+ break;
+ }
+ }
+ break;
+ default:
+ rust_unreachable ();
+ }
+
+ rust_assert (scrutinee_index_expr_func != nullptr);
+
+ // Generate tree to compare every element within array/slice
+ size_t element_index = 0;
+ switch (pattern.get_items ().get_item_type ())
+ {
+ case HIR::SlicePatternItems::ItemType::NO_REST:
+ {
+ auto &items
+ = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ());
+ for (auto &pattern_member : items.get_patterns ())
+ {
+ tree index_tree
+ = Backend::size_constant_expression (element_index++);
+ tree element_expr
+ = scrutinee_index_expr_func (match_scrutinee_expr, 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 HIR::SlicePatternItems::ItemType::HAS_REST:
+ {
+ auto &items
+ = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
+ for (auto &pattern_member : items.get_lower_patterns ())
+ {
+ tree index_tree
+ = Backend::size_constant_expression (element_index++);
+ tree element_expr
+ = scrutinee_index_expr_func (match_scrutinee_expr, 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 ());
+ }
+
+ // handle codegen for upper patterns differently for both types
+ switch (lookup->get_kind ())
+ {
+ case TyTy::TypeKind::ARRAY:
+ {
+ // for array type scrutinee, we can simply get the capacity as a
+ // const and calculate how many elements to skip
+ auto array_ty = static_cast<TyTy::ArrayType *> (lookup);
+ auto capacity_ty = array_ty->get_capacity ();
+
+ rust_assert (capacity_ty->get_kind () == TyTy::TypeKind::CONST);
+ auto *capacity_const = capacity_ty->as_const_type ();
+ rust_assert (capacity_const->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Value);
+ auto &capacity_value
+ = *static_cast<TyTy::ConstValueType *> (capacity_const);
+ auto cap_tree = capacity_value.get_value ();
+
+ rust_assert (!error_operand_p (cap_tree));
+
+ size_t cap_wi = (size_t) wi::to_wide (cap_tree).to_uhwi ();
+ element_index = cap_wi - items.get_upper_patterns ().size ();
+ for (auto &pattern_member : items.get_upper_patterns ())
+ {
+ tree index_tree
+ = Backend::size_constant_expression (element_index++);
+ tree element_expr
+ = scrutinee_index_expr_func (match_scrutinee_expr,
+ 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::REF:
+ {
+ // for slice type scrutinee, size is dyanamic, so number of
+ // elements to skip is calculated during runtime
+ tree slice_size
+ = Backend::struct_field_expression (match_scrutinee_expr, 1,
+ pattern.get_locus ());
+ tree upper_patterns_size = Backend::size_constant_expression (
+ items.get_upper_patterns ().size ());
+ tree index_tree = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::SUBTRACT, slice_size,
+ upper_patterns_size, pattern.get_locus ());
+ for (auto &pattern_member : items.get_upper_patterns ())
+ {
+ tree element_expr
+ = scrutinee_index_expr_func (match_scrutinee_expr,
+ 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 ());
+ index_tree = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::ADD, index_tree,
+ Backend::size_constant_expression (1),
+ pattern.get_locus ());
+ }
+ }
+ break;
+ default:
+ rust_unreachable ();
+ }
+ }
+ break;
+ }
+}
+
// setup the bindings
void
@@ -449,23 +810,54 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
HIR::TupleStructItems &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case HIR::TupleStructItems::RANGED: {
- // TODO
- rust_unreachable ();
+ case HIR::TupleStructItems::HAS_REST:
+ {
+ HIR::TupleStructItemsHasRest &items_has_rest
+ = static_cast<HIR::TupleStructItemsHasRest &> (items);
+ size_t num_patterns = items_has_rest.get_lower_patterns ().size ()
+ + items_has_rest.get_upper_patterns ().size ();
+
+ // enums cases shouldn't reach here
+ rust_assert (num_patterns <= variant->num_fields ()
+ && (!adt->is_enum ()));
+
+ size_t tuple_field_index = 0;
+ for (auto &pattern : items_has_rest.get_lower_patterns ())
+ {
+ tree binding
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pattern->get_locus ());
+
+ CompilePatternBindings::Compile (*pattern, binding, ctx);
+ }
+
+ tuple_field_index = variant->num_fields ()
+ - items_has_rest.get_upper_patterns ().size ();
+
+ for (auto &pattern : items_has_rest.get_upper_patterns ())
+ {
+ tree binding
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pattern->get_locus ());
+
+ CompilePatternBindings::Compile (*pattern, binding, ctx);
+ }
}
break;
- case HIR::TupleStructItems::MULTIPLE: {
- HIR::TupleStructItemsNoRange &items_no_range
- = static_cast<HIR::TupleStructItemsNoRange &> (items);
-
- rust_assert (items_no_range.get_patterns ().size ()
+ case HIR::TupleStructItems::NO_REST:
+ {
+ HIR::TupleStructItemsNoRest &items_no_rest
+ = static_cast<HIR::TupleStructItemsNoRest &> (items);
+ rust_assert (items_no_rest.get_patterns ().size ()
== variant->num_fields ());
if (adt->is_enum ())
{
size_t tuple_field_index = 0;
- for (auto &pattern : items_no_range.get_patterns ())
+ for (auto &pattern : items_no_rest.get_patterns ())
{
tree payload_accessor_union
= Backend::struct_field_expression (match_scrutinee_expr, 1,
@@ -487,12 +879,10 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
else
{
size_t tuple_field_index = 0;
- for (auto &pattern : items_no_range.get_patterns ())
+ for (auto &pattern : items_no_rest.get_patterns ())
{
- tree variant_accessor = match_scrutinee_expr;
-
tree binding
- = Backend::struct_field_expression (variant_accessor,
+ = Backend::struct_field_expression (match_scrutinee_expr,
tuple_field_index++,
pattern->get_locus ());
@@ -504,6 +894,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)
{
@@ -531,62 +986,23 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
rust_assert (ok);
}
- rust_assert (variant->get_variant_type ()
- == TyTy::VariantDef::VariantType::STRUCT);
+ rust_assert (
+ variant->get_variant_type () == TyTy::VariantDef::VariantType::STRUCT
+ || variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE);
auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
{
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 +1021,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,10 +1053,11 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern)
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::ItemType::RANGED: {
+ case HIR::TuplePatternItems::ItemType::HAS_REST:
+ {
size_t tuple_idx = 0;
auto &items
- = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
+ = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ());
auto &items_lower = items.get_lower_patterns ();
auto &items_upper = items.get_upper_patterns ();
@@ -674,10 +1097,11 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern)
return;
}
- case HIR::TuplePatternItems::ItemType::MULTIPLE: {
+ case HIR::TuplePatternItems::ItemType::NO_REST:
+ {
size_t tuple_idx = 0;
- auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
- pattern.get_items ());
+ auto &items
+ = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ());
for (auto &sub : items.get_patterns ())
{
@@ -695,12 +1119,156 @@ 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);
+
+ // function ptr that points to either array_index_expression or
+ // slice_index_expression depending on the scrutinee's type
+ tree (*scrutinee_index_expr_func) (tree, tree, location_t) = nullptr;
+
+ switch (lookup->get_kind ())
+ {
+ case TyTy::TypeKind::ARRAY:
+ scrutinee_index_expr_func = Backend::array_index_expression;
+ 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:
+ scrutinee_index_expr_func = Backend::slice_index_expression;
+ break;
+ default:
+ rust_unreachable ();
+ }
+
+ rust_assert (scrutinee_index_expr_func != nullptr);
+
+ size_t element_index = 0;
+
+ switch (pattern.get_items ().get_item_type ())
+ {
+ case HIR::SlicePatternItems::ItemType::NO_REST:
+ {
+ auto &items
+ = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ());
+ for (auto &pattern_member : items.get_patterns ())
+ {
+ tree index_tree
+ = Backend::size_constant_expression (element_index++);
+ tree element_expr
+ = scrutinee_index_expr_func (match_scrutinee_expr, index_tree,
+ pattern.get_locus ());
+ CompilePatternBindings::Compile (*pattern_member, element_expr,
+ ctx);
+ }
+ }
+ break;
+ case HIR::SlicePatternItems::ItemType::HAS_REST:
+ {
+ auto &items
+ = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
+ for (auto &pattern_member : items.get_lower_patterns ())
+ {
+ tree index_tree
+ = Backend::size_constant_expression (element_index++);
+ tree element_expr
+ = scrutinee_index_expr_func (match_scrutinee_expr, index_tree,
+ pattern.get_locus ());
+ CompilePatternBindings::Compile (*pattern_member, element_expr,
+ ctx);
+ }
+
+ // handle codegen for upper patterns differently for both types
+ switch (lookup->get_kind ())
+ {
+ case TyTy::TypeKind::ARRAY:
+ {
+ auto array_ty = static_cast<TyTy::ArrayType *> (lookup);
+ auto capacity_ty = array_ty->get_capacity ();
+
+ rust_assert (capacity_ty->get_kind () == TyTy::TypeKind::CONST);
+ auto *capacity_const = capacity_ty->as_const_type ();
+ rust_assert (capacity_const->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Value);
+ auto &capacity_value
+ = *static_cast<TyTy::ConstValueType *> (capacity_const);
+ auto cap_tree = capacity_value.get_value ();
+
+ rust_assert (!error_operand_p (cap_tree));
+
+ size_t cap_wi = (size_t) wi::to_wide (cap_tree).to_uhwi ();
+ element_index = cap_wi - items.get_upper_patterns ().size ();
+ for (auto &pattern_member : items.get_upper_patterns ())
+ {
+ tree index_tree
+ = Backend::size_constant_expression (element_index++);
+ tree element_expr
+ = scrutinee_index_expr_func (match_scrutinee_expr,
+ 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:
+ {
+ tree slice_size
+ = Backend::struct_field_expression (match_scrutinee_expr, 1,
+ pattern.get_locus ());
+ tree upper_patterns_size = Backend::size_constant_expression (
+ items.get_upper_patterns ().size ());
+ tree index_tree = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::SUBTRACT, slice_size,
+ upper_patterns_size, pattern.get_locus ());
+ for (auto &pattern_member : items.get_upper_patterns ())
+ {
+ tree element_expr
+ = scrutinee_index_expr_func (match_scrutinee_expr,
+ index_tree,
+ pattern.get_locus ());
+ CompilePatternBindings::Compile (*pattern_member,
+ element_expr, ctx);
+ index_tree = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::ADD, index_tree,
+ Backend::size_constant_expression (1),
+ pattern.get_locus ());
+ }
+ }
+ break;
+ default:
+ rust_unreachable ();
+ }
+ }
+ break;
+ }
+}
+
//
void
@@ -710,6 +1278,11 @@ CompilePatternLet::visit (HIR::IdentifierPattern &pattern)
rust_assert (
ctx->lookup_var_decl (pattern.get_mappings ().get_hirid (), &var));
+ if (pattern.get_is_ref ())
+ {
+ init_expr = address_expression (init_expr, EXPR_LOCATION (init_expr));
+ }
+
auto fnctx = ctx->peek_fn ();
if (ty->is_unit ())
{
@@ -721,6 +1294,11 @@ CompilePatternLet::visit (HIR::IdentifierPattern &pattern)
}
else
{
+ if (pattern.has_subpattern ())
+ {
+ CompilePatternLet::Compile (&pattern.get_subpattern (), init_expr, ty,
+ rval_locus, ctx);
+ }
auto s = Backend::init_statement (fnctx.fndecl, var, init_expr);
ctx->add_statement (s);
}
@@ -744,21 +1322,65 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern)
{
rust_assert (pattern.has_tuple_pattern_items ());
- tree tuple_type = TyTyResolveCompile::compile (ctx, ty);
+ bool has_by_ref = false;
+ auto check_refs
+ = [] (const std::vector<std::unique_ptr<HIR::Pattern>> &patterns) {
+ for (const auto &sub : patterns)
+ {
+ switch (sub->get_pattern_type ())
+ {
+ case HIR::Pattern::PatternType::IDENTIFIER:
+ {
+ auto id = static_cast<HIR::IdentifierPattern *> (sub.get ());
+ if (id->get_is_ref ())
+ return true;
+ break;
+ }
+ case HIR::Pattern::PatternType::REFERENCE:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+ };
+ switch (pattern.get_items ().get_item_type ())
+ {
+ case HIR::TuplePatternItems::ItemType::NO_REST:
+ {
+ auto &items
+ = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ());
+ has_by_ref = check_refs (items.get_patterns ());
+ break;
+ }
+ case HIR::TuplePatternItems::ItemType::HAS_REST:
+ {
+ auto &items
+ = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ());
+ has_by_ref = check_refs (items.get_lower_patterns ())
+ || check_refs (items.get_upper_patterns ());
+ break;
+ }
+ default:
+ break;
+ }
+
+ tree rhs_tuple_type = TYPE_MAIN_VARIANT (TREE_TYPE (init_expr));
tree init_stmt;
Bvariable *tmp_var
= Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
- tuple_type, init_expr, false,
+ rhs_tuple_type, init_expr, has_by_ref,
pattern.get_locus (), &init_stmt);
tree access_expr = Backend::var_expression (tmp_var, pattern.get_locus ());
ctx->add_statement (init_stmt);
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::ItemType::RANGED: {
+ case HIR::TuplePatternItems::ItemType::HAS_REST:
+ {
size_t tuple_idx = 0;
auto &items
- = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
+ = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ());
auto &items_lower = items.get_lower_patterns ();
auto &items_upper = items.get_upper_patterns ();
@@ -799,10 +1421,11 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern)
return;
}
- case HIR::TuplePatternItems::ItemType::MULTIPLE: {
+ case HIR::TuplePatternItems::ItemType::NO_REST:
+ {
size_t tuple_idx = 0;
- auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
- pattern.get_items ());
+ auto &items
+ = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ());
for (auto &sub : items.get_patterns ())
{
@@ -821,7 +1444,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 115dd04..5f30662 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -97,15 +97,20 @@ ResolvePathRef::attempt_constructor_expression_lookup (
// this can only be for discriminant variants the others are built up
// using call-expr or struct-init
- rust_assert (variant->get_variant_type ()
- == TyTy::VariantDef::VariantType::NUM);
+ if (variant->get_variant_type () != TyTy::VariantDef::VariantType::NUM)
+ {
+ rust_error_at (expr_locus, "variant expected constructor call");
+ return error_mark_node;
+ }
// we need the actual gcc type
tree compiled_adt_type = TyTyResolveCompile::compile (ctx, adt);
// make the ctor for the union
HIR::Expr &discrim_expr = variant->get_discriminant ();
+ ctx->push_const_context ();
tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
+ ctx->pop_const_context ();
tree folded_discrim_expr = fold_expr (discrim_expr_node);
tree qualifier = folded_discrim_expr;
@@ -127,10 +132,8 @@ ResolvePathRef::resolve_with_node_id (
tl::optional<HirId> hid
= ctx->get_mappings ().lookup_node_to_hir (resolved_node_id);
if (!hid.has_value ())
- {
- rust_error_at (expr_locus, "reverse call path lookup failure");
- return error_mark_node;
- }
+ return error_mark_node;
+
auto ref = hid.value ();
// might be a constant
@@ -184,18 +187,32 @@ ResolvePathRef::resolve_with_node_id (
}
}
+ // possibly a const expr value
+ if (lookup->get_kind () == TyTy::TypeKind::CONST)
+ {
+ auto d = lookup->destructure ();
+ rust_assert (d->get_kind () == TyTy::TypeKind::CONST);
+ auto c = d->as_const_type ();
+ rust_assert (c->const_kind () == TyTy::BaseConstType::ConstKind::Value);
+ auto val = static_cast<TyTy::ConstValueType *> (c);
+ return val->get_value ();
+ }
+
// 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;
- }
+ TREE_USED (resolved_item) = 1;
return resolved_item;
}
@@ -207,36 +224,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
@@ -259,10 +264,10 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
HIR::ExternalItem *resolved_extern_item = hir_extern_item->first;
if (!lookup->has_substitutions_defined ())
return CompileExternItem::compile (resolved_extern_item, ctx, nullptr,
- true, expr_locus);
+ expr_locus);
else
return CompileExternItem::compile (resolved_extern_item, ctx, lookup,
- true, expr_locus);
+ expr_locus);
}
else
{
@@ -284,10 +289,10 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
{
if (!lookup->has_substitutions_defined ())
return CompileInherentImplItem::Compile (resolved_item->first, ctx,
- nullptr, true, expr_locus);
+ nullptr, expr_locus);
else
return CompileInherentImplItem::Compile (resolved_item->first, ctx,
- lookup, true, expr_locus);
+ lookup, expr_locus);
}
else if (auto trait_item
= ctx->get_mappings ().lookup_hir_trait_item (ref))
@@ -334,11 +339,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
@@ -370,11 +382,10 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
if (!lookup->has_substitutions_defined ())
return CompileInherentImplItem::Compile (impl_item, ctx,
- nullptr, true,
- expr_locus);
+ nullptr, expr_locus);
else
return CompileInherentImplItem::Compile (impl_item, ctx, lookup,
- true, expr_locus);
+ expr_locus);
}
}
}
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..5b00afa 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;
}
@@ -129,7 +136,31 @@ TyTyResolveCompile::visit (const TyTy::InferType &type)
}
void
-TyTyResolveCompile::visit (const TyTy::ParamType &)
+TyTyResolveCompile::visit (const TyTy::ParamType &type)
+{
+ translated = error_mark_node;
+}
+
+void
+TyTyResolveCompile::visit (const TyTy::ConstParamType &type)
+{
+ translated = error_mark_node;
+}
+
+void
+TyTyResolveCompile::visit (const TyTy::ConstValueType &type)
+{
+ translated = error_mark_node;
+}
+
+void
+TyTyResolveCompile::visit (const TyTy::ConstInferType &type)
+{
+ translated = error_mark_node;
+}
+
+void
+TyTyResolveCompile::visit (const TyTy::ConstErrorType &type)
{
translated = error_mark_node;
}
@@ -173,8 +204,8 @@ TyTyResolveCompile::visit (const TyTy::ClosureType &type)
// this should be based on the closure move-ability
tree decl_type = TyTyResolveCompile::compile (ctx, lookup);
tree capture_type = build_reference_type (decl_type);
- fields.push_back (Backend::typed_identifier (mappings_name, capture_type,
- type.get_ident ().locus));
+ fields.emplace_back (mappings_name, capture_type,
+ type.get_ident ().locus);
}
tree type_record = Backend::struct_type (fields);
@@ -189,7 +220,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;
@@ -204,8 +235,7 @@ TyTyResolveCompile::visit (const TyTy::FnType &type)
auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode);
location_t return_type_locus
= ctx->get_mappings ().lookup_location (hir_type->get_ref ());
- results.push_back (
- Backend::typed_identifier ("_", ret, return_type_locus));
+ results.emplace_back ("_", ret, return_type_locus);
}
for (auto &param_pair : type.get_params ())
@@ -214,11 +244,10 @@ TyTyResolveCompile::visit (const TyTy::FnType &type)
auto compiled_param_type
= TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode);
- auto compiled_param = Backend::typed_identifier (
- param_pair.get_pattern ().as_string (), compiled_param_type,
- ctx->get_mappings ().lookup_location (param_tyty->get_ref ()));
-
- parameters.push_back (compiled_param);
+ parameters.emplace_back (param_pair.get_pattern ().as_string (),
+ compiled_param_type,
+ ctx->get_mappings ().lookup_location (
+ param_tyty->get_ref ()));
}
if (!type.is_variadic ())
@@ -264,10 +293,9 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type)
tree compiled_field_ty
= TyTyResolveCompile::compile (ctx, field->get_field_type ());
- Backend::typed_identifier f (field->get_name (), compiled_field_ty,
- ctx->get_mappings ().lookup_location (
- type.get_ty_ref ()));
- fields.push_back (std::move (f));
+ fields.emplace_back (field->get_name (), compiled_field_ty,
+ ctx->get_mappings ().lookup_location (
+ type.get_ty_ref ()));
}
type_record = type.is_union () ? Backend::union_type (fields, false)
@@ -344,10 +372,9 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type)
== TyTy::VariantDef::VariantType::TUPLE)
field_name = "__" + field->get_name ();
- Backend::typed_identifier f (
- field_name, compiled_field_ty,
- ctx->get_mappings ().lookup_location (type.get_ty_ref ()));
- fields.push_back (std::move (f));
+ fields.emplace_back (field_name, compiled_field_ty,
+ ctx->get_mappings ().lookup_location (
+ type.get_ty_ref ()));
}
tree variant_record = Backend::struct_type (fields);
@@ -369,10 +396,9 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type)
TyTy::VariantDef *variant = type.get_variants ().at (i++);
std::string implicit_variant_name = variant->get_identifier ();
- Backend::typed_identifier f (implicit_variant_name, variant_record,
- ctx->get_mappings ().lookup_location (
- type.get_ty_ref ()));
- enum_fields.push_back (std::move (f));
+ enum_fields.emplace_back (implicit_variant_name, variant_record,
+ ctx->get_mappings ().lookup_location (
+ type.get_ty_ref ()));
}
//
@@ -447,14 +473,13 @@ TyTyResolveCompile::visit (const TyTy::TupleType &type)
// this, rather than simply emitting the integer, is that this
// approach makes it simpler to use a C-only debugger, or
// GDB's C mode, when debugging Rust.
- Backend::typed_identifier f ("__" + std::to_string (i), compiled_field_ty,
- ctx->get_mappings ().lookup_location (
- type.get_ty_ref ()));
- fields.push_back (std::move (f));
+ fields.emplace_back ("__" + std::to_string (i), compiled_field_ty,
+ ctx->get_mappings ().lookup_location (
+ type.get_ty_ref ()));
}
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 +488,29 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type)
{
tree element_type
= TyTyResolveCompile::compile (ctx, type.get_element_type ());
+ auto const_capacity = type.get_capacity ();
- ctx->push_const_context ();
+ // Check if capacity is a const type
+ if (const_capacity->get_kind () != TyTy::TypeKind::CONST)
+ {
+ rust_error_at (type.get_locus (), "array capacity is not a const type");
+ translated = error_mark_node;
+ return;
+ }
- 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 ());
+ auto *capacity_const = const_capacity->as_const_type ();
- ctx->pop_const_context ();
+ rust_assert (capacity_const->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Value);
+ auto &capacity_value = *static_cast<TyTy::ConstValueType *> (capacity_const);
+ auto folded_capacity_expr = capacity_value.get_value ();
- 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 +783,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
@@ -768,17 +798,15 @@ TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type)
tree uint = Backend::integer_type (true, Backend::get_pointer_size ());
tree uintptr_ty = build_pointer_type (uint);
- Backend::typed_identifier f ("pointer", uintptr_ty,
- ctx->get_mappings ().lookup_location (
- type.get_ty_ref ()));
- fields.push_back (std::move (f));
+ fields.emplace_back ("pointer", uintptr_ty,
+ ctx->get_mappings ().lookup_location (
+ type.get_ty_ref ()));
tree vtable_size = build_int_cst (size_type_node, items.size ());
tree vtable_type = Backend::array_type (uintptr_ty, vtable_size);
- Backend::typed_identifier vtf ("vtable", vtable_type,
- ctx->get_mappings ().lookup_location (
- type.get_ty_ref ()));
- fields.push_back (std::move (vtf));
+ fields.emplace_back ("vtable", vtable_type,
+ ctx->get_mappings ().lookup_location (
+ type.get_ty_ref ()));
tree record = Backend::struct_type (fields);
RS_DST_FLAG (record) = 1;
diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h
index 7ebc4a6..d6c3259 100644
--- a/gcc/rust/backend/rust-compile-type.h
+++ b/gcc/rust/backend/rust-compile-type.h
@@ -50,6 +50,10 @@ public:
void visit (const TyTy::ReferenceType &) override;
void visit (const TyTy::PointerType &) override;
void visit (const TyTy::ParamType &) override;
+ void visit (const TyTy::ConstParamType &) override;
+ void visit (const TyTy::ConstValueType &) override;
+ void visit (const TyTy::ConstInferType &) override;
+ void visit (const TyTy::ConstErrorType &) 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..1f306ad 100644
--- a/gcc/rust/backend/rust-compile-var-decl.h
+++ b/gcc/rust/backend/rust-compile-var-decl.h
@@ -64,30 +64,79 @@ public:
ctx->insert_var_decl (stmt_id, var);
vars.push_back (var);
+
+ if (pattern.has_subpattern ())
+ {
+ auto subpattern_vars
+ = CompileVarDecl::compile (fndecl, translated_type,
+ &pattern.get_subpattern (), ctx);
+ vars.insert (vars.end (), subpattern_vars.begin (),
+ subpattern_vars.end ());
+ }
}
void visit (HIR::TuplePattern &pattern) override
{
+ rust_assert (TREE_CODE (translated_type) == RECORD_TYPE);
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::ItemType::MULTIPLE: {
- rust_assert (TREE_CODE (translated_type) == RECORD_TYPE);
- auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
+ case HIR::TuplePatternItems::ItemType::NO_REST:
+ {
+ auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> (
+ pattern.get_items ());
+
+ tree field = TYPE_FIELDS (translated_type);
+ for (auto &sub : items_no_rest.get_patterns ())
+ {
+ gcc_assert (field != NULL_TREE);
+ tree sub_ty = TREE_TYPE (field);
+ CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx);
+ field = DECL_CHAIN (field);
+ }
+ }
+ break;
+
+ case HIR::TuplePatternItems::ItemType::HAS_REST:
+ {
+ auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> (
pattern.get_items ());
- size_t offs = 0;
- for (auto &sub : items.get_patterns ())
+ // count total fields in translated_type
+ size_t total_fields = 0;
+ for (tree t = TYPE_FIELDS (translated_type); t; t = DECL_CHAIN (t))
+ {
+ total_fields++;
+ }
+
+ // process lower patterns
+ tree field = TYPE_FIELDS (translated_type);
+ for (auto &sub : items_has_rest.get_lower_patterns ())
+ {
+ gcc_assert (field != NULL_TREE);
+ tree sub_ty = TREE_TYPE (field);
+ CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx);
+ field = DECL_CHAIN (field);
+ }
+
+ // process upper patterns
+ if (!items_has_rest.get_upper_patterns ().empty ())
{
- tree sub_ty = error_mark_node;
- tree field = TYPE_FIELDS (translated_type);
- for (size_t i = 0; i < offs; i++)
+ size_t upper_start
+ = total_fields - items_has_rest.get_upper_patterns ().size ();
+ field = TYPE_FIELDS (translated_type);
+ for (size_t i = 0; i < upper_start; i++)
{
field = DECL_CHAIN (field);
gcc_assert (field != NULL_TREE);
}
- sub_ty = TREE_TYPE (field);
- CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx);
- offs++;
+
+ for (auto &sub : items_has_rest.get_upper_patterns ())
+ {
+ gcc_assert (field != NULL_TREE);
+ tree sub_ty = TREE_TYPE (field);
+ CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx);
+ field = DECL_CHAIN (field);
+ }
}
}
break;
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 7b00066..40f16e4 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -183,8 +183,7 @@ HIRCompileBase::coercion_site1 (tree rvalue, TyTy::BaseType *rval,
}
tree
-HIRCompileBase::coerce_to_dyn_object (tree compiled_ref,
- const TyTy::BaseType *actual,
+HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, TyTy::BaseType *actual,
const TyTy::DynamicObjectType *ty,
location_t locus)
{
@@ -201,9 +200,7 @@ HIRCompileBase::coerce_to_dyn_object (tree compiled_ref,
// __trait_object_ptr
// [list of function ptrs]
- std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>>
- probed_bounds_for_receiver = Resolver::TypeBoundsProbe::Probe (actual);
-
+ auto probed_bounds_for_receiver = Resolver::TypeBoundsProbe::Probe (actual);
tree address_of_compiled_ref = null_pointer_node;
if (!actual->is_unit ())
address_of_compiled_ref = address_expression (compiled_ref, locus);
@@ -241,12 +238,13 @@ HIRCompileBase::compute_address_for_trait_item (
&receiver_bounds,
const TyTy::BaseType *receiver, const TyTy::BaseType *root, location_t locus)
{
- TyTy::TypeBoundPredicateItem predicate_item
+ tl::optional<TyTy::TypeBoundPredicateItem> predicate_item
= predicate->lookup_associated_item (ref->get_identifier ());
- rust_assert (!predicate_item.is_error ());
+ rust_assert (predicate_item.has_value ());
// This is the expected end type
- TyTy::BaseType *trait_item_type = predicate_item.get_tyty_for_receiver (root);
+ TyTy::BaseType *trait_item_type
+ = predicate_item->get_tyty_for_receiver (root);
rust_assert (trait_item_type->get_kind () == TyTy::TypeKind::FNDEF);
TyTy::FnType *trait_item_fntype
= static_cast<TyTy::FnType *> (trait_item_type);
@@ -338,7 +336,7 @@ HIRCompileBase::compute_address_for_trait_item (
}
return CompileInherentImplItem::Compile (associated_function, ctx,
- lookup_fntype, true, locus);
+ lookup_fntype, locus);
}
// we can only compile trait-items with a body
diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc
index dc2d6b1..e32ba3a 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
{
@@ -109,12 +101,54 @@ struct constexpr_global_ctx
auto_vec<tree, 16> heap_vars;
/* Cleanups that need to be evaluated at the end of CLEANUP_POINT_EXPR. */
vec<tree> *cleanups;
+ /* If non-null, only allow modification of existing values of the variables
+ in this set. Set by modifiable_tracker, below. */
+ hash_set<tree> *modifiable;
/* Number of heap VAR_DECL deallocations. */
unsigned heap_dealloc_count;
/* Constructor. */
constexpr_global_ctx ()
: constexpr_ops_count (0), cleanups (NULL), heap_dealloc_count (0)
{}
+
+ tree get_value (tree t)
+ {
+ if (tree *p = values.get (t))
+ if (*p != void_node)
+ return *p;
+ return NULL_TREE;
+ }
+ tree *get_value_ptr (tree t, bool initializing)
+ {
+ if (modifiable && !modifiable->contains (t))
+ return nullptr;
+ if (tree *p = values.get (t))
+ {
+ if (*p != void_node)
+ return p;
+ else if (initializing)
+ {
+ *p = NULL_TREE;
+ return p;
+ }
+ }
+ return nullptr;
+ }
+ void put_value (tree t, tree v)
+ {
+ bool already_in_map = values.put (t, v);
+ if (!already_in_map && modifiable)
+ modifiable->add (t);
+ }
+ void destroy_value (tree t)
+ {
+ if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL
+ || TREE_CODE (t) == RESULT_DECL)
+ values.put (t, void_node);
+ else
+ values.remove (t);
+ }
+ void clear_value (tree t) { values.remove (t); }
};
/* In constexpr.cc */
@@ -463,60 +497,62 @@ 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);
+static tree decl_really_constant_value (tree decl, bool unshare_p /*= true*/);
+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 *jump_target);
-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 *, tree *jump_target);
-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 *, tree *);
-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 *, tree *jump_target);
-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_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p);
+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_loop_expr (const constexpr_ctx *ctx, tree t, 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,
+ 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_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_unary_expression (const constexpr_ctx *ctx, tree t,
+ bool /*lval*/, bool *non_constant_p,
+ bool *overflow_p, tree *jump_target);
+static bool eval_check_shift_p (location_t loc, const constexpr_ctx *ctx,
+ enum tree_code code, tree type, tree lhs,
+ tree rhs);
+static tree fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
+ tree lhs, tree rhs,
+ bool *non_constant_p,
+ bool *overflow_p, tree *jump_target);
+static tree maybe_fold_addr_pointer_plus (tree t);
/* Variables and functions to manage constexpr call expansion context.
These do not need to be marked for PCH or GC. */
@@ -578,8 +614,9 @@ fold_expr (tree expr)
bool non_constant_p = false;
bool overflow_p = false;
+ tree jump_target = NULL_TREE;
tree folded = eval_constant_expression (&ctx, expr, false, &non_constant_p,
- &overflow_p);
+ &overflow_p, &jump_target);
rust_assert (folded != NULL_TREE);
// more logic here to possibly port
@@ -605,13 +642,13 @@ same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2)
otherwise return NULL_TREE. */
static tree
-union_active_member (const constexpr_ctx *ctx, tree t)
+union_active_member (const constexpr_ctx *ctx, tree t, tree *jump_target)
{
constexpr_ctx new_ctx = *ctx;
new_ctx.quiet = true;
bool non_constant_p = false, overflow_p = false;
tree ctor = eval_constant_expression (&new_ctx, t, false, &non_constant_p,
- &overflow_p);
+ &overflow_p, jump_target);
if (TREE_CODE (ctor) == CONSTRUCTOR && CONSTRUCTOR_NELTS (ctor) == 1
&& CONSTRUCTOR_ELT (ctor, 0)->index
&& TREE_CODE (CONSTRUCTOR_ELT (ctor, 0)->index) == FIELD_DECL)
@@ -623,7 +660,8 @@ union_active_member (const constexpr_ctx *ctx, tree t)
static tree
fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type,
- tree op, unsigned HOST_WIDE_INT off, bool *empty_base)
+ tree op, unsigned HOST_WIDE_INT off, bool *empty_base,
+ tree *jump_target)
{
tree optype = TREE_TYPE (op);
unsigned HOST_WIDE_INT const_nunits;
@@ -670,7 +708,8 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type,
tree index = size_int (idx + tree_to_uhwi (min_val));
op = build4_loc (loc, ARRAY_REF, TREE_TYPE (optype), op, index,
NULL_TREE, NULL_TREE);
- return fold_indirect_ref_1 (ctx, loc, type, op, rem, empty_base);
+ return fold_indirect_ref_1 (ctx, loc, type, op, rem, empty_base,
+ jump_target);
}
}
/* ((foo *)&struct_with_foo_field)[x] => COMPONENT_REF */
@@ -679,7 +718,7 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type,
{
if (TREE_CODE (optype) == UNION_TYPE)
/* For unions prefer the currently active member. */
- if (tree field = union_active_member (ctx, op))
+ if (tree field = union_active_member (ctx, op, jump_target))
{
unsigned HOST_WIDE_INT el_sz
= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field)));
@@ -688,7 +727,7 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type,
tree cop = build3 (COMPONENT_REF, TREE_TYPE (field), op, field,
NULL_TREE);
if (tree ret = fold_indirect_ref_1 (ctx, loc, type, cop, off,
- empty_base))
+ empty_base, jump_target))
return ret;
}
}
@@ -707,8 +746,9 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type,
{
tree cop = build3 (COMPONENT_REF, TREE_TYPE (field), op, field,
NULL_TREE);
- if (tree ret = fold_indirect_ref_1 (ctx, loc, type, cop,
- off - upos, empty_base))
+ if (tree ret
+ = fold_indirect_ref_1 (ctx, loc, type, cop, off - upos,
+ empty_base, jump_target))
return ret;
}
}
@@ -737,7 +777,7 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type,
static tree
rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type,
- tree op0, bool *empty_base)
+ tree op0, bool *empty_base, tree *jump_target)
{
tree sub = op0;
tree subtype;
@@ -796,7 +836,8 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type,
tree off = integer_zero_node;
canonicalize_obj_off (op, off);
gcc_assert (integer_zerop (off));
- return fold_indirect_ref_1 (ctx, loc, type, op, 0, empty_base);
+ return fold_indirect_ref_1 (ctx, loc, type, op, 0, empty_base,
+ jump_target);
}
}
else if (TREE_CODE (sub) == POINTER_PLUS_EXPR
@@ -811,7 +852,7 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type,
tree obj = TREE_OPERAND (op00, 0);
canonicalize_obj_off (obj, off);
return fold_indirect_ref_1 (ctx, loc, type, obj, tree_to_uhwi (off),
- empty_base);
+ empty_base, jump_target);
}
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
@@ -820,8 +861,8 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type,
{
tree type_domain;
tree min_val = size_zero_node;
- tree newsub
- = rs_fold_indirect_ref (ctx, loc, TREE_TYPE (subtype), sub, NULL);
+ tree newsub = rs_fold_indirect_ref (ctx, loc, TREE_TYPE (subtype), sub,
+ NULL, jump_target);
if (newsub)
sub = newsub;
else
@@ -840,7 +881,7 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type,
static tree
rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p)
+ bool *non_constant_p, bool *overflow_p, tree *jump_target)
{
tree orig_op0 = TREE_OPERAND (t, 0);
bool empty_base = false;
@@ -858,13 +899,13 @@ rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval,
/* First try to simplify it directly. */
tree r = rs_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t),
- orig_op0, &empty_base);
+ orig_op0, &empty_base, jump_target);
if (!r)
{
/* If that didn't work, evaluate the operand first. */
- tree op0
- = eval_constant_expression (ctx, orig_op0,
- /*lval*/ false, non_constant_p, overflow_p);
+ tree op0 = eval_constant_expression (ctx, orig_op0,
+ /*lval*/ false, non_constant_p,
+ overflow_p, jump_target);
/* Don't VERIFY_CONSTANT here. */
if (*non_constant_p)
return t;
@@ -878,7 +919,7 @@ rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval,
}
r = rs_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t), op0,
- &empty_base);
+ &empty_base, jump_target);
if (r == NULL_TREE)
{
/* We couldn't fold to a constant value. Make sure it's not
@@ -907,7 +948,8 @@ rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval,
}
}
- r = eval_constant_expression (ctx, r, lval, non_constant_p, overflow_p);
+ r = eval_constant_expression (ctx, r, lval, non_constant_p, overflow_p,
+ jump_target);
if (*non_constant_p)
return t;
@@ -933,17 +975,17 @@ rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval,
static tree
eval_logical_expression (const constexpr_ctx *ctx, tree t, tree bailout_value,
tree continue_value, bool lval, bool *non_constant_p,
- bool *overflow_p)
+ bool *overflow_p, tree *jump_target)
{
tree r;
tree lhs = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
- non_constant_p, overflow_p);
+ non_constant_p, overflow_p, jump_target);
VERIFY_CONSTANT (lhs);
if (tree_int_cst_equal (lhs, bailout_value))
return lhs;
gcc_assert (tree_int_cst_equal (lhs, continue_value));
r = eval_constant_expression (ctx, TREE_OPERAND (t, 1), lval, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
VERIFY_CONSTANT (r);
return r;
}
@@ -1235,7 +1277,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);
@@ -1258,19 +1301,20 @@ get_or_insert_ctor_field (tree ctor, tree index, int pos_hint = -1)
static tree
eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t,
- bool *non_constant_p, bool *overflow_p)
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target)
{
- tree arg1
- = eval_constant_expression (ctx, TREE_OPERAND (t, 0),
- /*lval*/ false, non_constant_p, overflow_p);
+ tree arg1 = eval_constant_expression (ctx, TREE_OPERAND (t, 0),
+ /*lval*/ false, non_constant_p,
+ overflow_p, jump_target);
VERIFY_CONSTANT (arg1);
- tree arg2
- = eval_constant_expression (ctx, TREE_OPERAND (t, 1),
- /*lval*/ false, non_constant_p, overflow_p);
+ tree arg2 = eval_constant_expression (ctx, TREE_OPERAND (t, 1),
+ /*lval*/ false, non_constant_p,
+ overflow_p, jump_target);
VERIFY_CONSTANT (arg2);
- tree arg3
- = eval_constant_expression (ctx, TREE_OPERAND (t, 2),
- /*lval*/ false, non_constant_p, overflow_p);
+ tree arg3 = eval_constant_expression (ctx, TREE_OPERAND (t, 2),
+ /*lval*/ false, non_constant_p,
+ overflow_p, jump_target);
VERIFY_CONSTANT (arg3);
location_t loc = EXPR_LOCATION (t);
tree type = TREE_TYPE (t);
@@ -1295,7 +1339,7 @@ eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t,
static tree
eval_bare_aggregate (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p)
+ bool *non_constant_p, bool *overflow_p, tree *jump_target)
{
vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t);
bool changed = false;
@@ -1346,8 +1390,9 @@ eval_bare_aggregate (const constexpr_ctx *ctx, tree t, bool lval,
the active union member now so that we can later detect and diagnose
if its initializer attempts to activate another member. */
get_or_insert_ctor_field (ctx->ctor, index);
- tree elt = eval_constant_expression (&new_ctx, value, lval,
- non_constant_p, overflow_p);
+ tree elt
+ = eval_constant_expression (&new_ctx, value, lval, non_constant_p,
+ overflow_p, jump_target);
/* Don't VERIFY_CONSTANT here. */
if (ctx->quiet && *non_constant_p)
break;
@@ -1416,7 +1461,8 @@ eval_bare_aggregate (const constexpr_ctx *ctx, tree t, bool lval,
static tree
cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p)
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target)
{
int i;
tree args[3];
@@ -1424,8 +1470,9 @@ cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t, bool lval,
for (i = 0; i < 3; i++)
{
- args[i] = eval_constant_expression (ctx, TREE_OPERAND (t, i), lval,
- non_constant_p, overflow_p);
+ args[i]
+ = eval_constant_expression (ctx, TREE_OPERAND (t, i), lval,
+ non_constant_p, overflow_p, jump_target);
VERIFY_CONSTANT (args[i]);
}
@@ -1568,10 +1615,10 @@ 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,
+ tree *jump_target);
// forked from gcc/cp/constexpr.cc cxx_eval_array_reference
@@ -1580,11 +1627,11 @@ eval_and_check_array_index (const constexpr_ctx *ctx, tree t,
static tree
eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p)
+ bool *non_constant_p, bool *overflow_p, tree *jump_target)
{
tree oldary = TREE_OPERAND (t, 0);
- tree ary
- = eval_constant_expression (ctx, oldary, lval, non_constant_p, overflow_p);
+ tree ary = eval_constant_expression (ctx, oldary, lval, non_constant_p,
+ overflow_p, jump_target);
if (*non_constant_p)
return t;
if (!lval && TREE_CODE (ary) == VIEW_CONVERT_EXPR
@@ -1593,8 +1640,8 @@ eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval,
ary = TREE_OPERAND (ary, 0);
tree oldidx = TREE_OPERAND (t, 1);
- tree index
- = eval_and_check_array_index (ctx, t, lval, non_constant_p, overflow_p);
+ tree index = eval_and_check_array_index (ctx, t, lval, non_constant_p,
+ overflow_p, jump_target);
if (*non_constant_p)
return t;
@@ -1696,7 +1743,8 @@ eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval,
new_ctx.ctor = build_constructor (elem_type, NULL);
ctx = &new_ctx;
}
- t = eval_constant_expression (ctx, val, lval, non_constant_p, overflow_p);
+ t = eval_constant_expression (ctx, val, lval, non_constant_p, overflow_p,
+ jump_target);
if (!SCALAR_TYPE_P (elem_type) && t != ctx->ctor)
free_constructor (ctx->ctor);
return t;
@@ -1709,7 +1757,8 @@ eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval,
static tree
eval_component_reference (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p)
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target)
{
unsigned HOST_WIDE_INT i;
tree field;
@@ -1717,7 +1766,7 @@ eval_component_reference (const constexpr_ctx *ctx, tree t, bool lval,
tree part = TREE_OPERAND (t, 1);
tree orig_whole = TREE_OPERAND (t, 0);
tree whole = eval_constant_expression (ctx, orig_whole, lval, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
if (INDIRECT_REF_P (whole) && integer_zerop (TREE_OPERAND (whole, 0)))
{
if (!ctx->quiet)
@@ -1806,8 +1855,8 @@ eval_component_reference (const constexpr_ctx *ctx, tree t, bool lval,
// back to handle this to assign suitable value to value before sending it in
// eval_constant_expression below
// value = build_value_init (TREE_TYPE (t), tf_warning_or_error);
- return eval_constant_expression (ctx, value, lval, non_constant_p,
- overflow_p);
+ return eval_constant_expression (ctx, value, lval, non_constant_p, overflow_p,
+ jump_target);
}
/* Subroutine of cxx_eval_statement_list. Determine whether the statement
@@ -1866,7 +1915,7 @@ label_matches (const constexpr_ctx *ctx, tree *jump_target, tree stmt)
static tree
eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
bool *non_constant_p, bool *overflow_p,
- tree *jump_target /* = NULL */)
+ tree *jump_target)
{
if (jump_target && *jump_target)
{
@@ -1901,6 +1950,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))
@@ -1934,33 +1986,44 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
{
r = DECL_VALUE_EXPR (t);
return eval_constant_expression (ctx, r, lval, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
}
- /* 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)
- return t;
- else if (t == ctx->object)
- return ctx->ctor;
- if (VAR_P (t))
- if (tree *p = ctx->global->values.get (t))
- if (*p != NULL_TREE)
- {
- r = *p;
- break;
- }
+ /* 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)
+ return t;
+ else if (t == ctx->object)
+ return ctx->ctor;
+ if (VAR_P (t))
+ {
+ if (tree v = ctx->global->get_value (t))
+ {
+ r = v;
+ break;
+ }
+ }
+ if (COMPLETE_TYPE_P (TREE_TYPE (t))
+ && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/ false))
+ {
+ /* If the class is empty, we aren't actually loading anything. */
+ r = build_constructor (TREE_TYPE (t), NULL);
+ TREE_CONSTANT (r) = true;
+ }
+ else if (ctx->strict)
+ r = decl_really_constant_value (t, /*unshare_p=*/false);
+ else
r = decl_constant_value (t, /*unshare_p=*/false);
- if (TREE_CODE (r) == TARGET_EXPR
- && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
- r = TARGET_EXPR_INITIAL (r);
- if (DECL_P (r))
- {
+ if (TREE_CODE (r) == TARGET_EXPR
+ && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
+ r = TARGET_EXPR_INITIAL (r);
+ if (DECL_P (r) && !(VAR_P (t) && TYPE_REF_P (TREE_TYPE (t))))
+ {
+ if (!ctx->quiet)
non_const_var_error (loc, r);
- return r;
- }
- }
+ *non_constant_p = true;
+ }
break;
case PARM_DECL:
@@ -2026,7 +2089,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
case LTGT_EXPR:
case RANGE_EXPR:
case COMPLEX_EXPR:
- r = eval_binary_expression (ctx, t, lval, non_constant_p, overflow_p);
+ r = eval_binary_expression (ctx, t, lval, non_constant_p, overflow_p,
+ jump_target);
break;
/* fold can introduce non-IF versions of these; still treat them as
@@ -2035,17 +2099,18 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
case TRUTH_ANDIF_EXPR:
r = eval_logical_expression (ctx, t, boolean_false_node,
boolean_true_node, lval, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
break;
case TRUTH_OR_EXPR:
case TRUTH_ORIF_EXPR:
r = eval_logical_expression (ctx, t, boolean_true_node,
boolean_false_node, lval, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
break;
- case TARGET_EXPR: {
+ case TARGET_EXPR:
+ {
tree type = TREE_TYPE (t);
if (!literal_type_p (type))
@@ -2090,7 +2155,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
/* Pass false for 'lval' because this indicates
initialization of a temporary. */
r = eval_constant_expression (ctx, TREE_OPERAND (t, 1), false,
- non_constant_p, overflow_p);
+ non_constant_p, overflow_p, jump_target);
if (*non_constant_p)
break;
/* Adjust the type of the result to the type of the temporary. */
@@ -2107,13 +2172,14 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
break;
case CALL_EXPR:
- r = eval_call_expression (ctx, t, lval, non_constant_p, overflow_p);
+ r = eval_call_expression (ctx, t, lval, non_constant_p, overflow_p,
+ jump_target);
break;
case RETURN_EXPR:
if (TREE_OPERAND (t, 0) != NULL_TREE)
r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
- non_constant_p, overflow_p);
+ non_constant_p, overflow_p, jump_target);
/* FALLTHRU */
case BREAK_STMT:
case CONTINUE_STMT:
@@ -2129,7 +2195,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)))
@@ -2145,7 +2212,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
if (tree init = DECL_INITIAL (r))
{
init = eval_constant_expression (ctx, init, false, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
/* Don't share a CONSTRUCTOR that might be changed. */
init = unshare_constructor (init);
/* Remember that a constant object's constructor has already
@@ -2166,12 +2233,13 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
constant without its operand being, and vice versa. */
case MEM_REF:
case INDIRECT_REF:
- r = rs_eval_indirect_ref (ctx, t, lval, non_constant_p, overflow_p);
+ r = rs_eval_indirect_ref (ctx, t, lval, non_constant_p, overflow_p,
+ jump_target);
break;
case VEC_PERM_EXPR:
- r = cxx_eval_trinary_expression (ctx, t, lval, non_constant_p,
- overflow_p);
+ r = cxx_eval_trinary_expression (ctx, t, lval, non_constant_p, overflow_p,
+ jump_target);
break;
case PAREN_EXPR:
@@ -2179,11 +2247,12 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
/* A PAREN_EXPR resulting from __builtin_assoc_barrier has no effect in
constant expressions since it's unaffected by -fassociative-math. */
r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
- non_constant_p, overflow_p);
+ non_constant_p, overflow_p, jump_target);
break;
case MODIFY_EXPR:
- r = eval_store_expression (ctx, t, false, non_constant_p, overflow_p);
+ r = eval_store_expression (ctx, t, false, non_constant_p, overflow_p,
+ jump_target);
break;
case STATEMENT_LIST:
@@ -2199,12 +2268,14 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
case OBJ_TYPE_REF:
/* Virtual function lookup. We don't need to do anything fancy. */
return eval_constant_expression (ctx, OBJ_TYPE_REF_EXPR (t), lval,
- non_constant_p, overflow_p);
+ non_constant_p, overflow_p, jump_target);
- 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);
+ cond
+ = eval_constant_expression (ctx, cond, /*lval*/ false, non_constant_p,
+ overflow_p, jump_target);
VERIFY_CONSTANT (cond);
if (integer_nonzerop (cond))
*jump_target = t;
@@ -2234,7 +2305,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
else
{
r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), false,
- non_constant_p, overflow_p);
+ non_constant_p, overflow_p,
+ jump_target);
if (*non_constant_p)
break;
ctx->global->values.put (t, r);
@@ -2243,11 +2315,12 @@ 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,
- overflow_p);
+ overflow_p, jump_target);
/* Don't VERIFY_CONSTANT here. */
if (*non_constant_p)
return t;
@@ -2261,7 +2334,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. */
@@ -2291,7 +2365,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
if (lval)
{
r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
- non_constant_p, overflow_p);
+ non_constant_p, overflow_p,
+ jump_target);
if (r == error_mark_node)
;
else if (r == TREE_OPERAND (t, 0))
@@ -2310,7 +2385,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
case FIXED_CONVERT_EXPR:
- r = eval_unary_expression (ctx, t, lval, non_constant_p, overflow_p);
+ r = eval_unary_expression (ctx, t, lval, non_constant_p, overflow_p,
+ jump_target);
break;
case LOOP_EXPR:
@@ -2325,7 +2401,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
break;
case ARRAY_REF:
- r = eval_array_reference (ctx, t, lval, non_constant_p, overflow_p);
+ r = eval_array_reference (ctx, t, lval, non_constant_p, overflow_p,
+ jump_target);
break;
case COMPONENT_REF:
@@ -2339,11 +2416,13 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
*non_constant_p = true;
return t;
}
- r = eval_component_reference (ctx, t, lval, non_constant_p, overflow_p);
+ r = eval_component_reference (ctx, t, lval, non_constant_p, overflow_p,
+ jump_target);
break;
case BIT_FIELD_REF:
- r = eval_bit_field_ref (ctx, t, lval, non_constant_p, overflow_p);
+ r = eval_bit_field_ref (ctx, t, lval, non_constant_p, overflow_p,
+ jump_target);
break;
case COND_EXPR:
@@ -2388,7 +2467,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
case VEC_COND_EXPR:
r = eval_vector_conditional_expression (ctx, t, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
break;
case TRY_CATCH_EXPR:
@@ -2401,7 +2480,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;
@@ -2413,7 +2493,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
/* Evaluate the cleanups. */
FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
eval_constant_expression (ctx, cleanup, false, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
}
break;
@@ -2423,7 +2503,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
if (!*non_constant_p)
/* Also evaluate the cleanup. */
eval_constant_expression (ctx, TREE_OPERAND (t, 1), true,
- non_constant_p, overflow_p);
+ non_constant_p, overflow_p, jump_target);
break;
case CONSTRUCTOR:
@@ -2435,17 +2515,19 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
if (TREE_CONSTANT (t))
return fold (t);
}
- r = eval_bare_aggregate (ctx, t, lval, non_constant_p, overflow_p);
+ r = eval_bare_aggregate (ctx, t, lval, non_constant_p, overflow_p,
+ jump_target);
break;
/* 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,
- overflow_p);
+ overflow_p, jump_target);
if (*non_constant_p)
return t;
tree type = TREE_TYPE (t);
@@ -2576,7 +2658,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
return ctor;
else
return eval_constant_expression (ctx, ctor, lval, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
}
/* A placeholder without a referent. We can get here when
checking whether NSDMIs are noexcept, or in massage_init_elt;
@@ -2637,7 +2719,8 @@ is_empty_field (tree decl)
static tree
eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p)
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target)
{
constexpr_ctx new_ctx = *ctx;
@@ -2658,7 +2741,7 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval,
if (!SCALAR_TYPE_P (type))
new_ctx.ctor = new_ctx.object = NULL_TREE;
init = eval_constant_expression (&new_ctx, init, false, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
if (*non_constant_p)
return t;
}
@@ -2670,7 +2753,7 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval,
as a whole; otherwise, only evaluate the innermost piece to avoid
building up unnecessary *_REFs. */
target = eval_constant_expression (ctx, target, true, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
evaluated = true;
if (*non_constant_p)
return t;
@@ -2688,7 +2771,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)*/)
@@ -2698,7 +2782,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval,
if (TREE_CODE (probe) == ARRAY_REF)
{
elt = eval_and_check_array_index (ctx, probe, false,
- non_constant_p, overflow_p);
+ non_constant_p, overflow_p,
+ jump_target);
if (*non_constant_p)
return t;
}
@@ -2722,8 +2807,9 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval,
object = probe;
else
{
- probe = eval_constant_expression (ctx, probe, true,
- non_constant_p, overflow_p);
+ probe
+ = eval_constant_expression (ctx, probe, true, non_constant_p,
+ overflow_p, jump_target);
evaluated = true;
if (*non_constant_p)
return t;
@@ -2914,7 +3000,7 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval,
if (tree tinit = TARGET_EXPR_INITIAL (init))
init = tinit;
init = eval_constant_expression (&new_ctx, init, false, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
/* The hash table might have moved since the get earlier, and the
initializer might have mutated the underlying CONSTRUCTORs, so we must
recompute VALP. */
@@ -3016,22 +3102,115 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval,
Like cxx_eval_unary_expression, except for binary expressions. */
static tree
eval_binary_expression (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p)
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target)
{
+ tree r = NULL_TREE;
tree orig_lhs = TREE_OPERAND (t, 0);
tree orig_rhs = TREE_OPERAND (t, 1);
tree lhs, rhs;
-
lhs = eval_constant_expression (ctx, orig_lhs, lval, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
+ /* Don't VERIFY_CONSTANT here, it's unnecessary and will break pointer
+ subtraction. */
+ if (*non_constant_p)
+ return t;
+ if (*jump_target)
+ return NULL_TREE;
+
rhs = eval_constant_expression (ctx, orig_rhs, lval, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
+ if (*non_constant_p)
+ return t;
+ if (*jump_target)
+ return NULL_TREE;
location_t loc = EXPR_LOCATION (t);
enum tree_code code = TREE_CODE (t);
tree type = TREE_TYPE (t);
- return fold_binary_loc (loc, code, type, lhs, rhs);
+ if (code == EQ_EXPR || code == NE_EXPR)
+ {
+ bool is_code_eq = (code == EQ_EXPR);
+
+ if (TREE_CODE (lhs) == PTRMEM_CST && TREE_CODE (rhs) == PTRMEM_CST)
+ {
+ tree lmem = PTRMEM_CST_MEMBER (lhs);
+ tree rmem = PTRMEM_CST_MEMBER (rhs);
+ bool eq = false;
+ if (TREE_CODE (lmem) == TREE_CODE (rmem)
+ && TREE_CODE (lmem) == FIELD_DECL
+ && TREE_CODE (DECL_CONTEXT (lmem)) == UNION_TYPE
+ && same_type_p (DECL_CONTEXT (lmem), DECL_CONTEXT (rmem)))
+ /* If both refer to (possibly different) members of the same union
+ (12.3), they compare equal. */
+ eq = true;
+ // else
+ // eq = cp_tree_equal (lhs, rhs);
+ r = constant_boolean_node (eq == is_code_eq, type);
+ }
+ else if ((TREE_CODE (lhs) == PTRMEM_CST || TREE_CODE (rhs) == PTRMEM_CST)
+ && (null_member_pointer_value_p (lhs)
+ || null_member_pointer_value_p (rhs)))
+ r = constant_boolean_node (!is_code_eq, type);
+ }
+ if (r == NULL_TREE && TREE_CODE_CLASS (code) == tcc_comparison
+ && POINTER_TYPE_P (TREE_TYPE (lhs)))
+ {
+ if (tree lhso = maybe_fold_addr_pointer_plus (lhs))
+ lhs = fold_convert (TREE_TYPE (lhs), lhso);
+ if (tree rhso = maybe_fold_addr_pointer_plus (rhs))
+ rhs = fold_convert (TREE_TYPE (rhs), rhso);
+ }
+ if (code == POINTER_PLUS_EXPR && !*non_constant_p && integer_zerop (lhs)
+ && !integer_zerop (rhs))
+ {
+ if (!ctx->quiet)
+ error ("arithmetic involving a null pointer in %qE", lhs);
+ *non_constant_p = true;
+ return t;
+ }
+ else if (code == POINTER_PLUS_EXPR)
+ {
+ r = fold_pointer_plus_expression (ctx, t, lhs, rhs, non_constant_p,
+ overflow_p, jump_target);
+ if (*jump_target)
+ return NULL_TREE;
+ }
+
+ if (r == NULL_TREE)
+ {
+ r = fold_binary_loc (loc, code, type, lhs, rhs);
+ }
+
+ if (r == NULL_TREE && (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
+ && TREE_CODE (lhs) == INTEGER_CST && TREE_CODE (rhs) == INTEGER_CST
+ && wi::neg_p (wi::to_wide (rhs)))
+ {
+ /* For diagnostics and -fpermissive emulate previous behavior of
+ handling shifts by negative amount. */
+ tree nrhs = const_unop (NEGATE_EXPR, TREE_TYPE (rhs), rhs);
+ if (nrhs)
+ r = fold_binary_loc (loc,
+ code == LSHIFT_EXPR ? RSHIFT_EXPR : LSHIFT_EXPR,
+ type, lhs, nrhs);
+ }
+
+ if (r == NULL_TREE)
+ {
+ if (lhs == orig_lhs && rhs == orig_rhs)
+ r = t;
+ else
+ r = build2_loc (loc, code, type, lhs, rhs);
+ }
+ else if (eval_check_shift_p (loc, ctx, code, type, lhs, rhs))
+ *non_constant_p = true;
+ /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to
+ a local array in a constexpr function. */
+ bool ptr = INDIRECT_TYPE_P (TREE_TYPE (lhs));
+ if (!ptr)
+ VERIFY_CONSTANT (r);
+ return r;
}
/* Helper function of cxx_bind_parameters_in_call. Return non-NULL
@@ -3069,7 +3248,7 @@ addr_of_non_const_var (tree *tp, int *walk_subtrees, void *data)
static tree
rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun,
bool *non_constant_p, bool *overflow_p,
- bool *non_constant_args)
+ bool *non_constant_args, tree *jump_target)
{
const int nargs = call_expr_nargs (t);
tree parms = DECL_ARGUMENTS (fun);
@@ -3093,7 +3272,7 @@ rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun,
such as this, but here we do the elision differently: we keep the
TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm. */
arg = eval_constant_expression (ctx, x, /*lval=*/false, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
/* Don't VERIFY_CONSTANT here. */
if (*non_constant_p && ctx->quiet)
break;
@@ -3159,7 +3338,8 @@ rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun,
static tree
eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
- bool lval, bool *non_constant_p, bool *overflow_p)
+ bool lval, bool *non_constant_p, bool *overflow_p,
+ tree *jump_target)
{
const int nargs = call_expr_nargs (t);
tree *args = (tree *) alloca (nargs * sizeof (tree));
@@ -3262,8 +3442,9 @@ eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
|| potential_constant_expression (arg))
{
bool dummy1 = false, dummy2 = false;
- arg
- = eval_constant_expression (&new_ctx, arg, false, &dummy1, &dummy2);
+ tree dummy_jump_target = NULL_TREE;
+ arg = eval_constant_expression (&new_ctx, arg, false, &dummy1,
+ &dummy2, &dummy_jump_target);
}
if (bi_const_p)
@@ -3359,7 +3540,7 @@ eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
}
return eval_constant_expression (&new_ctx, new_call, lval, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
}
// Subroutine of cxx_eval_constant_expression.
@@ -3367,7 +3548,7 @@ eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
// evaluation.
static tree
eval_call_expression (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p)
+ bool *non_constant_p, bool *overflow_p, tree *jump_target)
{
location_t loc = EXPR_LOCATION (t);
tree fun = get_function_named_in_call (t);
@@ -3396,12 +3577,12 @@ eval_call_expression (const constexpr_ctx *ctx, tree t, bool lval,
if (fndecl_built_in_p (fun))
return eval_builtin_function_call (ctx, t, fun, lval, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
bool non_constant_args = false;
new_call.bindings
= rs_bind_parameters_in_call (ctx, t, fun, non_constant_p, overflow_p,
- &non_constant_args);
+ &non_constant_args, jump_target);
/* We build up the bindings list before we know whether we already have this
call cached. If we don't end up saving these bindings, ggc_free them when
@@ -3940,7 +4121,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 +4140,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);
+ &overflow_p, NULL);
}
- 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 +4160,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);
}
@@ -4024,6 +4209,17 @@ constant_value_1 (tree decl, bool, bool, bool unshare_p)
return unshare_p ? unshare_expr (decl) : decl;
}
+/* Like scalar_constant_value, but can also return aggregate initializers.
+ If UNSHARE_P, return an unshared copy of the initializer. */
+
+tree
+decl_really_constant_value (tree decl, bool unshare_p /*= true*/)
+{
+ return constant_value_1 (decl, /*strict_p=*/true,
+ /*return_aggregate_cst_ok_p=*/true,
+ /*unshare_p=*/unshare_p);
+}
+
// A more relaxed version of decl_really_constant_value, used by the
// common C/C++ code.
tree
@@ -4037,15 +4233,38 @@ decl_constant_value (tree decl, bool unshare_p)
static void
non_const_var_error (location_t loc, tree r)
{
- error_at (loc,
- "the value of %qD is not usable in a constant "
- "expression",
- r);
+ tree type = TREE_TYPE (r);
+
/* Avoid error cascade. */
if (DECL_INITIAL (r) == error_mark_node)
return;
-
- // more in cp/constexpr.cc
+ if (DECL_DECLARED_CONSTEXPR_P (r))
+ inform (DECL_SOURCE_LOCATION (r), "%qD used in its own initializer", r);
+ else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+ {
+ if (!DECL_INITIAL (r) || !TREE_CONSTANT (DECL_INITIAL (r))
+ || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r))
+ inform (DECL_SOURCE_LOCATION (r),
+ "%qD was not initialized with a constant "
+ "expression",
+ r);
+ else
+ gcc_unreachable ();
+ }
+ else if (TYPE_REF_P (type))
+ inform (DECL_SOURCE_LOCATION (r),
+ "%qD was not initialized with a constant "
+ "expression",
+ r);
+ else
+ {
+ if (!DECL_DECLARED_CONSTEXPR_P (r))
+ inform (DECL_SOURCE_LOCATION (r), "%qD was not declared %<constexpr%>",
+ r);
+ else
+ inform (DECL_SOURCE_LOCATION (r),
+ "%qD does not have integral or enumeration type", r);
+ }
}
static tree
@@ -4136,7 +4355,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))
@@ -4321,7 +4541,7 @@ verify_constant (tree t, bool allow_non_constant, bool *non_constant_p,
if (!*non_constant_p && !reduced_constant_expression_p (t) && t != void_node)
{
if (!allow_non_constant)
- error ("%q+E is not a constant expression", t);
+ error_at (EXPR_LOCATION (t), "is not a constant expression");
*non_constant_p = true;
}
if (TREE_OVERFLOW_P (t))
@@ -4426,7 +4646,8 @@ diag_array_subscript (location_t loc, const constexpr_ctx *ctx, tree array,
static tree
get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type,
- bool *non_constant_p, bool *overflow_p)
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target)
{
tree nelts;
if (TREE_CODE (type) == ARRAY_TYPE)
@@ -4442,8 +4663,8 @@ get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type,
rust_unreachable ();
/* For VLAs, the number of elements won't be an integer constant. */
- nelts
- = eval_constant_expression (ctx, nelts, false, non_constant_p, overflow_p);
+ nelts = eval_constant_expression (ctx, nelts, false, non_constant_p,
+ overflow_p, jump_target);
return nelts;
}
@@ -4455,13 +4676,13 @@ get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type,
static tree
eval_and_check_array_index (const constexpr_ctx *ctx, tree t,
bool allow_one_past, bool *non_constant_p,
- bool *overflow_p)
+ bool *overflow_p, tree *jump_target)
{
location_t loc = rs_expr_loc_or_input_loc (t);
tree ary = TREE_OPERAND (t, 0);
t = TREE_OPERAND (t, 1);
tree index = eval_constant_expression (ctx, t, allow_one_past, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
VERIFY_CONSTANT (index);
if (!tree_fits_shwi_p (index) || tree_int_cst_sgn (index) < 0)
@@ -4472,7 +4693,7 @@ eval_and_check_array_index (const constexpr_ctx *ctx, tree t,
}
tree nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary), non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
VERIFY_CONSTANT (nelts);
if (allow_one_past ? !tree_int_cst_le (index, nelts)
: !tree_int_cst_lt (index, nelts))
@@ -4682,9 +4903,9 @@ eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval,
bool *non_constant_p, bool *overflow_p,
tree *jump_target)
{
- tree val
- = eval_constant_expression (ctx, TREE_OPERAND (t, 0),
- /*lval*/ false, non_constant_p, overflow_p);
+ tree val = eval_constant_expression (ctx, TREE_OPERAND (t, 0),
+ /*lval*/ false, non_constant_p,
+ overflow_p, jump_target);
VERIFY_CONSTANT (val);
if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_P (t))
{
@@ -4721,14 +4942,14 @@ eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval,
static tree
eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p)
+ bool *non_constant_p, bool *overflow_p, tree *jump_target)
{
tree orig_whole = TREE_OPERAND (t, 0);
tree retval, fldval, utype, mask;
bool fld_seen = false;
HOST_WIDE_INT istart, isize;
tree whole = eval_constant_expression (ctx, orig_whole, lval, non_constant_p,
- overflow_p);
+ overflow_p, jump_target);
tree start, field, value;
unsigned HOST_WIDE_INT i;
@@ -4959,8 +5180,8 @@ eval_switch_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
{
tree cond
= TREE_CODE (t) == SWITCH_STMT ? SWITCH_STMT_COND (t) : SWITCH_COND (t);
- cond
- = eval_constant_expression (ctx, cond, false, non_constant_p, overflow_p);
+ cond = eval_constant_expression (ctx, cond, false, non_constant_p, overflow_p,
+ jump_target);
VERIFY_CONSTANT (cond);
*jump_target = cond;
@@ -4994,12 +5215,13 @@ eval_switch_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
static tree
eval_unary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/,
- bool *non_constant_p, bool *overflow_p)
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target)
{
tree r;
tree orig_arg = TREE_OPERAND (t, 0);
tree arg = eval_constant_expression (ctx, orig_arg, /*lval*/ false,
- non_constant_p, overflow_p);
+ non_constant_p, overflow_p, jump_target);
VERIFY_CONSTANT (arg);
location_t loc = EXPR_LOCATION (t);
enum tree_code code = TREE_CODE (t);
@@ -5135,7 +5357,9 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
if (manifestly_const_eval)
instantiate_constexpr_fns (r);
- r = eval_constant_expression (&ctx, r, false, &non_constant_p, &overflow_p);
+ tree jump_target = NULL_TREE;
+ r = eval_constant_expression (&ctx, r, false, &non_constant_p, &overflow_p,
+ &jump_target);
if (!constexpr_dtor)
verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
@@ -5147,7 +5371,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
/* Evaluate the cleanups. */
FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
eval_constant_expression (&ctx, cleanup, false, &non_constant_p,
- &overflow_p);
+ &overflow_p, NULL);
/* Mutable logic is a bit tricky: we want to allow initialization of
constexpr variables with mutable members, but we can't copy those
@@ -5907,7 +6131,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
/* A pointer-to-member constant. */
return true;
- // handle_addr_expr:
#if 0
/* FIXME adjust when issue 1197 is fully resolved. For now don't do
any checking here, as we might dereference the pointer later. If
@@ -5943,7 +6166,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 +6438,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 +6448,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 +6464,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 +6485,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 +6508,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))
@@ -6477,6 +6706,170 @@ fold_non_dependent_init (tree t, tsubst_flags_t /*=tf_warning_or_error*/,
return maybe_constant_init (t, object, manifestly_const_eval);
}
+/* Check whether the shift operation with code CODE and type TYPE on LHS
+ and RHS is undefined. If it is, give an error with an explanation,
+ and return true; return false otherwise. */
+
+static bool
+eval_check_shift_p (location_t loc, const constexpr_ctx *ctx,
+ enum tree_code code, tree type, tree lhs, tree rhs)
+{
+ if ((code != LSHIFT_EXPR && code != RSHIFT_EXPR)
+ || TREE_CODE (lhs) != INTEGER_CST || TREE_CODE (rhs) != INTEGER_CST)
+ return false;
+
+ tree lhstype = TREE_TYPE (lhs);
+ unsigned HOST_WIDE_INT uprec = TYPE_PRECISION (TREE_TYPE (lhs));
+
+ /* [expr.shift] The behavior is undefined if the right operand
+ is negative, or greater than or equal to the length in bits
+ of the promoted left operand. */
+ if (tree_int_cst_sgn (rhs) == -1)
+ {
+ if (!ctx->quiet)
+ permerror (loc, "right operand of shift expression %q+E is negative",
+ build2_loc (loc, code, type, lhs, rhs));
+ return (!flag_permissive || ctx->quiet);
+ }
+ if (compare_tree_int (rhs, uprec) >= 0)
+ {
+ if (!ctx->quiet)
+ permerror (loc,
+ "right operand of shift expression %q+E is greater "
+ "than or equal to the precision %wu of the left operand",
+ build2_loc (loc, code, type, lhs, rhs), uprec);
+ return (!flag_permissive || ctx->quiet);
+ }
+
+ /* The value of E1 << E2 is E1 left-shifted E2 bit positions; [...]
+ if E1 has a signed type and non-negative value, and E1x2^E2 is
+ representable in the corresponding unsigned type of the result type,
+ then that value, converted to the result type, is the resulting value;
+ otherwise, the behavior is undefined.
+ For C++20:
+ The value of E1 << E2 is the unique value congruent to E1 x 2^E2 modulo
+ 2^N, where N is the range exponent of the type of the result. */
+ if (code == LSHIFT_EXPR && !TYPE_OVERFLOW_WRAPS (lhstype))
+ {
+ if (tree_int_cst_sgn (lhs) == -1)
+ {
+ if (!ctx->quiet)
+ permerror (loc, "left operand of shift expression %q+E is negative",
+ build2_loc (loc, code, type, lhs, rhs));
+ return (!flag_permissive || ctx->quiet);
+ }
+ /* For signed x << y the following:
+ (unsigned) x >> ((prec (lhs) - 1) - y)
+ if > 1, is undefined. The right-hand side of this formula
+ is the highest bit of the LHS that can be set (starting from 0),
+ so that the shift doesn't overflow. We then right-shift the LHS
+ to see whether any other bit is set making the original shift
+ undefined -- the result is not representable in the corresponding
+ unsigned type. */
+ tree t = build_int_cst (unsigned_type_node, uprec - 1);
+ t = fold_build2 (MINUS_EXPR, unsigned_type_node, t, rhs);
+ tree ulhs = fold_convert (unsigned_type_for (lhstype), lhs);
+ t = fold_build2 (RSHIFT_EXPR, TREE_TYPE (ulhs), ulhs, t);
+ if (tree_int_cst_lt (integer_one_node, t))
+ {
+ if (!ctx->quiet)
+ permerror (loc, "shift expression %q+E overflows",
+ build2_loc (loc, code, type, lhs, rhs));
+ return (!flag_permissive || ctx->quiet);
+ }
+ }
+ return false;
+}
+
+/* Helper function for cxx_eval_binary_expression. Try to optimize
+ original POINTER_PLUS_EXPR T, LHS p+ RHS, return NULL_TREE if the
+ generic folding should be used. */
+
+static tree
+fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t, tree lhs,
+ tree rhs, bool *non_constant_p, bool *overflow_p,
+ tree *jump_target)
+{
+ STRIP_NOPS (lhs);
+ if (TREE_CODE (lhs) != ADDR_EXPR)
+ return NULL_TREE;
+
+ lhs = TREE_OPERAND (lhs, 0);
+
+ /* &A[i] p+ j => &A[i + j] */
+ if (TREE_CODE (lhs) == ARRAY_REF
+ && TREE_CODE (TREE_OPERAND (lhs, 1)) == INTEGER_CST
+ && TREE_CODE (rhs) == INTEGER_CST && TYPE_SIZE_UNIT (TREE_TYPE (lhs))
+ && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (lhs))) == INTEGER_CST)
+ {
+ tree orig_type = TREE_TYPE (t);
+ location_t loc = EXPR_LOCATION (t);
+ tree type = TREE_TYPE (lhs);
+
+ t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (lhs, 1));
+ tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (lhs, 0)));
+ nelts = eval_constant_expression (ctx, nelts, true, non_constant_p,
+ overflow_p, jump_target);
+ if (*non_constant_p)
+ return NULL_TREE;
+ if (*jump_target)
+ return NULL_TREE;
+ /* Don't fold an out-of-bound access. */
+ if (!tree_int_cst_le (t, nelts))
+ return NULL_TREE;
+ rhs = fold_convert (ssizetype, rhs);
+ /* Don't fold if rhs can't be divided exactly by TYPE_SIZE_UNIT.
+ constexpr int A[1]; ... (char *)&A[0] + 1 */
+ if (!integer_zerop (fold_build2_loc (loc, TRUNC_MOD_EXPR, sizetype, rhs,
+ TYPE_SIZE_UNIT (type))))
+ return NULL_TREE;
+ /* Make sure to treat the second operand of POINTER_PLUS_EXPR
+ as signed. */
+ rhs = fold_build2_loc (loc, EXACT_DIV_EXPR, ssizetype, rhs,
+ TYPE_SIZE_UNIT (type));
+ t = size_binop_loc (loc, PLUS_EXPR, rhs, t);
+ t = build4_loc (loc, ARRAY_REF, type, TREE_OPERAND (lhs, 0), t, NULL_TREE,
+ NULL_TREE);
+ t = build_fold_addr_expr (t);
+ t = fold_convert (orig_type, t);
+ return eval_constant_expression (ctx, t, true, non_constant_p, overflow_p,
+ jump_target);
+ }
+
+ return NULL_TREE;
+}
+
+/* Try to fold expressions like
+ (struct S *) (&a[0].D.2378 + 12)
+ into
+ &MEM <struct T> [(void *)&a + 12B]
+ This is something normally done by gimple_fold_stmt_to_constant_1
+ on GIMPLE, but is undesirable on GENERIC if we are e.g. going to
+ dereference the address because some details are lost.
+ For pointer comparisons we want such folding though so that
+ match.pd address_compare optimization works. */
+
+static tree
+maybe_fold_addr_pointer_plus (tree t)
+{
+ while (CONVERT_EXPR_P (t) && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0))))
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) != POINTER_PLUS_EXPR)
+ return NULL_TREE;
+ tree op0 = TREE_OPERAND (t, 0);
+ tree op1 = TREE_OPERAND (t, 1);
+ if (TREE_CODE (op1) != INTEGER_CST)
+ return NULL_TREE;
+ while (CONVERT_EXPR_P (op0)
+ && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0))))
+ op0 = TREE_OPERAND (op0, 0);
+ if (TREE_CODE (op0) != ADDR_EXPR)
+ return NULL_TREE;
+ op1 = fold_convert (ptr_type_node, op1);
+ tree r = fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (op0)), op0, op1);
+ return build1_loc (EXPR_LOCATION (t), ADDR_EXPR, TREE_TYPE (op0), r);
+}
+
} // namespace Compile
} // namespace Rust
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 6cba04b..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);
@@ -3848,16 +3874,18 @@ strip_top_quals (tree t)
/* Print an error message for invalid use of an incomplete type.
VALUE is the expression that was used (or 0 if that isn't known)
and TYPE is the type that was invalid. DIAG_KIND indicates the
- type of diagnostic (see diagnostic.def). */
+ type of diagnostic (see diagnostics/kinds.def). */
void
cxx_incomplete_type_diagnostic (location_t loc, const_tree value,
- const_tree type, diagnostic_t diag_kind)
+ const_tree type,
+ enum diagnostics::kind diag_kind)
{
// bool is_decl = false, complained = false;
- gcc_assert (diag_kind == DK_WARNING || diag_kind == DK_PEDWARN
- || diag_kind == DK_ERROR);
+ gcc_assert (diag_kind == diagnostics::kind::warning
+ || diag_kind == diagnostics::kind::pedwarn
+ || diag_kind == diagnostics::kind::error);
/* Avoid duplicate error message. */
if (TREE_CODE (type) == ERROR_MARK)
@@ -3907,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);
@@ -3992,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. */
@@ -4288,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 {
@@ -4419,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)
{
@@ -4516,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);
@@ -5131,7 +5169,7 @@ complete_type_or_maybe_complain (tree type, tree value, tsubst_flags_t complain)
else if (!COMPLETE_TYPE_P (type))
{
if (complain & tf_error)
- cxx_incomplete_type_diagnostic (value, type, DK_ERROR);
+ cxx_incomplete_type_diagnostic (value, type, diagnostics::kind::error);
note_failed_type_completion_for_satisfaction (type);
return NULL_TREE;
}
diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h
index bb99684..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);
@@ -3137,7 +3108,7 @@ extern bool reject_gcc_builtin (const_tree, location_t = UNKNOWN_LOCATION);
extern tree resolve_nondeduced_context (tree, tsubst_flags_t);
extern void cxx_incomplete_type_diagnostic (location_t, const_tree, const_tree,
- diagnostic_t);
+ enum diagnostics::kind);
extern void cxx_incomplete_type_error (location_t, const_tree, const_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; }
@@ -3430,7 +3389,7 @@ null_node_p (const_tree expr)
inline void
cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
- diagnostic_t diag_kind)
+ enum diagnostics::kind diag_kind)
{
cxx_incomplete_type_diagnostic (rs_expr_loc_or_input_loc (value), value, type,
diag_kind);
@@ -3439,11 +3398,10 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
inline void
cxx_incomplete_type_error (const_tree value, const_tree type)
{
- cxx_incomplete_type_diagnostic (value, type, DK_ERROR);
+ 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 d6acc6a..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),
@@ -325,6 +327,14 @@ ExprStmtBuilder::visit (HIR::InlineAsm &expr)
{}
void
+ExprStmtBuilder::visit (HIR::LlvmInlineAsm &expr)
+{}
+
+void
+ExprStmtBuilder::visit (HIR::OffsetOf &expr)
+{}
+
+void
ExprStmtBuilder::visit (HIR::MethodCallExpr &expr)
{}
@@ -411,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 daedb68..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;
@@ -100,6 +103,8 @@ protected: // Expr
void visit (HIR::IfExpr &expr) override;
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..de8a830 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
@@ -24,9 +24,10 @@
#include "rust-hir-item.h"
#include "rust-hir-type-check.h"
#include "rust-hir-visitor.h"
-#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 {
@@ -73,7 +74,7 @@ struct BuilderContext
// External context.
Resolver::TypeCheckContext &tyctx;
- Resolver::Resolver &resolver;
+ const Resolver2_0::NameResolutionContext &resolver;
// BIR output
BasicBlocks basic_blocks;
@@ -102,7 +103,7 @@ struct BuilderContext
public:
BuilderContext ()
: tyctx (*Resolver::TypeCheckContext::get ()),
- resolver (*Resolver::Resolver::get ())
+ resolver (Resolver2_0::ImmutableNameResolutionContext::get ().resolver ())
{
basic_blocks.emplace_back (); // StartBB
}
@@ -401,37 +402,31 @@ 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);
- return resolved_label;
+ auto res = ctx.resolver.lookup (expr.get_mappings ().get_nodeid ());
+ rust_assert (res.has_value ());
+ return res.value ();
}
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);
- return ctx.place_db.lookup_variable (variable_id);
+ auto res = ctx.resolver.lookup (variable.get_mappings ().get_nodeid ());
+ rust_assert (res.has_value ());
+ return ctx.place_db.lookup_variable (res.value ());
}
template <typename T>
PlaceId resolve_variable_or_fn (T &variable, TyTy::BaseType *ty)
{
ty = (ty) ? ty : lookup_type (variable);
+
// 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 (ty->is<TyTy::FnType> ())
return ctx.place_db.get_constant (ty);
- else
- return ctx.place_db.lookup_or_add_variable (variable_id, ty);
+
+ auto res = ctx.resolver.lookup (variable.get_mappings ().get_nodeid ());
+ rust_assert (res.has_value ());
+ return ctx.place_db.lookup_or_add_variable (res.value (), ty);
}
protected: // Implicit conversions.
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 3bc622c..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 ());
@@ -207,6 +215,8 @@ 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..e78d750 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
@@ -70,11 +70,34 @@ PatternBindingBuilder::visit (HIR::SlicePattern &pattern)
return ty->as<TyTy::SliceType> ()->get_element_type ();
});
- // Regions are unchnaged.
+ // Regions are unchanged.
- for (auto &item : pattern.get_items ())
+ switch (pattern.get_items ().get_item_type ())
{
- item->accept_vis (*this);
+ case HIR::SlicePatternItems::NO_REST:
+ {
+ auto &items
+ = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ());
+ for (auto &member : items.get_patterns ())
+ {
+ member->accept_vis (*this);
+ }
+ break;
+ }
+ case HIR::SlicePatternItems::HAS_REST:
+ {
+ auto &items
+ = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
+ for (auto &member : items.get_lower_patterns ())
+ {
+ member->accept_vis (*this);
+ }
+ for (auto &member : items.get_upper_patterns ())
+ {
+ member->accept_vis (*this);
+ }
+ break;
+ }
}
}
@@ -101,7 +124,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 +147,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 +164,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,15 +225,17 @@ PatternBindingBuilder::visit (HIR::TuplePattern &pattern)
size_t index = 0;
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::MULTIPLE: {
- auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
- pattern.get_items ());
+ case HIR::TuplePatternItems::NO_REST:
+ {
+ auto &items
+ = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ());
visit_tuple_fields (items.get_patterns (), saved, index);
break;
}
- case HIR::TuplePatternItems::RANGED: {
+ case HIR::TuplePatternItems::HAS_REST:
+ {
auto &items
- = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
+ = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ());
auto tyty = ctx.place_db[init.value ()].tyty;
rust_assert (tyty->get_kind () == TyTy::TUPLE);
@@ -244,9 +272,10 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern)
size_t index = 0;
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TupleStructItems::RANGED: {
+ case HIR::TupleStructItems::HAS_REST:
+ {
auto &items
- = static_cast<HIR::TupleStructItemsRange &> (pattern.get_items ());
+ = static_cast<HIR::TupleStructItemsHasRest &> (pattern.get_items ());
rust_assert (type->get_kind () == TyTy::ADT);
auto adt_ty = static_cast<TyTy::ADTType *> (type);
@@ -261,9 +290,10 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern)
visit_tuple_fields (items.get_upper_patterns (), saved, index);
break;
}
- case HIR::TupleStructItems::MULTIPLE: {
+ case HIR::TupleStructItems::NO_REST:
+ {
auto &items
- = static_cast<HIR::TupleStructItemsNoRange &> (pattern.get_items ());
+ = static_cast<HIR::TupleStructItemsNoRest &> (pattern.get_items ());
visit_tuple_fields (items.get_patterns (), saved, index);
break;
}
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 94fcecd..6cb87c7 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 (); }
@@ -153,6 +156,8 @@ protected:
void visit (HIR::AwaitExpr &expr) override { rust_unreachable (); }
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
@@ -220,11 +225,11 @@ protected:
rust_unreachable ();
}
void visit (HIR::StructPattern &pattern) override { rust_unreachable (); }
- void visit (HIR::TupleStructItemsNoRange &tuple_items) override
+ void visit (HIR::TupleStructItemsNoRest &tuple_items) override
{
rust_unreachable ();
}
- void visit (HIR::TupleStructItemsRange &tuple_items) override
+ void visit (HIR::TupleStructItemsHasRest &tuple_items) override
{
rust_unreachable ();
}
@@ -232,15 +237,23 @@ protected:
{
rust_unreachable ();
}
- void visit (HIR::TuplePatternItemsMultiple &tuple_items) override
+ void visit (HIR::TuplePatternItemsNoRest &tuple_items) override
{
rust_unreachable ();
}
- void visit (HIR::TuplePatternItemsRanged &tuple_items) override
+ void visit (HIR::TuplePatternItemsHasRest &tuple_items) override
{
rust_unreachable ();
}
void visit (HIR::TuplePattern &pattern) override { rust_unreachable (); }
+ void visit (HIR::SlicePatternItemsNoRest &tuple_items) override
+ {
+ rust_unreachable ();
+ }
+ void visit (HIR::SlicePatternItemsHasRest &tuple_items) override
+ {
+ rust_unreachable ();
+ }
void visit (HIR::SlicePattern &pattern) override { rust_unreachable (); }
void visit (HIR::AltPattern &pattern) override { rust_unreachable (); }
void visit (HIR::EmptyStmt &stmt) override { rust_unreachable (); }
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 67ca90b..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)); }
@@ -204,6 +204,9 @@ template <typename I, typename T> class IndexVec
{
std::vector<T> internal_vector;
+ typedef decltype (std::declval<I> ().value) size_type;
+ static constexpr auto MAX_INDEX = std::numeric_limits<size_type>::max ();
+
public:
IndexVec () = default;
IndexVec (size_t size) { internal_vector.reserve (size); }
@@ -214,12 +217,16 @@ 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)...);
}
- size_t size () const { return internal_vector.size (); }
+ size_type size () const
+ {
+ rust_assert (internal_vector.size () < MAX_INDEX);
+ return static_cast<size_type> (internal_vector.size ());
+ }
std::vector<T> &get_vector () { return internal_vector; }
};
@@ -418,8 +425,7 @@ public:
if (lookup != INVALID_PLACE)
return lookup;
- add_place ({Place::VARIABLE, id, {}, is_type_copy (tyty), tyty});
- return {places.size () - 1};
+ return add_place ({Place::VARIABLE, id, {}, is_type_copy (tyty), tyty});
};
template <typename FN> void for_each_path_from_root (PlaceId var, FN fn) const
@@ -465,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:
@@ -485,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-bir.h b/gcc/rust/checks/errors/borrowck/rust-bir.h
index e90e508..8a5f7be 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir.h
@@ -35,6 +35,26 @@ using BasicBlocks = IndexVec<BasicBlockId, BasicBlock>;
class Statement;
class AbstractExpr;
+/** Unique identifier for a basic block in the BIR. */
+struct BasicBlockId
+{
+ uint32_t value;
+ // some overloads for comparision
+ bool operator== (const BasicBlockId &rhs) const { return value == rhs.value; }
+ bool operator!= (const BasicBlockId &rhs) const
+ {
+ return !(operator== (rhs));
+ }
+ bool operator< (const BasicBlockId &rhs) const { return value < rhs.value; }
+ bool operator> (const BasicBlockId &rhs) const { return value > rhs.value; }
+ bool operator<= (const BasicBlockId &rhs) const { return !(operator> (rhs)); }
+ bool operator>= (const BasicBlockId &rhs) const { return !(operator< (rhs)); }
+};
+
+static constexpr BasicBlockId INVALID_BB
+ = {std::numeric_limits<uint32_t>::max ()};
+static constexpr BasicBlockId ENTRY_BASIC_BLOCK = {0};
+
/**
* Top-level entity of the Borrow-checker IR (BIR).
* It represents a single function (method, closure, etc.), which is the
@@ -132,26 +152,6 @@ public:
WARN_UNUSED_RESULT location_t get_location () const { return location; }
};
-/** Unique identifier for a basic block in the BIR. */
-struct BasicBlockId
-{
- uint32_t value;
- // some overloads for comparision
- bool operator== (const BasicBlockId &rhs) const { return value == rhs.value; }
- bool operator!= (const BasicBlockId &rhs) const
- {
- return !(operator== (rhs));
- }
- bool operator< (const BasicBlockId &rhs) const { return value < rhs.value; }
- bool operator> (const BasicBlockId &rhs) const { return value > rhs.value; }
- bool operator<= (const BasicBlockId &rhs) const { return !(operator> (rhs)); }
- bool operator>= (const BasicBlockId &rhs) const { return !(operator< (rhs)); }
-};
-
-static constexpr BasicBlockId INVALID_BB
- = {std::numeric_limits<uint32_t>::max ()};
-static constexpr BasicBlockId ENTRY_BASIC_BLOCK = {0};
-
struct BasicBlock
{
// BIR "instructions".
diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
index 6c67706..adf1448 100644
--- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
@@ -142,7 +142,7 @@ BorrowCheckerDiagnostics::get_statement (Polonius::Point point)
const BIR::Loan &
BorrowCheckerDiagnostics::get_loan (Polonius::Loan loan)
{
- return bir_function.place_db.get_loans ()[{loan}];
+ return bir_function.place_db.get_loans ()[{(uint32_t) loan}];
}
const HIR::LifetimeParam *
diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
index cdb20e8..63f2a95 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 {}
@@ -123,6 +126,8 @@ public:
void visit (HIR::AwaitExpr &expr) override {}
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 {}
@@ -165,12 +170,14 @@ public:
void visit (HIR::StructPatternFieldIdentPat &field) override {}
void visit (HIR::StructPatternFieldIdent &field) override {}
void visit (HIR::StructPattern &pattern) override {}
- void visit (HIR::TupleStructItemsNoRange &tuple_items) override {}
- void visit (HIR::TupleStructItemsRange &tuple_items) override {}
+ void visit (HIR::TupleStructItemsNoRest &tuple_items) override {}
+ void visit (HIR::TupleStructItemsHasRest &tuple_items) override {}
void visit (HIR::TupleStructPattern &pattern) override {}
- void visit (HIR::TuplePatternItemsMultiple &tuple_items) override {}
- void visit (HIR::TuplePatternItemsRanged &tuple_items) override {}
+ void visit (HIR::TuplePatternItemsNoRest &tuple_items) override {}
+ void visit (HIR::TuplePatternItemsHasRest &tuple_items) override {}
void visit (HIR::TuplePattern &pattern) override {}
+ void visit (HIR::SlicePatternItemsNoRest &tuple_items) override {}
+ void visit (HIR::SlicePatternItemsHasRest &tuple_items) override {}
void visit (HIR::SlicePattern &pattern) override {}
void visit (HIR::AltPattern &pattern) override {}
void visit (HIR::EmptyStmt &stmt) override {}
diff --git a/gcc/rust/checks/errors/feature/contrib/.gitignore b/gcc/rust/checks/errors/feature/contrib/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/gcc/rust/checks/errors/feature/contrib/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/gcc/rust/checks/errors/feature/contrib/Makefile b/gcc/rust/checks/errors/feature/contrib/Makefile
new file mode 100644
index 0000000..7c828ab
--- /dev/null
+++ b/gcc/rust/checks/errors/feature/contrib/Makefile
@@ -0,0 +1,59 @@
+# 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/>.
+
+OUT = ../rust-feature-defs.h
+
+all: $(OUT)
+
+mk-build-dir:
+ mkdir -p build
+
+build/parse.c: parse.y mk-build-dir
+ $(YACC) $(YFLAGS) -o $@ --defines=build/parse.h $<
+
+build/parse.h: build/parse.c;
+
+build/scan.c: scan.l
+ $(LEX) $(LFLAGS) -o $@ -Ca --header-file=build/scan.h $<
+
+build/scan.h: build/scan.c;
+
+build/%.o: build/%.c build/parse.h build/scan.h
+ $(CC) $(CFLAGS) -c -Ibuild -o $@ $<
+
+build/feature-extract: build/parse.o build/scan.o
+ $(CC) $(LDFLAGS) $(LDLIBS) -o $@ $^
+
+build/download.rs: fetch
+ ./$< $@
+
+$(OUT): build/feature-extract build/download.rs
+ # add copyright header + newline
+ echo | \
+ cat copyright-stub.h - | \
+ sed "s/YYYY/$$(date +%Y)/" > build/rust-feature-defs.h
+ cat build/download.rs | ./$< >> build/rust-feature-defs.h
+ clang-format -i build/rust-feature-defs.h \
+ --style=file:../../../../../../contrib/clang-format
+ mv build/rust-feature-defs.h $(OUT)
+
+clean:
+ $(RM) -r build
+
+clean-all: clean
+ $(RM) $(OUT)
diff --git a/gcc/rust/checks/errors/feature/contrib/README b/gcc/rust/checks/errors/feature/contrib/README
new file mode 100644
index 0000000..e85fe09
--- /dev/null
+++ b/gcc/rust/checks/errors/feature/contrib/README
@@ -0,0 +1,3 @@
+This program is intended for use in generating rust-feature-defs.h
+
+To use, run `./regen`
diff --git a/gcc/rust/checks/errors/feature/contrib/copyright-stub.h b/gcc/rust/checks/errors/feature/contrib/copyright-stub.h
new file mode 100644
index 0000000..1a5f52c
--- /dev/null
+++ b/gcc/rust/checks/errors/feature/contrib/copyright-stub.h
@@ -0,0 +1,19 @@
+// Copyright (C) YYYY 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/>.
+
+// AUTO-GENERATED -- SEE LOCAL contrib SUBDIRECTORY
diff --git a/gcc/rust/checks/errors/feature/contrib/fetch b/gcc/rust/checks/errors/feature/contrib/fetch
new file mode 100755
index 0000000..b26ed3c
--- /dev/null
+++ b/gcc/rust/checks/errors/feature/contrib/fetch
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# 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/>.
+
+RUST_VERSION="1.49.0"
+
+[ $# = 1 ] || exit 1
+
+# Fetches files from the official rustc git repository
+
+URL_PREFIX='https://raw.githubusercontent.com/rust-lang/rust/refs/tags'
+URL_TEMPLATE="$URL_PREFIX/$RUST_VERSION/compiler/rustc_feature/src"
+
+wget -O $1 "$URL_TEMPLATE"/{accepted,active,removed}.rs
diff --git a/gcc/rust/checks/errors/feature/contrib/parse.y b/gcc/rust/checks/errors/feature/contrib/parse.y
new file mode 100644
index 0000000..34c0138
--- /dev/null
+++ b/gcc/rust/checks/errors/feature/contrib/parse.y
@@ -0,0 +1,143 @@
+/* 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 <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+int yylex (void);
+void yyerror (char const *);
+
+#include "scan.h"
+
+// expands to three %s parameters
+#define UNWRAP_OPT_STR(prefix, s) (s ? prefix "_SOME (" : prefix "_NONE"), (s ? s : ""), (s ? ")" : "")
+
+%}
+
+%union
+{
+ char *str;
+};
+
+%token <str> IDENT STR NUM
+%token SCOPE
+%token K_SOME K_NONE
+%token K_ACTIVE K_ACCEPTED K_REMOVED K_STABLE_REMOVED
+%token K_E_START K_E_2018
+
+%type <str> issue
+%type <str> edition
+%type <str> reason
+
+%%
+
+multi_database: multi_database database
+| database
+;
+
+database: '(' entry_list ')';
+
+entry_list: entry_list entry ','
+| entry ','
+;
+
+entry: '(' K_ACTIVE ',' IDENT ',' STR ',' issue ',' edition ')' {
+ char *ident_upper = strdup ($4);
+ for (size_t i = 0; ident_upper[i]; i++)
+ ident_upper[i] = toupper (ident_upper[i]);
+ printf ("FEATURE_ACTIVE (\"%s\", %s, %s, %s%s%s, EDITION_%s)\n", $4, ident_upper, $6, UNWRAP_OPT_STR ("ISSUE", $8), $10 ? $10 : "NONE");
+ free ($4);
+ free (ident_upper);
+ free ($6);
+ free ($8);
+}
+| '(' K_ACCEPTED ',' IDENT ',' STR ',' issue ',' K_NONE ')' {
+ char *ident_upper = strdup ($4);
+ for (size_t i = 0; ident_upper[i]; i++)
+ ident_upper[i] = toupper (ident_upper[i]);
+ printf ("FEATURE_ACCEPTED (\"%s\", %s, %s, %s%s%s)\n", $4, ident_upper, $6, UNWRAP_OPT_STR ("ISSUE", $8));
+ free ($4);
+ free (ident_upper);
+ free ($6);
+ free ($8);
+}
+| '(' K_REMOVED ',' IDENT ',' STR ',' issue ',' K_NONE ',' reason ')' {
+ char *ident_upper;
+ // HACK: convert no_debug to F_NO_DEBUG instead
+ // since NO_DEBUG is used as an unrelated macro
+ if (!strcmp ($4, "no_debug"))
+ {
+ ident_upper = strdup ("F_NO_DEBUG");
+ }
+ else
+ {
+ ident_upper = strdup ($4);
+ for (size_t i = 0; ident_upper[i]; i++)
+ ident_upper[i] = toupper (ident_upper[i]);
+ }
+ printf ("FEATURE_REMOVED (\"%s\", %s, %s, %s%s%s, %s%s%s)\n", $4, ident_upper, $6, UNWRAP_OPT_STR ("ISSUE", $8), UNWRAP_OPT_STR ("REASON", $12));
+ free ($4);
+ free (ident_upper);
+ free ($6);
+ free ($8);
+ free ($12);
+}
+| '(' K_STABLE_REMOVED ',' IDENT ',' STR ',' issue ',' K_NONE ')' {
+ char *ident_upper = strdup ($4);
+ for (size_t i = 0; ident_upper[i]; i++)
+ ident_upper[i] = toupper (ident_upper[i]);
+ printf ("FEATURE_STABLE_REMOVED (\"%s\", %s, %s, %s%s%s)\n", $4, ident_upper, $6, UNWRAP_OPT_STR ("ISSUE", $8));
+ free ($4);
+ free (ident_upper);
+ free ($6);
+ free ($8);
+}
+;
+
+issue: K_SOME '(' NUM ')' { $$ = $3; }
+| K_NONE { $$ = NULL; }
+;
+
+/* TODO: expand this as needed */
+edition: K_NONE { $$ = NULL; }
+| K_SOME '(' K_E_START SCOPE K_E_2018 ')' { $$ = "2018"; }
+;
+
+reason: K_SOME '(' STR ')' { $$ = $3; }
+| K_NONE { $$ = NULL; }
+;
+
+%%
+
+void yyerror (const char *msg)
+{
+ fprintf (stderr, "%s\n", msg);
+}
+
+int yywrap (void)
+{
+ return 1;
+}
+
+int main (void)
+{
+ return yyparse ();
+}
diff --git a/gcc/rust/checks/errors/feature/contrib/regen b/gcc/rust/checks/errors/feature/contrib/regen
new file mode 100755
index 0000000..0dc6cc5
--- /dev/null
+++ b/gcc/rust/checks/errors/feature/contrib/regen
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# 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/>.
+
+cd "$(dirname "$0")"
+rm -f ../rust-feature-defs.h
+make all
diff --git a/gcc/rust/checks/errors/feature/contrib/scan.l b/gcc/rust/checks/errors/feature/contrib/scan.l
new file mode 100644
index 0000000..768f4c7
--- /dev/null
+++ b/gcc/rust/checks/errors/feature/contrib/scan.l
@@ -0,0 +1,55 @@
+/* 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 "parse.h"
+
+static int p_count = 0;
+
+%}
+
+%x INSIDE COMMENT
+
+%%
+
+declare_features! BEGIN (INSIDE);
+.|\n /* ignore */
+
+<INSIDE>\( p_count++; return '(';
+<INSIDE>\) if (!--p_count) { BEGIN (0); } return ')';
+<INSIDE>, return ',';
+<INSIDE>:: return SCOPE;
+<INSIDE>Some return K_SOME;
+<INSIDE>None return K_NONE;
+<INSIDE>active return K_ACTIVE;
+<INSIDE>accepted return K_ACCEPTED;
+<INSIDE>removed return K_REMOVED;
+<INSIDE>stable_removed return K_STABLE_REMOVED;
+<INSIDE>Edition return K_E_START;
+<INSIDE>Edition2018 return K_E_2018;
+
+<INSIDE>[A-Za-z_][A-Za-z0-9_]* yylval.str = strdup (yytext); return IDENT;
+<INSIDE>[1-9][0-9]* yylval.str = strdup (yytext); return NUM;
+<INSIDE>\"[^"]+\" yylval.str = strdup (yytext); return STR;
+<INSIDE>"/""/" BEGIN (COMMENT);
+<INSIDE>[ \n] /* ignore */
+<INSIDE>. { fprintf (stderr, "unrecognized character %u\n", (unsigned int) yytext[0]); exit (1); }
+
+<COMMENT>. /* skip */
+<COMMENT>\n BEGIN (INSIDE);
diff --git a/gcc/rust/checks/errors/feature/rust-feature-defs.h b/gcc/rust/checks/errors/feature/rust-feature-defs.h
new file mode 100644
index 0000000..d8514e1
--- /dev/null
+++ b/gcc/rust/checks/errors/feature/rust-feature-defs.h
@@ -0,0 +1,600 @@
+// 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/>.
+
+// AUTO-GENERATED -- SEE LOCAL contrib SUBDIRECTORY
+
+FEATURE_ACCEPTED ("issue_5723_bootstrap", ISSUE_5723_BOOTSTRAP, "1.0.0",
+ ISSUE_NONE)
+FEATURE_ACCEPTED ("test_accepted_feature", TEST_ACCEPTED_FEATURE, "1.0.0",
+ ISSUE_NONE)
+FEATURE_ACCEPTED ("associated_types", ASSOCIATED_TYPES, "1.0.0", ISSUE_NONE)
+FEATURE_ACCEPTED ("default_type_params", DEFAULT_TYPE_PARAMS, "1.0.0",
+ ISSUE_NONE)
+FEATURE_ACCEPTED ("globs", GLOBS, "1.0.0", ISSUE_NONE)
+FEATURE_ACCEPTED ("macro_rules", MACRO_RULES, "1.0.0", ISSUE_NONE)
+FEATURE_ACCEPTED ("slicing_syntax", SLICING_SYNTAX, "1.0.0", ISSUE_NONE)
+FEATURE_ACCEPTED ("struct_variant", STRUCT_VARIANT, "1.0.0", ISSUE_NONE)
+FEATURE_ACCEPTED ("tuple_indexing", TUPLE_INDEXING, "1.0.0", ISSUE_NONE)
+FEATURE_ACCEPTED ("if_let", IF_LET, "1.0.0", ISSUE_NONE)
+FEATURE_ACCEPTED ("while_let", WHILE_LET, "1.0.0", ISSUE_NONE)
+FEATURE_ACCEPTED ("no_std", NO_STD, "1.6.0", ISSUE_NONE)
+FEATURE_ACCEPTED ("augmented_assignments", AUGMENTED_ASSIGNMENTS, "1.8.0",
+ ISSUE_SOME (28235))
+FEATURE_ACCEPTED ("braced_empty_structs", BRACED_EMPTY_STRUCTS, "1.8.0",
+ ISSUE_SOME (29720))
+FEATURE_ACCEPTED ("deprecated", DEPRECATED, "1.9.0", ISSUE_SOME (29935))
+FEATURE_ACCEPTED ("type_macros", TYPE_MACROS, "1.13.0", ISSUE_SOME (27245))
+FEATURE_ACCEPTED ("question_mark", QUESTION_MARK, "1.13.0", ISSUE_SOME (31436))
+FEATURE_ACCEPTED ("dotdot_in_tuple_patterns", DOTDOT_IN_TUPLE_PATTERNS,
+ "1.14.0", ISSUE_SOME (33627))
+FEATURE_ACCEPTED ("item_like_imports", ITEM_LIKE_IMPORTS, "1.15.0",
+ ISSUE_SOME (35120))
+FEATURE_ACCEPTED ("more_struct_aliases", MORE_STRUCT_ALIASES, "1.16.0",
+ ISSUE_SOME (37544))
+FEATURE_ACCEPTED ("static_in_const", STATIC_IN_CONST, "1.17.0",
+ ISSUE_SOME (35897))
+FEATURE_ACCEPTED ("field_init_shorthand", FIELD_INIT_SHORTHAND, "1.17.0",
+ ISSUE_SOME (37340))
+FEATURE_ACCEPTED ("static_recursion", STATIC_RECURSION, "1.17.0",
+ ISSUE_SOME (29719))
+FEATURE_ACCEPTED ("pub_restricted", PUB_RESTRICTED, "1.18.0",
+ ISSUE_SOME (32409))
+FEATURE_ACCEPTED ("windows_subsystem", WINDOWS_SUBSYSTEM, "1.18.0",
+ ISSUE_SOME (37499))
+FEATURE_ACCEPTED ("loop_break_value", LOOP_BREAK_VALUE, "1.19.0",
+ ISSUE_SOME (37339))
+FEATURE_ACCEPTED ("relaxed_adts", RELAXED_ADTS, "1.19.0", ISSUE_SOME (35626))
+FEATURE_ACCEPTED ("closure_to_fn_coercion", CLOSURE_TO_FN_COERCION, "1.19.0",
+ ISSUE_SOME (39817))
+FEATURE_ACCEPTED ("struct_field_attributes", STRUCT_FIELD_ATTRIBUTES, "1.20.0",
+ ISSUE_SOME (38814))
+FEATURE_ACCEPTED ("associated_consts", ASSOCIATED_CONSTS, "1.20.0",
+ ISSUE_SOME (29646))
+FEATURE_ACCEPTED ("compile_error", COMPILE_ERROR, "1.20.0", ISSUE_SOME (40872))
+FEATURE_ACCEPTED ("rvalue_static_promotion", RVALUE_STATIC_PROMOTION, "1.21.0",
+ ISSUE_SOME (38865))
+FEATURE_ACCEPTED ("drop_types_in_const", DROP_TYPES_IN_CONST, "1.22.0",
+ ISSUE_SOME (33156))
+FEATURE_ACCEPTED ("abi_sysv64", ABI_SYSV64, "1.24.0", ISSUE_SOME (36167))
+FEATURE_ACCEPTED ("repr_align", REPR_ALIGN, "1.25.0", ISSUE_SOME (33626))
+FEATURE_ACCEPTED ("match_beginning_vert", MATCH_BEGINNING_VERT, "1.25.0",
+ ISSUE_SOME (44101))
+FEATURE_ACCEPTED ("use_nested_groups", USE_NESTED_GROUPS, "1.25.0",
+ ISSUE_SOME (44494))
+FEATURE_ACCEPTED ("const_indexing", CONST_INDEXING, "1.26.0",
+ ISSUE_SOME (29947))
+FEATURE_ACCEPTED ("inclusive_range_syntax", INCLUSIVE_RANGE_SYNTAX, "1.26.0",
+ ISSUE_SOME (28237))
+FEATURE_ACCEPTED ("dotdoteq_in_patterns", DOTDOTEQ_IN_PATTERNS, "1.26.0",
+ ISSUE_SOME (28237))
+FEATURE_ACCEPTED ("termination_trait", TERMINATION_TRAIT, "1.26.0",
+ ISSUE_SOME (43301))
+FEATURE_ACCEPTED ("clone_closures", CLONE_CLOSURES, "1.26.0",
+ ISSUE_SOME (44490))
+FEATURE_ACCEPTED ("copy_closures", COPY_CLOSURES, "1.26.0", ISSUE_SOME (44490))
+FEATURE_ACCEPTED ("universal_impl_trait", UNIVERSAL_IMPL_TRAIT, "1.26.0",
+ ISSUE_SOME (34511))
+FEATURE_ACCEPTED ("conservative_impl_trait", CONSERVATIVE_IMPL_TRAIT, "1.26.0",
+ ISSUE_SOME (34511))
+FEATURE_ACCEPTED ("i128_type", I128_TYPE, "1.26.0", ISSUE_SOME (35118))
+FEATURE_ACCEPTED ("match_default_bindings", MATCH_DEFAULT_BINDINGS, "1.26.0",
+ ISSUE_SOME (42640))
+FEATURE_ACCEPTED ("underscore_lifetimes", UNDERSCORE_LIFETIMES, "1.26.0",
+ ISSUE_SOME (44524))
+FEATURE_ACCEPTED ("generic_param_attrs", GENERIC_PARAM_ATTRS, "1.27.0",
+ ISSUE_SOME (48848))
+FEATURE_ACCEPTED ("cfg_target_feature", CFG_TARGET_FEATURE, "1.27.0",
+ ISSUE_SOME (29717))
+FEATURE_ACCEPTED ("target_feature", TARGET_FEATURE, "1.27.0", ISSUE_NONE)
+FEATURE_ACCEPTED ("dyn_trait", DYN_TRAIT, "1.27.0", ISSUE_SOME (44662))
+FEATURE_ACCEPTED ("fn_must_use", FN_MUST_USE, "1.27.0", ISSUE_SOME (43302))
+FEATURE_ACCEPTED ("macro_lifetime_matcher", MACRO_LIFETIME_MATCHER, "1.27.0",
+ ISSUE_SOME (34303))
+FEATURE_ACCEPTED ("termination_trait_test", TERMINATION_TRAIT_TEST, "1.27.0",
+ ISSUE_SOME (48854))
+FEATURE_ACCEPTED ("global_allocator", GLOBAL_ALLOCATOR, "1.28.0",
+ ISSUE_SOME (27389))
+FEATURE_ACCEPTED ("repr_transparent", REPR_TRANSPARENT, "1.28.0",
+ ISSUE_SOME (43036))
+FEATURE_ACCEPTED ("proc_macro", PROC_MACRO, "1.29.0", ISSUE_SOME (38356))
+FEATURE_ACCEPTED ("non_modrs_mods", NON_MODRS_MODS, "1.30.0",
+ ISSUE_SOME (44660))
+FEATURE_ACCEPTED ("macro_vis_matcher", MACRO_VIS_MATCHER, "1.30.0",
+ ISSUE_SOME (41022))
+FEATURE_ACCEPTED ("use_extern_macros", USE_EXTERN_MACROS, "1.30.0",
+ ISSUE_SOME (35896))
+FEATURE_ACCEPTED ("raw_identifiers", RAW_IDENTIFIERS, "1.30.0",
+ ISSUE_SOME (48589))
+FEATURE_ACCEPTED ("tool_attributes", TOOL_ATTRIBUTES, "1.30.0",
+ ISSUE_SOME (44690))
+FEATURE_ACCEPTED ("proc_macro_path_invoc", PROC_MACRO_PATH_INVOC, "1.30.0",
+ ISSUE_SOME (38356))
+FEATURE_ACCEPTED ("attr_literals", ATTR_LITERALS, "1.30.0", ISSUE_SOME (34981))
+FEATURE_ACCEPTED ("infer_outlives_requirements", INFER_OUTLIVES_REQUIREMENTS,
+ "1.30.0", ISSUE_SOME (44493))
+FEATURE_ACCEPTED ("panic_handler", PANIC_HANDLER, "1.30.0", ISSUE_SOME (44489))
+FEATURE_ACCEPTED ("used", USED, "1.30.0", ISSUE_SOME (40289))
+FEATURE_ACCEPTED ("crate_in_paths", CRATE_IN_PATHS, "1.30.0",
+ ISSUE_SOME (45477))
+FEATURE_ACCEPTED ("extern_absolute_paths", EXTERN_ABSOLUTE_PATHS, "1.30.0",
+ ISSUE_SOME (44660))
+FEATURE_ACCEPTED ("extern_prelude", EXTERN_PRELUDE, "1.30.0",
+ ISSUE_SOME (44660))
+FEATURE_ACCEPTED ("pattern_parentheses", PATTERN_PARENTHESES, "1.31.0",
+ ISSUE_SOME (51087))
+FEATURE_ACCEPTED ("min_const_fn", MIN_CONST_FN, "1.31.0", ISSUE_SOME (53555))
+FEATURE_ACCEPTED ("tool_lints", TOOL_LINTS, "1.31.0", ISSUE_SOME (44690))
+FEATURE_ACCEPTED ("impl_header_lifetime_elision", IMPL_HEADER_LIFETIME_ELISION,
+ "1.31.0", ISSUE_SOME (15872))
+FEATURE_ACCEPTED ("extern_crate_item_prelude", EXTERN_CRATE_ITEM_PRELUDE,
+ "1.31.0", ISSUE_SOME (55599))
+FEATURE_ACCEPTED ("macro_literal_matcher", MACRO_LITERAL_MATCHER, "1.32.0",
+ ISSUE_SOME (35625))
+FEATURE_ACCEPTED ("macro_at_most_once_rep", MACRO_AT_MOST_ONCE_REP, "1.32.0",
+ ISSUE_SOME (48075))
+FEATURE_ACCEPTED ("self_struct_ctor", SELF_STRUCT_CTOR, "1.32.0",
+ ISSUE_SOME (51994))
+FEATURE_ACCEPTED ("self_in_typedefs", SELF_IN_TYPEDEFS, "1.32.0",
+ ISSUE_SOME (49303))
+FEATURE_ACCEPTED ("uniform_paths", UNIFORM_PATHS, "1.32.0", ISSUE_SOME (53130))
+FEATURE_ACCEPTED ("exhaustive_integer_patterns", EXHAUSTIVE_INTEGER_PATTERNS,
+ "1.33.0", ISSUE_SOME (50907))
+FEATURE_ACCEPTED ("underscore_imports", UNDERSCORE_IMPORTS, "1.33.0",
+ ISSUE_SOME (48216))
+FEATURE_ACCEPTED ("repr_packed", REPR_PACKED, "1.33.0", ISSUE_SOME (33158))
+FEATURE_ACCEPTED ("irrefutable_let_patterns", IRREFUTABLE_LET_PATTERNS,
+ "1.33.0", ISSUE_SOME (44495))
+FEATURE_ACCEPTED ("min_const_unsafe_fn", MIN_CONST_UNSAFE_FN, "1.33.0",
+ ISSUE_SOME (55607))
+FEATURE_ACCEPTED ("const_let", CONST_LET, "1.33.0", ISSUE_SOME (48821))
+FEATURE_ACCEPTED ("cfg_attr_multi", CFG_ATTR_MULTI, "1.33.0",
+ ISSUE_SOME (54881))
+FEATURE_ACCEPTED ("if_while_or_patterns", IF_WHILE_OR_PATTERNS, "1.33.0",
+ ISSUE_SOME (48215))
+FEATURE_ACCEPTED ("cfg_target_vendor", CFG_TARGET_VENDOR, "1.33.0",
+ ISSUE_SOME (29718))
+FEATURE_ACCEPTED ("extern_crate_self", EXTERN_CRATE_SELF, "1.34.0",
+ ISSUE_SOME (56409))
+FEATURE_ACCEPTED ("unrestricted_attribute_tokens",
+ UNRESTRICTED_ATTRIBUTE_TOKENS, "1.34.0", ISSUE_SOME (55208))
+FEATURE_ACCEPTED ("type_alias_enum_variants", TYPE_ALIAS_ENUM_VARIANTS,
+ "1.37.0", ISSUE_SOME (49683))
+FEATURE_ACCEPTED ("repr_align_enum", REPR_ALIGN_ENUM, "1.37.0",
+ ISSUE_SOME (57996))
+FEATURE_ACCEPTED ("underscore_const_names", UNDERSCORE_CONST_NAMES, "1.37.0",
+ ISSUE_SOME (54912))
+FEATURE_ACCEPTED ("async_await", ASYNC_AWAIT, "1.39.0", ISSUE_SOME (50547))
+FEATURE_ACCEPTED ("bind_by_move_pattern_guards", BIND_BY_MOVE_PATTERN_GUARDS,
+ "1.39.0", ISSUE_SOME (15287))
+FEATURE_ACCEPTED ("param_attrs", PARAM_ATTRS, "1.39.0", ISSUE_SOME (60406))
+FEATURE_ACCEPTED ("macros_in_extern", MACROS_IN_EXTERN, "1.40.0",
+ ISSUE_SOME (49476))
+FEATURE_ACCEPTED ("non_exhaustive", NON_EXHAUSTIVE, "1.40.0",
+ ISSUE_SOME (44109))
+FEATURE_ACCEPTED ("const_constructor", CONST_CONSTRUCTOR, "1.40.0",
+ ISSUE_SOME (61456))
+FEATURE_ACCEPTED ("cfg_doctest", CFG_DOCTEST, "1.40.0", ISSUE_SOME (62210))
+FEATURE_ACCEPTED ("re_rebalance_coherence", RE_REBALANCE_COHERENCE, "1.41.0",
+ ISSUE_SOME (55437))
+FEATURE_ACCEPTED ("transparent_enums", TRANSPARENT_ENUMS, "1.42.0",
+ ISSUE_SOME (60405))
+FEATURE_ACCEPTED ("slice_patterns", SLICE_PATTERNS, "1.42.0",
+ ISSUE_SOME (62254))
+FEATURE_ACCEPTED ("const_if_match", CONST_IF_MATCH, "1.46.0",
+ ISSUE_SOME (49146))
+FEATURE_ACCEPTED ("const_loop", CONST_LOOP, "1.46.0", ISSUE_SOME (52000))
+FEATURE_ACCEPTED ("track_caller", TRACK_CALLER, "1.46.0", ISSUE_SOME (47809))
+FEATURE_ACCEPTED ("doc_alias", DOC_ALIAS, "1.48.0", ISSUE_SOME (50146))
+FEATURE_ACCEPTED ("move_ref_pattern", MOVE_REF_PATTERN, "1.48.0",
+ ISSUE_SOME (68354))
+FEATURE_ACTIVE ("rustc_attrs", RUSTC_ATTRS, "1.0.0", ISSUE_NONE, EDITION_NONE)
+FEATURE_ACTIVE ("rustc_private", RUSTC_PRIVATE, "1.0.0", ISSUE_SOME (27812),
+ EDITION_NONE)
+FEATURE_ACTIVE ("intrinsics", INTRINSICS, "1.0.0", ISSUE_NONE, EDITION_NONE)
+FEATURE_ACTIVE ("lang_items", LANG_ITEMS, "1.0.0", ISSUE_NONE, EDITION_NONE)
+FEATURE_ACTIVE ("staged_api", STAGED_API, "1.0.0", ISSUE_NONE, EDITION_NONE)
+FEATURE_ACTIVE ("allow_internal_unstable", ALLOW_INTERNAL_UNSTABLE, "1.0.0",
+ ISSUE_NONE, EDITION_NONE)
+FEATURE_ACTIVE ("allow_internal_unsafe", ALLOW_INTERNAL_UNSAFE, "1.0.0",
+ ISSUE_NONE, EDITION_NONE)
+FEATURE_ACTIVE ("link_llvm_intrinsics", LINK_LLVM_INTRINSICS, "1.0.0",
+ ISSUE_SOME (29602), EDITION_NONE)
+FEATURE_ACTIVE ("box_syntax", BOX_SYNTAX, "1.0.0", ISSUE_SOME (49733),
+ EDITION_NONE)
+FEATURE_ACTIVE ("main", MAIN, "1.0.0", ISSUE_SOME (29634), EDITION_NONE)
+FEATURE_ACTIVE ("start", START, "1.0.0", ISSUE_SOME (29633), EDITION_NONE)
+FEATURE_ACTIVE ("fundamental", FUNDAMENTAL, "1.0.0", ISSUE_SOME (29635),
+ EDITION_NONE)
+FEATURE_ACTIVE ("unboxed_closures", UNBOXED_CLOSURES, "1.0.0",
+ ISSUE_SOME (29625), EDITION_NONE)
+FEATURE_ACTIVE ("linkage", LINKAGE, "1.0.0", ISSUE_SOME (29603), EDITION_NONE)
+FEATURE_ACTIVE ("optin_builtin_traits", OPTIN_BUILTIN_TRAITS, "1.0.0",
+ ISSUE_SOME (13231), EDITION_NONE)
+FEATURE_ACTIVE ("box_patterns", BOX_PATTERNS, "1.0.0", ISSUE_SOME (29641),
+ EDITION_NONE)
+FEATURE_ACTIVE ("prelude_import", PRELUDE_IMPORT, "1.2.0", ISSUE_NONE,
+ EDITION_NONE)
+FEATURE_ACTIVE ("omit_gdb_pretty_printer_section",
+ OMIT_GDB_PRETTY_PRINTER_SECTION, "1.5.0", ISSUE_NONE,
+ EDITION_NONE)
+FEATURE_ACTIVE ("abi_vectorcall", ABI_VECTORCALL, "1.7.0", ISSUE_NONE,
+ EDITION_NONE)
+FEATURE_ACTIVE ("structural_match", STRUCTURAL_MATCH, "1.8.0",
+ ISSUE_SOME (31434), EDITION_NONE)
+FEATURE_ACTIVE ("dropck_eyepatch", DROPCK_EYEPATCH, "1.10.0",
+ ISSUE_SOME (34761), EDITION_NONE)
+FEATURE_ACTIVE ("panic_runtime", PANIC_RUNTIME, "1.10.0", ISSUE_SOME (32837),
+ EDITION_NONE)
+FEATURE_ACTIVE ("needs_panic_runtime", NEEDS_PANIC_RUNTIME, "1.10.0",
+ ISSUE_SOME (32837), EDITION_NONE)
+FEATURE_ACTIVE ("compiler_builtins", COMPILER_BUILTINS, "1.13.0", ISSUE_NONE,
+ EDITION_NONE)
+FEATURE_ACTIVE ("abi_unadjusted", ABI_UNADJUSTED, "1.16.0", ISSUE_NONE,
+ EDITION_NONE)
+FEATURE_ACTIVE ("profiler_runtime", PROFILER_RUNTIME, "1.18.0", ISSUE_NONE,
+ EDITION_NONE)
+FEATURE_ACTIVE ("abi_thiscall", ABI_THISCALL, "1.19.0", ISSUE_NONE,
+ EDITION_NONE)
+FEATURE_ACTIVE ("allocator_internals", ALLOCATOR_INTERNALS, "1.20.0",
+ ISSUE_NONE, EDITION_NONE)
+FEATURE_ACTIVE ("test_2018_feature", TEST_2018_FEATURE, "1.31.0", ISSUE_NONE,
+ EDITION_2018)
+FEATURE_ACTIVE ("no_niche", NO_NICHE, "1.42.0", ISSUE_NONE, EDITION_NONE)
+FEATURE_ACTIVE ("rustc_allow_const_fn_unstable", RUSTC_ALLOW_CONST_FN_UNSTABLE,
+ "1.49.0", ISSUE_SOME (69399), EDITION_NONE)
+FEATURE_ACTIVE ("arm_target_feature", ARM_TARGET_FEATURE, "1.27.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("aarch64_target_feature", AARCH64_TARGET_FEATURE, "1.27.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("hexagon_target_feature", HEXAGON_TARGET_FEATURE, "1.27.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("powerpc_target_feature", POWERPC_TARGET_FEATURE, "1.27.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("mips_target_feature", MIPS_TARGET_FEATURE, "1.27.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("avx512_target_feature", AVX512_TARGET_FEATURE, "1.27.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("sse4a_target_feature", SSE4A_TARGET_FEATURE, "1.27.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("tbm_target_feature", TBM_TARGET_FEATURE, "1.27.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("wasm_target_feature", WASM_TARGET_FEATURE, "1.30.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("adx_target_feature", ADX_TARGET_FEATURE, "1.32.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("cmpxchg16b_target_feature", CMPXCHG16B_TARGET_FEATURE,
+ "1.32.0", ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("movbe_target_feature", MOVBE_TARGET_FEATURE, "1.34.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("rtm_target_feature", RTM_TARGET_FEATURE, "1.35.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("f16c_target_feature", F16C_TARGET_FEATURE, "1.36.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("riscv_target_feature", RISCV_TARGET_FEATURE, "1.45.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("ermsb_target_feature", ERMSB_TARGET_FEATURE, "1.49.0",
+ ISSUE_SOME (44839), EDITION_NONE)
+FEATURE_ACTIVE ("link_args", LINK_ARGS, "1.0.0", ISSUE_SOME (29596),
+ EDITION_NONE)
+FEATURE_ACTIVE ("non_ascii_idents", NON_ASCII_IDENTS, "1.0.0",
+ ISSUE_SOME (55467), EDITION_NONE)
+FEATURE_ACTIVE ("plugin_registrar", PLUGIN_REGISTRAR, "1.0.0",
+ ISSUE_SOME (29597), EDITION_NONE)
+FEATURE_ACTIVE ("plugin", PLUGIN, "1.0.0", ISSUE_SOME (29597), EDITION_NONE)
+FEATURE_ACTIVE ("thread_local", THREAD_LOCAL, "1.0.0", ISSUE_SOME (29594),
+ EDITION_NONE)
+FEATURE_ACTIVE ("simd_ffi", SIMD_FFI, "1.0.0", ISSUE_SOME (27731), EDITION_NONE)
+FEATURE_ACTIVE ("nll", NLL, "1.0.0", ISSUE_SOME (43234), EDITION_NONE)
+FEATURE_ACTIVE ("const_fn", CONST_FN, "1.2.0", ISSUE_SOME (57563), EDITION_NONE)
+FEATURE_ACTIVE ("associated_type_defaults", ASSOCIATED_TYPE_DEFAULTS, "1.2.0",
+ ISSUE_SOME (29661), EDITION_NONE)
+FEATURE_ACTIVE ("no_core", NO_CORE, "1.3.0", ISSUE_SOME (29639), EDITION_NONE)
+FEATURE_ACTIVE ("default_type_parameter_fallback",
+ DEFAULT_TYPE_PARAMETER_FALLBACK, "1.3.0", ISSUE_SOME (27336),
+ EDITION_NONE)
+FEATURE_ACTIVE ("repr_simd", REPR_SIMD, "1.4.0", ISSUE_SOME (27731),
+ EDITION_NONE)
+FEATURE_ACTIVE ("platform_intrinsics", PLATFORM_INTRINSICS, "1.4.0",
+ ISSUE_SOME (27731), EDITION_NONE)
+FEATURE_ACTIVE ("unwind_attributes", UNWIND_ATTRIBUTES, "1.4.0",
+ ISSUE_SOME (58760), EDITION_NONE)
+FEATURE_ACTIVE ("stmt_expr_attributes", STMT_EXPR_ATTRIBUTES, "1.6.0",
+ ISSUE_SOME (15701), EDITION_NONE)
+FEATURE_ACTIVE ("type_ascription", TYPE_ASCRIPTION, "1.6.0", ISSUE_SOME (23416),
+ EDITION_NONE)
+FEATURE_ACTIVE ("cfg_target_thread_local", CFG_TARGET_THREAD_LOCAL, "1.7.0",
+ ISSUE_SOME (29594), EDITION_NONE)
+FEATURE_ACTIVE ("specialization", SPECIALIZATION, "1.7.0", ISSUE_SOME (31844),
+ EDITION_NONE)
+FEATURE_ACTIVE ("min_specialization", MIN_SPECIALIZATION, "1.7.0",
+ ISSUE_SOME (31844), EDITION_NONE)
+FEATURE_ACTIVE ("naked_functions", NAKED_FUNCTIONS, "1.9.0", ISSUE_SOME (32408),
+ EDITION_NONE)
+FEATURE_ACTIVE ("cfg_target_has_atomic", CFG_TARGET_HAS_ATOMIC, "1.9.0",
+ ISSUE_SOME (32976), EDITION_NONE)
+FEATURE_ACTIVE ("exclusive_range_pattern", EXCLUSIVE_RANGE_PATTERN, "1.11.0",
+ ISSUE_SOME (37854), EDITION_NONE)
+FEATURE_ACTIVE ("never_type", NEVER_TYPE, "1.13.0", ISSUE_SOME (35121),
+ EDITION_NONE)
+FEATURE_ACTIVE ("exhaustive_patterns", EXHAUSTIVE_PATTERNS, "1.13.0",
+ ISSUE_SOME (51085), EDITION_NONE)
+FEATURE_ACTIVE ("untagged_unions", UNTAGGED_UNIONS, "1.13.0",
+ ISSUE_SOME (55149), EDITION_NONE)
+FEATURE_ACTIVE ("link_cfg", LINK_CFG, "1.14.0", ISSUE_SOME (37406),
+ EDITION_NONE)
+FEATURE_ACTIVE ("abi_ptx", ABI_PTX, "1.15.0", ISSUE_SOME (38788), EDITION_NONE)
+FEATURE_ACTIVE ("repr128", REPR128, "1.16.0", ISSUE_SOME (56071), EDITION_NONE)
+FEATURE_ACTIVE ("static_nobundle", STATIC_NOBUNDLE, "1.16.0",
+ ISSUE_SOME (37403), EDITION_NONE)
+FEATURE_ACTIVE ("abi_msp430_interrupt", ABI_MSP430_INTERRUPT, "1.16.0",
+ ISSUE_SOME (38487), EDITION_NONE)
+FEATURE_ACTIVE ("decl_macro", DECL_MACRO, "1.17.0", ISSUE_SOME (39412),
+ EDITION_NONE)
+FEATURE_ACTIVE ("abi_x86_interrupt", ABI_X86_INTERRUPT, "1.17.0",
+ ISSUE_SOME (40180), EDITION_NONE)
+FEATURE_ACTIVE ("allow_fail", ALLOW_FAIL, "1.19.0", ISSUE_SOME (46488),
+ EDITION_NONE)
+FEATURE_ACTIVE ("unsized_tuple_coercion", UNSIZED_TUPLE_COERCION, "1.20.0",
+ ISSUE_SOME (42877), EDITION_NONE)
+FEATURE_ACTIVE ("generators", GENERATORS, "1.21.0", ISSUE_SOME (43122),
+ EDITION_NONE)
+FEATURE_ACTIVE ("doc_cfg", DOC_CFG, "1.21.0", ISSUE_SOME (43781), EDITION_NONE)
+FEATURE_ACTIVE ("doc_masked", DOC_MASKED, "1.21.0", ISSUE_SOME (44027),
+ EDITION_NONE)
+FEATURE_ACTIVE ("doc_spotlight", DOC_SPOTLIGHT, "1.22.0", ISSUE_SOME (45040),
+ EDITION_NONE)
+FEATURE_ACTIVE ("external_doc", EXTERNAL_DOC, "1.22.0", ISSUE_SOME (44732),
+ EDITION_NONE)
+FEATURE_ACTIVE ("crate_visibility_modifier", CRATE_VISIBILITY_MODIFIER,
+ "1.23.0", ISSUE_SOME (53120), EDITION_NONE)
+FEATURE_ACTIVE ("extern_types", EXTERN_TYPES, "1.23.0", ISSUE_SOME (43467),
+ EDITION_NONE)
+FEATURE_ACTIVE ("arbitrary_self_types", ARBITRARY_SELF_TYPES, "1.23.0",
+ ISSUE_SOME (44874), EDITION_NONE)
+FEATURE_ACTIVE ("in_band_lifetimes", IN_BAND_LIFETIMES, "1.23.0",
+ ISSUE_SOME (44524), EDITION_NONE)
+FEATURE_ACTIVE ("generic_associated_types", GENERIC_ASSOCIATED_TYPES, "1.23.0",
+ ISSUE_SOME (44265), EDITION_NONE)
+FEATURE_ACTIVE ("trait_alias", TRAIT_ALIAS, "1.24.0", ISSUE_SOME (41517),
+ EDITION_NONE)
+FEATURE_ACTIVE ("infer_static_outlives_requirements",
+ INFER_STATIC_OUTLIVES_REQUIREMENTS, "1.26.0",
+ ISSUE_SOME (54185), EDITION_NONE)
+FEATURE_ACTIVE ("const_fn_union", CONST_FN_UNION, "1.27.0", ISSUE_SOME (51909),
+ EDITION_NONE)
+FEATURE_ACTIVE ("const_raw_ptr_to_usize_cast", CONST_RAW_PTR_TO_USIZE_CAST,
+ "1.27.0", ISSUE_SOME (51910), EDITION_NONE)
+FEATURE_ACTIVE ("const_raw_ptr_deref", CONST_RAW_PTR_DEREF, "1.27.0",
+ ISSUE_SOME (51911), EDITION_NONE)
+FEATURE_ACTIVE ("trivial_bounds", TRIVIAL_BOUNDS, "1.28.0", ISSUE_SOME (48214),
+ EDITION_NONE)
+FEATURE_ACTIVE ("label_break_value", LABEL_BREAK_VALUE, "1.28.0",
+ ISSUE_SOME (48594), EDITION_NONE)
+FEATURE_ACTIVE ("doc_keyword", DOC_KEYWORD, "1.28.0", ISSUE_SOME (51315),
+ EDITION_NONE)
+FEATURE_ACTIVE ("try_blocks", TRY_BLOCKS, "1.29.0", ISSUE_SOME (31436),
+ EDITION_NONE)
+FEATURE_ACTIVE ("alloc_error_handler", ALLOC_ERROR_HANDLER, "1.29.0",
+ ISSUE_SOME (51540), EDITION_NONE)
+FEATURE_ACTIVE ("abi_amdgpu_kernel", ABI_AMDGPU_KERNEL, "1.29.0",
+ ISSUE_SOME (51575), EDITION_NONE)
+FEATURE_ACTIVE ("const_panic", CONST_PANIC, "1.30.0", ISSUE_SOME (51999),
+ EDITION_NONE)
+FEATURE_ACTIVE ("marker_trait_attr", MARKER_TRAIT_ATTR, "1.30.0",
+ ISSUE_SOME (29864), EDITION_NONE)
+FEATURE_ACTIVE ("proc_macro_hygiene", PROC_MACRO_HYGIENE, "1.30.0",
+ ISSUE_SOME (54727), EDITION_NONE)
+FEATURE_ACTIVE ("unsized_locals", UNSIZED_LOCALS, "1.30.0", ISSUE_SOME (48055),
+ EDITION_NONE)
+FEATURE_ACTIVE ("custom_test_frameworks", CUSTOM_TEST_FRAMEWORKS, "1.30.0",
+ ISSUE_SOME (50297), EDITION_NONE)
+FEATURE_ACTIVE ("custom_inner_attributes", CUSTOM_INNER_ATTRIBUTES, "1.30.0",
+ ISSUE_SOME (54726), EDITION_NONE)
+FEATURE_ACTIVE ("impl_trait_in_bindings", IMPL_TRAIT_IN_BINDINGS, "1.30.0",
+ ISSUE_SOME (63065), EDITION_NONE)
+FEATURE_ACTIVE ("lint_reasons", LINT_REASONS, "1.31.0", ISSUE_SOME (54503),
+ EDITION_NONE)
+FEATURE_ACTIVE ("precise_pointer_size_matching", PRECISE_POINTER_SIZE_MATCHING,
+ "1.32.0", ISSUE_SOME (56354), EDITION_NONE)
+FEATURE_ACTIVE ("ffi_returns_twice", FFI_RETURNS_TWICE, "1.34.0",
+ ISSUE_SOME (58314), EDITION_NONE)
+FEATURE_ACTIVE ("const_generics", CONST_GENERICS, "1.34.0", ISSUE_SOME (44580),
+ EDITION_NONE)
+FEATURE_ACTIVE ("optimize_attribute", OPTIMIZE_ATTRIBUTE, "1.34.0",
+ ISSUE_SOME (54882), EDITION_NONE)
+FEATURE_ACTIVE ("c_variadic", C_VARIADIC, "1.34.0", ISSUE_SOME (44930),
+ EDITION_NONE)
+FEATURE_ACTIVE ("associated_type_bounds", ASSOCIATED_TYPE_BOUNDS, "1.34.0",
+ ISSUE_SOME (52662), EDITION_NONE)
+FEATURE_ACTIVE ("let_chains", LET_CHAINS, "1.37.0", ISSUE_SOME (53667),
+ EDITION_NONE)
+FEATURE_ACTIVE ("transparent_unions", TRANSPARENT_UNIONS, "1.37.0",
+ ISSUE_SOME (60405), EDITION_NONE)
+FEATURE_ACTIVE ("arbitrary_enum_discriminant", ARBITRARY_ENUM_DISCRIMINANT,
+ "1.37.0", ISSUE_SOME (60553), EDITION_NONE)
+FEATURE_ACTIVE ("member_constraints", MEMBER_CONSTRAINTS, "1.37.0",
+ ISSUE_SOME (61997), EDITION_NONE)
+FEATURE_ACTIVE ("async_closure", ASYNC_CLOSURE, "1.37.0", ISSUE_SOME (62290),
+ EDITION_NONE)
+FEATURE_ACTIVE ("const_in_array_repeat_expressions",
+ CONST_IN_ARRAY_REPEAT_EXPRESSIONS, "1.37.0", ISSUE_SOME (49147),
+ EDITION_NONE)
+FEATURE_ACTIVE ("type_alias_impl_trait", TYPE_ALIAS_IMPL_TRAIT, "1.38.0",
+ ISSUE_SOME (63063), EDITION_NONE)
+FEATURE_ACTIVE ("or_patterns", OR_PATTERNS, "1.38.0", ISSUE_SOME (54883),
+ EDITION_NONE)
+FEATURE_ACTIVE ("const_extern_fn", CONST_EXTERN_FN, "1.40.0",
+ ISSUE_SOME (64926), EDITION_NONE)
+FEATURE_ACTIVE ("raw_dylib", RAW_DYLIB, "1.40.0", ISSUE_SOME (58713),
+ EDITION_NONE)
+FEATURE_ACTIVE ("object_safe_for_dispatch", OBJECT_SAFE_FOR_DISPATCH, "1.40.0",
+ ISSUE_SOME (43561), EDITION_NONE)
+FEATURE_ACTIVE ("abi_efiapi", ABI_EFIAPI, "1.40.0", ISSUE_SOME (65815),
+ EDITION_NONE)
+FEATURE_ACTIVE ("raw_ref_op", RAW_REF_OP, "1.41.0", ISSUE_SOME (64490),
+ EDITION_NONE)
+FEATURE_ACTIVE ("never_type_fallback", NEVER_TYPE_FALLBACK, "1.41.0",
+ ISSUE_SOME (65992), EDITION_NONE)
+FEATURE_ACTIVE ("register_attr", REGISTER_ATTR, "1.41.0", ISSUE_SOME (66080),
+ EDITION_NONE)
+FEATURE_ACTIVE ("register_tool", REGISTER_TOOL, "1.41.0", ISSUE_SOME (66079),
+ EDITION_NONE)
+FEATURE_ACTIVE ("cfg_sanitize", CFG_SANITIZE, "1.41.0", ISSUE_SOME (39699),
+ EDITION_NONE)
+FEATURE_ACTIVE ("half_open_range_patterns", HALF_OPEN_RANGE_PATTERNS, "1.41.0",
+ ISSUE_SOME (67264), EDITION_NONE)
+FEATURE_ACTIVE ("const_mut_refs", CONST_MUT_REFS, "1.41.0", ISSUE_SOME (57349),
+ EDITION_NONE)
+FEATURE_ACTIVE ("bindings_after_at", BINDINGS_AFTER_AT, "1.41.0",
+ ISSUE_SOME (65490), EDITION_NONE)
+FEATURE_ACTIVE ("const_trait_impl", CONST_TRAIT_IMPL, "1.42.0",
+ ISSUE_SOME (67792), EDITION_NONE)
+FEATURE_ACTIVE ("const_trait_bound_opt_out", CONST_TRAIT_BOUND_OPT_OUT,
+ "1.42.0", ISSUE_SOME (67794), EDITION_NONE)
+FEATURE_ACTIVE ("no_sanitize", NO_SANITIZE, "1.42.0", ISSUE_SOME (39699),
+ EDITION_NONE)
+FEATURE_ACTIVE ("const_eval_limit", CONST_EVAL_LIMIT, "1.43.0",
+ ISSUE_SOME (67217), EDITION_NONE)
+FEATURE_ACTIVE ("negative_impls", NEGATIVE_IMPLS, "1.44.0", ISSUE_SOME (68318),
+ EDITION_NONE)
+FEATURE_ACTIVE ("target_feature_11", TARGET_FEATURE_11, "1.45.0",
+ ISSUE_SOME (69098), EDITION_NONE)
+FEATURE_ACTIVE ("cfg_version", CFG_VERSION, "1.45.0", ISSUE_SOME (64796),
+ EDITION_NONE)
+FEATURE_ACTIVE ("ffi_pure", FFI_PURE, "1.45.0", ISSUE_SOME (58329),
+ EDITION_NONE)
+FEATURE_ACTIVE ("ffi_const", FFI_CONST, "1.45.0", ISSUE_SOME (58328),
+ EDITION_NONE)
+FEATURE_ACTIVE ("unsafe_block_in_unsafe_fn", UNSAFE_BLOCK_IN_UNSAFE_FN,
+ "1.45.0", ISSUE_SOME (71668), EDITION_NONE)
+FEATURE_ACTIVE ("abi_avr_interrupt", ABI_AVR_INTERRUPT, "1.45.0",
+ ISSUE_SOME (69664), EDITION_NONE)
+FEATURE_ACTIVE ("const_precise_live_drops", CONST_PRECISE_LIVE_DROPS, "1.46.0",
+ ISSUE_SOME (73255), EDITION_NONE)
+FEATURE_ACTIVE ("format_args_capture", FORMAT_ARGS_CAPTURE, "1.46.0",
+ ISSUE_SOME (67984), EDITION_NONE)
+FEATURE_ACTIVE ("lazy_normalization_consts", LAZY_NORMALIZATION_CONSTS,
+ "1.46.0", ISSUE_SOME (72219), EDITION_NONE)
+FEATURE_ACTIVE ("const_fn_transmute", CONST_FN_TRANSMUTE, "1.46.0",
+ ISSUE_SOME (53605), EDITION_NONE)
+FEATURE_ACTIVE ("min_const_generics", MIN_CONST_GENERICS, "1.47.0",
+ ISSUE_SOME (74878), EDITION_NONE)
+FEATURE_ACTIVE ("if_let_guard", IF_LET_GUARD, "1.47.0", ISSUE_SOME (51114),
+ EDITION_NONE)
+FEATURE_ACTIVE ("const_evaluatable_checked", CONST_EVALUATABLE_CHECKED,
+ "1.48.0", ISSUE_SOME (76560), EDITION_NONE)
+FEATURE_ACTIVE ("const_fn_floating_point_arithmetic",
+ CONST_FN_FLOATING_POINT_ARITHMETIC, "1.48.0",
+ ISSUE_SOME (57241), EDITION_NONE)
+FEATURE_ACTIVE ("const_fn_fn_ptr_basics", CONST_FN_FN_PTR_BASICS, "1.48.0",
+ ISSUE_SOME (57563), EDITION_NONE)
+FEATURE_ACTIVE ("cmse_nonsecure_entry", CMSE_NONSECURE_ENTRY, "1.48.0",
+ ISSUE_SOME (75835), EDITION_NONE)
+FEATURE_ACTIVE ("default_alloc_error_handler", DEFAULT_ALLOC_ERROR_HANDLER,
+ "1.48.0", ISSUE_SOME (66741), EDITION_NONE)
+FEATURE_ACTIVE ("const_impl_trait", CONST_IMPL_TRAIT, "1.48.0",
+ ISSUE_SOME (77463), EDITION_NONE)
+FEATURE_ACTIVE ("isa_attribute", ISA_ATTRIBUTE, "1.48.0", ISSUE_SOME (74727),
+ EDITION_NONE)
+FEATURE_ACTIVE ("inline_const", INLINE_CONST, "1.49.0", ISSUE_SOME (76001),
+ EDITION_NONE)
+FEATURE_ACTIVE ("unsized_fn_params", UNSIZED_FN_PARAMS, "1.49.0",
+ ISSUE_SOME (48055), EDITION_NONE)
+FEATURE_ACTIVE ("destructuring_assignment", DESTRUCTURING_ASSIGNMENT, "1.49.0",
+ ISSUE_SOME (71126), EDITION_NONE)
+FEATURE_ACTIVE ("cfg_panic", CFG_PANIC, "1.49.0", ISSUE_SOME (77443),
+ EDITION_NONE)
+FEATURE_REMOVED ("import_shadowing", IMPORT_SHADOWING, "1.0.0", ISSUE_NONE,
+ REASON_NONE)
+FEATURE_REMOVED ("managed_boxes", MANAGED_BOXES, "1.0.0", ISSUE_NONE,
+ REASON_NONE)
+FEATURE_REMOVED ("negate_unsigned", NEGATE_UNSIGNED, "1.0.0",
+ ISSUE_SOME (29645), REASON_NONE)
+FEATURE_REMOVED ("reflect", REFLECT, "1.0.0", ISSUE_SOME (27749), REASON_NONE)
+FEATURE_REMOVED ("opt_out_copy", OPT_OUT_COPY, "1.0.0", ISSUE_NONE, REASON_NONE)
+FEATURE_REMOVED ("quad_precision_float", QUAD_PRECISION_FLOAT, "1.0.0",
+ ISSUE_NONE, REASON_NONE)
+FEATURE_REMOVED ("struct_inherit", STRUCT_INHERIT, "1.0.0", ISSUE_NONE,
+ REASON_NONE)
+FEATURE_REMOVED ("test_removed_feature", TEST_REMOVED_FEATURE, "1.0.0",
+ ISSUE_NONE, REASON_NONE)
+FEATURE_REMOVED ("visible_private_types", VISIBLE_PRIVATE_TYPES, "1.0.0",
+ ISSUE_NONE, REASON_NONE)
+FEATURE_REMOVED ("unsafe_no_drop_flag", UNSAFE_NO_DROP_FLAG, "1.0.0",
+ ISSUE_NONE, REASON_NONE)
+FEATURE_REMOVED ("unmarked_api", UNMARKED_API, "1.0.0", ISSUE_NONE, REASON_NONE)
+FEATURE_REMOVED ("allocator", ALLOCATOR, "1.0.0", ISSUE_NONE, REASON_NONE)
+FEATURE_REMOVED ("simd", SIMD, "1.0.0", ISSUE_SOME (27731),
+ REASON_SOME ("removed in favor of `#[repr(simd)]`"))
+FEATURE_REMOVED ("advanced_slice_patterns", ADVANCED_SLICE_PATTERNS, "1.0.0",
+ ISSUE_SOME (62254),
+ REASON_SOME ("merged into `#![feature(slice_patterns)]`"))
+FEATURE_REMOVED ("macro_reexport", MACRO_REEXPORT, "1.0.0", ISSUE_SOME (29638),
+ REASON_SOME ("subsumed by `pub use`"))
+FEATURE_REMOVED (
+ "custom_attribute", CUSTOM_ATTRIBUTE, "1.0.0", ISSUE_SOME (29642),
+ REASON_SOME (
+ "removed in favor of `#![register_tool]` and `#![register_attr]`"))
+FEATURE_REMOVED ("pushpop_unsafe", PUSHPOP_UNSAFE, "1.2.0", ISSUE_NONE,
+ REASON_NONE)
+FEATURE_REMOVED ("needs_allocator", NEEDS_ALLOCATOR, "1.4.0",
+ ISSUE_SOME (27389),
+ REASON_SOME ("subsumed by `#![feature(allocator_internals)]`"))
+FEATURE_REMOVED ("sanitizer_runtime", SANITIZER_RUNTIME, "1.17.0", ISSUE_NONE,
+ REASON_NONE)
+FEATURE_REMOVED ("proc_macro_mod", PROC_MACRO_MOD, "1.27.0", ISSUE_SOME (54727),
+ REASON_SOME ("subsumed by `#![feature(proc_macro_hygiene)]`"))
+FEATURE_REMOVED ("proc_macro_expr", PROC_MACRO_EXPR, "1.27.0",
+ ISSUE_SOME (54727),
+ REASON_SOME ("subsumed by `#![feature(proc_macro_hygiene)]`"))
+FEATURE_REMOVED ("proc_macro_non_items", PROC_MACRO_NON_ITEMS, "1.27.0",
+ ISSUE_SOME (54727),
+ REASON_SOME ("subsumed by `#![feature(proc_macro_hygiene)]`"))
+FEATURE_REMOVED ("proc_macro_gen", PROC_MACRO_GEN, "1.27.0", ISSUE_SOME (54727),
+ REASON_SOME ("subsumed by `#![feature(proc_macro_hygiene)]`"))
+FEATURE_REMOVED ("panic_implementation", PANIC_IMPLEMENTATION, "1.28.0",
+ ISSUE_SOME (44489),
+ REASON_SOME ("subsumed by `#[panic_handler]`"))
+FEATURE_REMOVED ("custom_derive", CUSTOM_DERIVE, "1.32.0", ISSUE_SOME (29644),
+ REASON_SOME ("subsumed by `#[proc_macro_derive]`"))
+FEATURE_REMOVED ("extern_in_paths", EXTERN_IN_PATHS, "1.33.0",
+ ISSUE_SOME (55600),
+ REASON_SOME ("subsumed by `::foo::bar` paths"))
+FEATURE_REMOVED ("quote", QUOTE, "1.33.0", ISSUE_SOME (29601), REASON_NONE)
+FEATURE_REMOVED ("dropck_parametricity", DROPCK_PARAMETRICITY, "1.38.0",
+ ISSUE_SOME (28498), REASON_NONE)
+FEATURE_REMOVED ("await_macro", AWAIT_MACRO, "1.38.0", ISSUE_SOME (50547),
+ REASON_SOME ("subsumed by `.await` syntax"))
+FEATURE_REMOVED (
+ "existential_type", EXISTENTIAL_TYPE, "1.38.0", ISSUE_SOME (63063),
+ REASON_SOME ("removed in favor of `#![feature(type_alias_impl_trait)]`"))
+FEATURE_REMOVED ("rustc_diagnostic_macros", RUSTC_DIAGNOSTIC_MACROS, "1.38.0",
+ ISSUE_NONE, REASON_NONE)
+FEATURE_REMOVED ("on_unimplemented", ON_UNIMPLEMENTED, "1.40.0", ISSUE_NONE,
+ REASON_NONE)
+FEATURE_REMOVED (
+ "overlapping_marker_traits", OVERLAPPING_MARKER_TRAITS, "1.42.0",
+ ISSUE_SOME (29864),
+ REASON_SOME ("removed in favor of `#![feature(marker_trait_attr)]`"))
+FEATURE_REMOVED ("no_debug", F_NO_DEBUG, "1.43.0", ISSUE_SOME (29721),
+ REASON_SOME ("removed due to lack of demand"))
+FEATURE_REMOVED (
+ "const_compare_raw_pointers", CONST_COMPARE_RAW_POINTERS, "1.46.0",
+ ISSUE_SOME (53020),
+ REASON_SOME ("cannot be allowed in const eval in any meaningful way"))
+FEATURE_STABLE_REMOVED ("no_stack_check", NO_STACK_CHECK, "1.0.0", ISSUE_NONE)
diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc b/gcc/rust/checks/errors/feature/rust-feature-gate.cc
index f3daa61..9df822b 100644
--- a/gcc/rust/checks/errors/rust-feature-gate.cc
+++ b/gcc/rust/checks/errors/feature/rust-feature-gate.cc
@@ -34,12 +34,22 @@ FeatureGate::check (AST::Crate &crate)
void
FeatureGate::visit (AST::Crate &crate)
{
- valid_features.clear ();
+ valid_lang_features.clear ();
+ valid_lib_features.clear ();
+
+ // avoid clearing defined features (?)
for (const auto &attr : crate.inner_attrs)
{
if (attr.get_path ().as_string () == "feature")
{
+ // check for empty feature, such as `#![feature], this is an error
+ if (attr.empty_input ())
+ {
+ rust_error_at (attr.get_locus (), ErrorCode::E0556,
+ "malformed %<feature%> attribute input");
+ continue;
+ }
const auto &attr_input = attr.get_attr_input ();
auto type = attr_input.get_attr_input_type ();
if (type == AST::AttrInput::AttrInputType::TOKEN_TREE)
@@ -51,31 +61,47 @@ FeatureGate::visit (AST::Crate &crate)
for (const auto &item : meta_item->get_items ())
{
const auto &name_str = item->as_string ();
- auto tname = Feature::as_name (name_str);
- if (tname.has_value ())
- {
- auto name = tname.value ();
- valid_features.insert (name);
- }
+ // TODO: detect duplicates
+ if (auto tname = Feature::as_name (name_str))
+ valid_lang_features.insert (tname.value ());
else
- rust_error_at (item->get_locus (), ErrorCode::E0635,
- "unknown feature %qs", name_str.c_str ());
+ valid_lib_features.emplace (name_str, item->get_locus ());
}
}
}
}
AST::DefaultASTVisitor::visit (crate);
+
+ for (auto &ent : valid_lib_features)
+ {
+ const std::string &feature = ent.first;
+ location_t locus = ent.second;
+
+ // rustc treats these as valid,
+ // but apparently has special handling for them
+ if (feature == "libc" || feature == "test")
+ continue;
+
+ if (defined_lib_features.find (feature) != defined_lib_features.end ())
+ {
+ // TODO: emit warning if stable
+ continue;
+ }
+
+ rust_error_at (locus, ErrorCode::E0635, "unknown feature %qs",
+ feature.c_str ());
+ }
}
void
FeatureGate::gate (Feature::Name name, location_t loc,
const std::string &error_msg)
{
- if (!valid_features.count (name))
+ if (!valid_lang_features.count (name))
{
- auto feature = Feature::create (name);
+ auto &feature = Feature::lookup (name);
if (auto issue = feature.issue ())
{
auto issue_number = issue.value ();
@@ -140,9 +166,77 @@ FeatureGate::check_may_dangle_attribute (
}
void
+FeatureGate::check_lang_item_attribute (
+ const std::vector<AST::Attribute> &attributes)
+{
+ for (const AST::Attribute &attr : attributes)
+ {
+ const auto &str_path = attr.get_path ().as_string ();
+ bool is_lang_item = str_path == Values::Attributes::LANG
+ && attr.has_attr_input ()
+ && attr.get_attr_input ().get_attr_input_type ()
+ == AST::AttrInput::AttrInputType::LITERAL;
+
+ if (is_lang_item)
+ gate (Feature::Name::LANG_ITEMS, attr.get_locus (),
+ "lang items are subject to change");
+ }
+}
+
+void
+FeatureGate::note_stability_attribute (
+ const std::vector<AST::Attribute> &attributes)
+{
+ for (const AST::Attribute &attr : attributes)
+ {
+ std::string attr_name = attr.get_path ().as_string ();
+
+ Stability stability;
+
+ if (attr_name == Values::Attributes::STABLE)
+ stability = Stability::STABLE;
+ else if (attr_name == Values::Attributes::UNSTABLE)
+ stability = Stability::UNSTABLE;
+ else if (attr_name == Values::Attributes::RUSTC_CONST_STABLE)
+ stability = Stability::STABLE;
+ else if (attr_name == Values::Attributes::RUSTC_CONST_UNSTABLE)
+ stability = Stability::UNSTABLE;
+ else
+ continue;
+
+ if (attr.empty_input ())
+ // TODO: error?
+ continue;
+
+ auto &attr_input = attr.get_attr_input ();
+ if (attr_input.get_attr_input_type ()
+ != AST::AttrInput::AttrInputType::TOKEN_TREE)
+ // TODO: error?
+ continue;
+
+ std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item (
+ static_cast<const AST::DelimTokenTree &> (attr_input)
+ .parse_to_meta_item ());
+
+ for (auto &item : meta_item->get_items ())
+ {
+ // TODO: more thorough error checking?
+ // ~only the standard libraries should ever exercise this
+ if (item->is_key_value_pair ())
+ {
+ auto &pair = static_cast<const AST::MetaNameValueStr &> (*item);
+ if (pair.get_name ().as_string () == "feature")
+ defined_lib_features.emplace (pair.get_value (), stability);
+ }
+ }
+ }
+}
+
+void
FeatureGate::visit (AST::MacroRulesDefinition &rules_def)
{
check_rustc_attri (rules_def.get_outer_attrs ());
+ note_stability_attribute (rules_def.get_outer_attrs ());
}
void
@@ -151,6 +245,10 @@ FeatureGate::visit (AST::Function &function)
if (!function.is_external ())
check_rustc_attri (function.get_outer_attrs ());
+ check_lang_item_attribute (function.get_outer_attrs ());
+
+ note_stability_attribute (function.get_outer_attrs ());
+
AST::DefaultASTVisitor::visit (function);
}
@@ -177,8 +275,9 @@ void
FeatureGate::visit (AST::Trait &trait)
{
if (trait.is_auto ())
- gate (Feature::Name::AUTO_TRAITS, trait.get_locus (),
+ gate (Feature::Name::OPTIN_BUILTIN_TRAITS, trait.get_locus (),
"auto traits are experimental and possibly buggy");
+ check_lang_item_attribute (trait.get_outer_attrs ());
AST::DefaultASTVisitor::visit (trait);
}
@@ -236,4 +335,32 @@ FeatureGate::visit (AST::UseTreeGlob &use)
// #[feature(prelude_import)]
}
+void
+FeatureGate::visit (AST::StructStruct &struct_item)
+{
+ check_lang_item_attribute (struct_item.get_outer_attrs ());
+ AST::DefaultASTVisitor::visit (struct_item);
+}
+
+void
+FeatureGate::visit (AST::TraitItemType &trait_item_type)
+{
+ check_lang_item_attribute (trait_item_type.get_outer_attrs ());
+ AST::DefaultASTVisitor::visit (trait_item_type);
+}
+
+void
+FeatureGate::visit (AST::Enum &enum_item)
+{
+ check_lang_item_attribute (enum_item.get_outer_attrs ());
+ AST::DefaultASTVisitor::visit (enum_item);
+}
+
+void
+FeatureGate::visit (AST::EnumItem &enum_variant)
+{
+ check_lang_item_attribute (enum_variant.get_outer_attrs ());
+ AST::DefaultASTVisitor::visit (enum_variant);
+}
+
} // namespace Rust
diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/feature/rust-feature-gate.h
index f1011e5..8ff491c 100644
--- a/gcc/rust/checks/errors/rust-feature-gate.h
+++ b/gcc/rust/checks/errors/feature/rust-feature-gate.h
@@ -47,13 +47,30 @@ public:
void visit (AST::ExternBlock &block) override;
void visit (AST::MacroRulesDefinition &rules_def) override;
void visit (AST::RangePattern &pattern) override;
+ void visit (AST::StructStruct &struct_item) override;
+ void visit (AST::TraitItemType &trait_item_type) override;
+ void visit (AST::Enum &enum_item) override;
+ void visit (AST::EnumItem &enum_variant) override;
private:
void gate (Feature::Name name, location_t loc, const std::string &error_msg);
void check_rustc_attri (const std::vector<AST::Attribute> &attributes);
void
check_may_dangle_attribute (const std::vector<AST::Attribute> &attributes);
- std::set<Feature::Name> valid_features;
+ void
+ check_lang_item_attribute (const std::vector<AST::Attribute> &attributes);
+ void note_stability_attribute (const std::vector<AST::Attribute> &attributes);
+
+ std::set<Feature::Name> valid_lang_features;
+ std::map<std::string, location_t> valid_lib_features;
+
+ enum class Stability
+ {
+ STABLE,
+ UNSTABLE,
+ };
+
+ std::map<std::string, Stability> defined_lib_features;
};
} // namespace Rust
#endif
diff --git a/gcc/rust/checks/errors/feature/rust-feature.cc b/gcc/rust/checks/errors/feature/rust-feature.cc
new file mode 100644
index 0000000..1a967aa
--- /dev/null
+++ b/gcc/rust/checks/errors/feature/rust-feature.cc
@@ -0,0 +1,100 @@
+// 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 "rust-feature.h"
+
+namespace Rust {
+
+Feature Feature::feature_list[] = {
+#define ISSUE_SOME(n) n
+#define ISSUE_NONE tl::nullopt
+#define EDITION_2018 Edition::E2018
+#define EDITION_NONE tl::nullopt
+#define REASON_SOME(r) r
+#define REASON_NONE tl::nullopt
+
+#define FEATURE_BASE(state, name_str, name, rust_since, issue, ...) \
+ Feature (Feature::Name::name, Feature::State::state, name_str, rust_since, \
+ issue, __VA_ARGS__),
+
+#define FEATURE_ACTIVE(a, b, c, d, edition) \
+ FEATURE_BASE (ACTIVE, a, b, c, d, edition, tl::nullopt)
+
+#define FEATURE_ACCEPTED(a, b, c, d) \
+ FEATURE_BASE (ACCEPTED, a, b, c, d, tl::nullopt, tl::nullopt)
+
+#define FEATURE_REMOVED(a, b, c, d, reason) \
+ FEATURE_BASE (REMOVED, a, b, c, d, tl::nullopt, reason)
+
+#define FEATURE_STABLE_REMOVED(a, b, c, d) \
+ FEATURE_BASE (ACCEPTED, a, b, c, d, tl::nullopt, tl::nullopt)
+
+#include "rust-feature-defs.h"
+
+#undef ISSUE_SOME
+#undef ISSUE_NONE
+#undef EDITION_2018
+#undef EDITION_NONE
+#undef REASON_SOME
+#undef REASON_NONE
+
+#undef FEATURE_BASE
+#undef FEATURE_ACTIVE
+#undef FEATURE_ACCEPTED
+#undef FEATURE_REMOVED
+#undef FEATURE_STABLE_REMOVED
+};
+
+const std::map<std::string, Feature::Name> Feature::name_hash_map = {
+#define FEATURE(s, name, ...) {s, Feature::Name::name},
+#define FEATURE_ACTIVE(...) FEATURE (__VA_ARGS__)
+#define FEATURE_ACCEPTED(...) FEATURE (__VA_ARGS__)
+#define FEATURE_REMOVED(...) FEATURE (__VA_ARGS__)
+#define FEATURE_STABLE_REMOVED(...) FEATURE (__VA_ARGS__)
+#include "rust-feature-defs.h"
+#undef FEATURE
+#undef FEATURE_ACTIVE
+#undef FEATURE_ACCEPTED
+#undef FEATURE_REMOVED
+#undef FEATURE_STABLE_REMOVED
+};
+
+tl::optional<Feature::Name>
+Feature::as_name (const std::string &name)
+{
+ auto it = Feature::name_hash_map.find (name);
+ if (it == Feature::name_hash_map.end ())
+ return tl::nullopt;
+ else
+ return it->second;
+}
+
+tl::optional<std::reference_wrapper<const Feature>>
+Feature::lookup (const std::string &name)
+{
+ return as_name (name).map (
+ [] (Name n) { return std::ref (Feature::lookup (n)); });
+}
+
+const Feature &
+Feature::lookup (Feature::Name name)
+{
+ return feature_list[static_cast<size_t> (name)];
+}
+
+} // namespace Rust
diff --git a/gcc/rust/checks/errors/feature/rust-feature.h b/gcc/rust/checks/errors/feature/rust-feature.h
new file mode 100644
index 0000000..8686cf4
--- /dev/null
+++ b/gcc/rust/checks/errors/feature/rust-feature.h
@@ -0,0 +1,85 @@
+// 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/>.
+
+#ifndef RUST_FEATURE_H
+#define RUST_FEATURE_H
+
+#include "rust-edition.h"
+#include "optional.h"
+
+namespace Rust {
+
+class Feature
+{
+public:
+ enum class State
+ {
+ ACCEPTED, // stabilized
+ ACTIVE, // unstable
+ REMOVED, // removed
+ STABILIZED, // removed after stabilization
+ };
+
+ enum class Name
+ {
+#define FEATURE_ACTIVE(x, name, ...) name,
+#define FEATURE_ACCEPTED(x, name, ...) name,
+#define FEATURE_REMOVED(x, name, ...) name,
+#define FEATURE_STABLE_REMOVED(x, name, ...) name,
+#include "rust-feature-defs.h"
+#undef FEATURE_ACTIVE
+#undef FEATURE_ACCEPTED
+#undef FEATURE_REMOVED
+#undef FEATURE_STABLE_REMOVED
+ };
+
+ const std::string &as_string () const { return m_name_str; }
+
+ Name name () const { return m_name; }
+ State state () const { return m_state; }
+ tl::optional<unsigned> issue () const { return m_issue; }
+
+ static tl::optional<Name> as_name (const std::string &name);
+
+ static tl::optional<std::reference_wrapper<const Feature>>
+ lookup (const std::string &name);
+ static const Feature &lookup (Name name);
+
+private:
+ Feature (Name name, State state, const char *name_str, const char *rust_since,
+ tl::optional<unsigned> issue_number, tl::optional<Edition> edition,
+ tl::optional<const char *> reason)
+ : m_name (name), m_state (state), m_name_str (name_str),
+ m_rust_since (rust_since), m_issue (issue_number), edition (edition),
+ m_reason (reason)
+ {}
+
+ Name m_name;
+ State m_state;
+ std::string m_name_str;
+ std::string m_rust_since;
+ tl::optional<unsigned> m_issue;
+ tl::optional<Edition> edition;
+ tl::optional<const char *> m_reason;
+
+ static Feature feature_list[];
+ static const std::map<std::string, Name> name_hash_map;
+};
+
+} // namespace Rust
+#endif
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
index 3d25459..90248d3 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
@@ -20,13 +20,12 @@
#include "rust-reachability.h"
#include "rust-hir-type-check.h"
#include "rust-hir-map.h"
-#include "rust-name-resolver.h"
+#include "rust-immutable-name-resolution-context.h"
#include "rust-visibility-resolver.h"
#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 {
@@ -36,12 +35,13 @@ Resolver::resolve (HIR::Crate &crate)
{
PrivacyContext ctx;
auto &mappings = Analysis::Mappings::get ();
- auto resolver = Rust::Resolver::Resolver::get ();
+ auto &resolver
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
auto ty_ctx = ::Rust::Resolver::TypeCheckContext::get ();
- VisibilityResolver (mappings, *resolver).go (crate);
+ VisibilityResolver (mappings, resolver).go (crate);
PubRestrictedVisitor (mappings).go (crate);
- PrivacyReporter (mappings, *resolver, *ty_ctx).go (crate);
+ PrivacyReporter (mappings, resolver, *ty_ctx).go (crate);
auto visitor = ReachabilityVisitor (ctx, *ty_ctx);
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 a537c42..c1a3d45 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
@@ -28,7 +28,8 @@ namespace Rust {
namespace Privacy {
PrivacyReporter::PrivacyReporter (
- Analysis::Mappings &mappings, Resolver::Resolver &resolver,
+ Analysis::Mappings &mappings,
+ const Resolver2_0::NameResolutionContext &resolver,
const Rust::Resolver::TypeCheckContext &ty_ctx)
: mappings (mappings), resolver (resolver), ty_ctx (ty_ctx),
current_module (tl::nullopt)
@@ -90,59 +91,18 @@ PrivacyReporter::go (HIR::Crate &crate)
}
}
-static bool
-is_child_module (Analysis::Mappings &mappings, NodeId parent,
- NodeId possible_child)
-{
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- return nr_ctx.values.is_module_descendant (parent, possible_child);
- }
-
- auto children = mappings.lookup_module_children (parent);
-
- if (!children)
- return false;
-
- // Visit all toplevel children
- for (auto &child : *children)
- if (child == possible_child)
- return true;
-
- // Now descend recursively in the child module tree
- for (auto &child : *children)
- if (is_child_module (mappings, child, possible_child))
- return true;
-
- return false;
-}
-
// FIXME: This function needs a lot of refactoring
void
PrivacyReporter::check_for_privacy_violation (const NodeId &use_id,
const location_t locus)
{
- 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 (use_id))
- ref_node_id = *id;
- }
- // FIXME: Don't assert here - we might be dealing with a type
- else if (!resolver.lookup_resolved_name (use_id, &ref_node_id))
- resolver.lookup_resolved_type (use_id, &ref_node_id);
+ NodeId ref_node_id;
// FIXME: Assert here. For now, we return since this causes issues when
// checking inferred types (#1260)
- // rust_assert (ref_node_id != UNKNOWN_NODEID);
- if (ref_node_id == UNKNOWN_NODEID)
+ if (auto id = resolver.lookup (use_id))
+ ref_node_id = *id;
+ else
return;
auto vis = mappings.lookup_visibility (ref_node_id);
@@ -157,7 +117,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 ())
@@ -174,7 +135,9 @@ PrivacyReporter::check_for_privacy_violation (const NodeId &use_id,
// FIXME: This needs a LOT of TLC: hinting about the definition, a
// string to say if it's a module, function, type, etc...
- if (!is_child_module (mappings, mod_node_id, current_module.value ()))
+
+ if (!resolver.values.is_module_descendant (mod_node_id,
+ current_module.value ()))
valid = false;
}
break;
@@ -215,12 +178,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 +208,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 +239,8 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings,
return;
case TyTy::OPAQUE:
return;
+ case TyTy::CONST:
+ return;
case TyTy::ERROR:
return;
}
@@ -306,6 +274,16 @@ PrivacyReporter::visit (HIR::InlineAsm &)
{}
void
+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 (),
@@ -409,7 +387,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);
@@ -514,6 +493,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 5111a3e..d64b7a7 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
@@ -19,10 +19,12 @@
#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-hir-type-check.h"
#include "rust-mapping-common.h"
-#include "rust-name-resolver.h"
+#include "rust-name-resolution-context.h"
namespace Rust {
namespace Privacy {
@@ -37,7 +39,7 @@ class PrivacyReporter : public HIR::HIRExpressionVisitor,
{
public:
PrivacyReporter (Analysis::Mappings &mappings,
- Rust::Resolver::Resolver &resolver,
+ const Resolver2_0::NameResolutionContext &resolver,
const Rust::Resolver::TypeCheckContext &ty_ctx);
/**
@@ -106,6 +108,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);
@@ -125,6 +129,8 @@ types
virtual void visit (HIR::AwaitExpr &expr);
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 &);
@@ -152,7 +158,7 @@ types
virtual void visit (HIR::ExprStmt &stmt);
Analysis::Mappings &mappings;
- Rust::Resolver::Resolver &resolver;
+ const Resolver2_0::NameResolutionContext &resolver;
const Rust::Resolver::TypeCheckContext &ty_ctx;
// `None` means we're in the root module - the crate
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..4240673 100644
--- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
+++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
@@ -20,16 +20,14 @@
#include "rust-ast.h"
#include "rust-hir.h"
#include "rust-hir-item.h"
-#include "rust-immutable-name-resolution-context.h"
-
-// for flag_name_resolution_2_0
-#include "options.h"
+#include "rust-name-resolution-context.h"
namespace Rust {
namespace Privacy {
-VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings,
- Resolver::Resolver &resolver)
+VisibilityResolver::VisibilityResolver (
+ Analysis::Mappings &mappings,
+ const Resolver2_0::NameResolutionContext &resolver)
: mappings (mappings), resolver (resolver)
{}
@@ -64,23 +62,12 @@ VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction,
= Error (restriction.get_locus (),
"cannot use non-module path as privacy restrictor");
- NodeId ref_node_id = UNKNOWN_NODEID;
- if (flag_name_resolution_2_0)
+ NodeId ref_node_id;
+ if (auto id = resolver.lookup (ast_node_id))
{
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- if (auto id = nr_ctx.lookup (ast_node_id))
- {
- ref_node_id = *id;
- }
- else
- {
- invalid_path.emit ();
- return false;
- }
+ ref_node_id = *id;
}
- else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
+ else
{
invalid_path.emit ();
return false;
@@ -127,7 +114,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/privacy/rust-visibility-resolver.h b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h
index 4dfba4c..ddd70a8 100644
--- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h
+++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h
@@ -24,7 +24,7 @@
#include "rust-hir-stmt.h"
#include "rust-hir-item.h"
#include "rust-hir-map.h"
-#include "rust-name-resolver.h"
+#include "rust-name-resolution-context.h"
#include "rust-hir-visitor.h"
namespace Rust {
@@ -34,7 +34,7 @@ class VisibilityResolver : public HIR::HIRVisItemVisitor
{
public:
VisibilityResolver (Analysis::Mappings &mappings,
- Rust::Resolver::Resolver &resolver);
+ const Resolver2_0::NameResolutionContext &resolver);
/**
* Perform visibility resolving on an entire crate
@@ -93,7 +93,7 @@ public:
private:
Analysis::Mappings &mappings;
- Rust::Resolver::Resolver &resolver;
+ const Resolver2_0::NameResolutionContext &resolver;
DefId current_module;
};
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc
index 4904322..782d694 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 &)
{}
@@ -537,6 +557,14 @@ ConstChecker::visit (InlineAsm &)
{}
void
+ConstChecker::visit (LlvmInlineAsm &)
+{}
+
+void
+ConstChecker::visit (OffsetOf &)
+{}
+
+void
ConstChecker::visit (TypeParam &)
{}
@@ -646,6 +674,9 @@ ConstChecker::visit (Enum &enum_item)
{
check_default_const_generics (enum_item.get_generic_params (),
ConstGenericCtx::Enum);
+
+ for (auto &item : enum_item.get_variants ())
+ item->accept_vis (*this);
}
void
@@ -782,11 +813,11 @@ ConstChecker::visit (StructPattern &)
{}
void
-ConstChecker::visit (TupleStructItemsNoRange &)
+ConstChecker::visit (TupleStructItemsNoRest &)
{}
void
-ConstChecker::visit (TupleStructItemsRange &)
+ConstChecker::visit (TupleStructItemsHasRest &)
{}
void
@@ -794,11 +825,11 @@ ConstChecker::visit (TupleStructPattern &)
{}
void
-ConstChecker::visit (TuplePatternItemsMultiple &)
+ConstChecker::visit (TuplePatternItemsNoRest &)
{}
void
-ConstChecker::visit (TuplePatternItemsRanged &)
+ConstChecker::visit (TuplePatternItemsHasRest &)
{}
void
@@ -806,6 +837,14 @@ ConstChecker::visit (TuplePattern &)
{}
void
+ConstChecker::visit (SlicePatternItemsNoRest &)
+{}
+
+void
+ConstChecker::visit (SlicePatternItemsHasRest &)
+{}
+
+void
ConstChecker::visit (SlicePattern &)
{}
diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h
index 00f57988..d464b7b 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;
@@ -132,6 +134,8 @@ private:
virtual void visit (AwaitExpr &expr) override;
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;
@@ -176,12 +180,14 @@ private:
virtual void visit (StructPatternFieldIdentPat &field) override;
virtual void visit (StructPatternFieldIdent &field) override;
virtual void visit (StructPattern &pattern) override;
- virtual void visit (TupleStructItemsNoRange &tuple_items) override;
- virtual void visit (TupleStructItemsRange &tuple_items) override;
+ virtual void visit (TupleStructItemsNoRest &tuple_items) override;
+ virtual void visit (TupleStructItemsHasRest &tuple_items) override;
virtual void visit (TupleStructPattern &pattern) override;
- virtual void visit (TuplePatternItemsMultiple &tuple_items) override;
- virtual void visit (TuplePatternItemsRanged &tuple_items) override;
+ virtual void visit (TuplePatternItemsNoRest &tuple_items) override;
+ virtual void visit (TuplePatternItemsHasRest &tuple_items) override;
virtual void visit (TuplePattern &pattern) override;
+ virtual void visit (SlicePatternItemsNoRest &items) override;
+ virtual void visit (SlicePatternItemsHasRest &items) override;
virtual void visit (SlicePattern &pattern) override;
virtual void visit (AltPattern &pattern) override;
virtual void visit (EmptyStmt &stmt) override;
diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/rust-feature.cc
deleted file mode 100644
index 25af46c..0000000
--- a/gcc/rust/checks/errors/rust-feature.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-feature.h"
-
-namespace Rust {
-
-Feature
-Feature::create (Feature::Name f)
-{
- switch (f)
- {
- case Feature::Name::ASSOCIATED_TYPE_BOUNDS:
- return Feature (Feature::Name::ASSOCIATED_TYPE_BOUNDS,
- Feature::State::ACCEPTED, "associated_type_bounds",
- "1.34.0", 52662);
- case Feature::Name::INTRINSICS:
- return Feature (f, Feature::State::ACCEPTED, "intrinsics", "1.0.0");
- case Feature::Name::RUSTC_ATTRS:
- return Feature (f, Feature::State::ACCEPTED, "rustc_attrs", "1.0.0");
- case Feature::Name::DECL_MACRO:
- return Feature (f, Feature::State::ACCEPTED, "decl_macro", "1.0.0",
- 39412);
- case Feature::Name::EXTERN_TYPES:
- return Feature (f, Feature::State::ACTIVE, "extern_types", "1.23.0",
- 43467);
- case Feature::Name::NEGATIVE_IMPLS:
- return Feature (f, Feature::State::ACTIVE, "negative_impls", "1.0.0",
- 68318);
- case Feature::Name::BOX_SYNTAX:
- return Feature (f, Feature::State::ACTIVE, "box_syntax", "1.0.0", 49733);
- case Feature::Name::DROPCK_EYEPATCH:
- return Feature (f, Feature::State::ACTIVE, "dropck_eyepatch", "1.10.0",
- 34761);
- case Feature::Name::RAW_REF_OP:
- return Feature (f, Feature::State::ACTIVE, "raw_ref_op", "1.41.0", 64490);
- case Feature::Name::EXCLUSIVE_RANGE_PATTERN:
- return Feature (Feature::Name::EXCLUSIVE_RANGE_PATTERN,
- Feature::State::ACTIVE, "exclusive_range_pattern",
- "1.11.0", 37854);
- case Feature::Name::PRELUDE_IMPORT:
- return Feature (f, Feature::State::ACTIVE, "prelude_import", "1.0.0");
- case Feature::Name::AUTO_TRAITS:
- return Feature (f, Feature::State::ACTIVE, "optin_builtin_traits",
- "1.0.0", 13231);
- default:
- rust_unreachable ();
- }
-}
-
-const std::map<std::string, Feature::Name> Feature::name_hash_map = {
- {"associated_type_bounds", Feature::Name::ASSOCIATED_TYPE_BOUNDS},
- {"intrinsics", Feature::Name::INTRINSICS},
- {"rustc_attrs", Feature::Name::RUSTC_ATTRS},
- {"decl_macro", Feature::Name::DECL_MACRO},
- {"negative_impls", Feature::Name::NEGATIVE_IMPLS},
- // TODO: Rename to "auto_traits" when supporting
- // later Rust versions
- {"optin_builtin_traits", Feature::Name::AUTO_TRAITS},
- {"extern_types", Feature::Name::EXTERN_TYPES},
- {"lang_items", Feature::Name::LANG_ITEMS},
- {"no_core", Feature::Name::NO_CORE},
- {"box_syntax", Feature::Name::BOX_SYNTAX},
- {"dropck_eyepatch", Feature::Name::DROPCK_EYEPATCH},
- {"raw_ref_op", Feature::Name::RAW_REF_OP},
- {"exclusive_range_pattern", Feature::Name::EXCLUSIVE_RANGE_PATTERN},
- {"prelude_import", Feature::Name::PRELUDE_IMPORT},
-}; // namespace Rust
-
-tl::optional<Feature::Name>
-Feature::as_name (const std::string &name)
-{
- if (Feature::name_hash_map.count (name))
- return Feature::name_hash_map.at (name);
-
- return tl::nullopt;
-}
-
-} // namespace Rust
diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/rust-feature.h
deleted file mode 100644
index 9edae6d..0000000
--- a/gcc/rust/checks/errors/rust-feature.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_FEATURE_H
-#define RUST_FEATURE_H
-
-#include "rust-edition.h"
-#include "optional.h"
-
-namespace Rust {
-
-class Feature
-{
-public:
- enum class State
- {
- ACCEPTED,
- ACTIVE,
- REMOVED,
- STABILIZED,
- };
-
- enum class Name
- {
- ASSOCIATED_TYPE_BOUNDS,
- INTRINSICS,
- NEGATIVE_IMPLS,
- RUSTC_ATTRS,
- DECL_MACRO,
- AUTO_TRAITS,
- EXTERN_TYPES,
- LANG_ITEMS,
- NO_CORE,
- BOX_SYNTAX,
- DROPCK_EYEPATCH,
- RAW_REF_OP,
- EXCLUSIVE_RANGE_PATTERN,
- PRELUDE_IMPORT,
- };
-
- const std::string &as_string () { return m_name_str; }
- Name name () { return m_name; }
- const std::string &description () { return m_description; }
- State state () { return m_state; }
- tl::optional<unsigned> issue () { return m_issue; }
-
- static tl::optional<Name> as_name (const std::string &name);
- static Feature create (Name name);
-
-private:
- Feature (Name name, State state, const char *name_str,
- const char *rustc_since,
- tl::optional<unsigned> issue_number = tl::nullopt,
- const tl::optional<Edition> &edition = tl::nullopt,
- const char *description = "")
- : m_state (state), m_name (name), m_name_str (name_str),
- m_rustc_since (rustc_since), m_issue (issue_number), edition (edition),
- m_description (description)
- {}
-
- State m_state;
- Name m_name;
- std::string m_name_str;
- std::string m_rustc_since;
- tl::optional<unsigned> m_issue;
- tl::optional<Edition> edition;
- std::string m_description; // TODO: Switch to optional?
-
- static const std::map<std::string, Name> name_hash_map;
-};
-
-} // namespace Rust
-#endif
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index 257f4cd..f132e04 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -28,15 +28,12 @@
#include "rust-tyty.h"
#include "rust-immutable-name-resolution-context.h"
-// for flag_name_resolution_2_0
-#include "options.h"
-
namespace Rust {
namespace Analysis {
PatternChecker::PatternChecker ()
: tyctx (*Resolver::TypeCheckContext::get ()),
- resolver (*Resolver::Resolver::get ()),
+ resolver (Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()),
mappings (Analysis::Mappings::get ())
{}
@@ -238,17 +235,9 @@ PatternChecker::visit (CallExpr &expr)
NodeId ast_node_id = expr.get_fnexpr ().get_mappings ().get_nodeid ();
NodeId ref_node_id;
- 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
- return;
- }
- else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
+ if (auto id = resolver.lookup (ast_node_id))
+ ref_node_id = *id;
+ else
return;
if (auto definition_id = mappings.lookup_node_to_hir (ref_node_id))
@@ -295,6 +284,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 &)
{}
@@ -423,6 +424,14 @@ PatternChecker::visit (InlineAsm &expr)
{}
void
+PatternChecker::visit (LlvmInlineAsm &expr)
+{}
+
+void
+PatternChecker::visit (OffsetOf &expr)
+{}
+
+void
PatternChecker::visit (TypeParam &)
{}
@@ -620,11 +629,11 @@ PatternChecker::visit (StructPattern &)
{}
void
-PatternChecker::visit (TupleStructItemsNoRange &)
+PatternChecker::visit (TupleStructItemsNoRest &)
{}
void
-PatternChecker::visit (TupleStructItemsRange &)
+PatternChecker::visit (TupleStructItemsHasRest &)
{}
void
@@ -632,11 +641,11 @@ PatternChecker::visit (TupleStructPattern &)
{}
void
-PatternChecker::visit (TuplePatternItemsMultiple &)
+PatternChecker::visit (TuplePatternItemsNoRest &)
{}
void
-PatternChecker::visit (TuplePatternItemsRanged &)
+PatternChecker::visit (TuplePatternItemsHasRest &)
{}
void
@@ -644,6 +653,14 @@ PatternChecker::visit (TuplePattern &)
{}
void
+PatternChecker::visit (SlicePatternItemsNoRest &)
+{}
+
+void
+PatternChecker::visit (SlicePatternItemsHasRest &)
+{}
+
+void
PatternChecker::visit (SlicePattern &)
{}
@@ -724,23 +741,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;
}
@@ -896,19 +917,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 ()
@@ -922,14 +946,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;
@@ -951,7 +977,7 @@ Matrix::specialize (const Constructor &ctor) const
if (ctor.is_covered_by (hd.ctor ()))
{
pats.pop_head_constructor (ctor, subfields_place_info.size ());
- new_rows.push_back (MatrixRow (pats, row.is_under_guard ()));
+ new_rows.emplace_back (pats, row.is_under_guard ());
}
}
@@ -987,7 +1013,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 ());
@@ -1012,7 +1039,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 ();
@@ -1022,11 +1050,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++)
{
@@ -1038,7 +1068,8 @@ WitnessPat::to_string () const
return buf;
}
break;
- case TyTy::VariantDef::VariantType::STRUCT: {
+ case TyTy::VariantDef::VariantType::STRUCT:
+ {
buf += " {";
if (!fields.empty ())
buf += " ";
@@ -1057,7 +1088,8 @@ WitnessPat::to_string () const
buf += "}";
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
break;
@@ -1065,21 +1097,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;
@@ -1096,12 +1132,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);
@@ -1114,7 +1152,8 @@ WitnessMatrix::apply_constructor (const Constructor &ctor,
}
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
}
@@ -1144,7 +1183,7 @@ WitnessMatrix::apply_constructor (const Constructor &ctor,
}
}
- stack.push_back (WitnessPat (ctor, subfield, ty));
+ stack.emplace_back (ctor, subfield, ty);
}
}
@@ -1156,9 +1195,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,
@@ -1171,28 +1210,58 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
std::vector<DeconstructedPat> fields;
switch (elems.get_item_type ())
{
- case HIR::TupleStructItems::ItemType::MULTIPLE: {
- HIR::TupleStructItemsNoRange &multiple
- = static_cast<HIR::TupleStructItemsNoRange &> (elems);
+ case HIR::TupleStructItems::ItemType::NO_REST:
+ {
+ HIR::TupleStructItemsNoRest &items_no_rest
+ = static_cast<HIR::TupleStructItemsNoRest &> (elems);
rust_assert (variant->get_fields ().size ()
- == multiple.get_patterns ().size ());
+ == items_no_rest.get_patterns ().size ());
- for (size_t i = 0; i < multiple.get_patterns ().size (); i++)
+ for (size_t i = 0; i < items_no_rest.get_patterns ().size (); i++)
{
fields.push_back (
- lower_pattern (ctx, *multiple.get_patterns ().at (i),
+ lower_pattern (ctx, *items_no_rest.get_patterns ().at (i),
variant->get_fields ().at (i)->get_field_type ()));
}
return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
}
break;
- case HIR::TupleStructItems::ItemType::RANGED: {
- // TODO: ranged tuple struct items
- rust_unreachable ();
+ case HIR::TupleStructItems::ItemType::HAS_REST:
+ {
+ HIR::TupleStructItemsHasRest &items_has_rest
+ = static_cast<HIR::TupleStructItemsHasRest &> (elems);
+
+ size_t num_patterns = items_has_rest.get_lower_patterns ().size ()
+ + items_has_rest.get_upper_patterns ().size ();
+
+ rust_assert (num_patterns <= variant->num_fields ());
+
+ size_t i = 0;
+ for (auto &pattern_member : items_has_rest.get_lower_patterns ())
+ {
+ fields.push_back (lower_pattern (
+ ctx, *pattern_member,
+ variant->get_fields ().at (i++)->get_field_type ()));
+ }
+ while (i < variant->num_fields ()
+ - items_has_rest.get_upper_patterns ().size ())
+ {
+ fields.push_back (
+ DeconstructedPat::make_wildcard (pattern.get_locus ()));
+ i++;
+ }
+ for (auto &pattern_member : items_has_rest.get_upper_patterns ())
+ {
+ fields.push_back (lower_pattern (
+ ctx, *pattern_member,
+ variant->get_fields ().at (i++)->get_field_type ()));
+ }
+ return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
}
@@ -1223,7 +1292,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
@@ -1232,7 +1302,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
@@ -1242,12 +1313,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 ();
}
}
@@ -1264,11 +1337,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
@@ -1276,13 +1351,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)
{
@@ -1339,37 +1416,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 ();
}
}
@@ -1537,7 +1621,7 @@ check_match_usefulness (Resolver::TypeCheckContext *ctx,
MatchArm lowered = lower_arm (ctx, arm, scrutinee_ty);
PatOrWild pat = PatOrWild::make_pattern (lowered.get_pat ());
pats.push (pat);
- rows.push_back (MatrixRow (pats, lowered.has_guard ()));
+ rows.emplace_back (pats, lowered.has_guard ());
}
std::vector<PlaceInfo> place_infos = {{PlaceInfo (scrutinee_ty)}};
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
index 2171340..645e61d 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
@@ -26,16 +26,16 @@
#include "rust-tyty.h"
#include "optional.h"
#include "rust-hir-visitor.h"
-#include "rust-name-resolver.h"
+#include "rust-immutable-name-resolution-context.h"
namespace Rust {
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
{
@@ -46,7 +46,7 @@ public:
private:
Resolver::TypeCheckContext &tyctx;
- Resolver::Resolver &resolver;
+ const Resolver2_0::NameResolutionContext &resolver;
Analysis::Mappings &mappings;
virtual void visit (Lifetime &lifetime) override;
@@ -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;
@@ -106,6 +108,8 @@ private:
virtual void visit (AwaitExpr &expr) override;
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;
@@ -149,12 +153,14 @@ private:
virtual void visit (StructPatternFieldIdentPat &field) override;
virtual void visit (StructPatternFieldIdent &field) override;
virtual void visit (StructPattern &pattern) override;
- virtual void visit (TupleStructItemsNoRange &tuple_items) override;
- virtual void visit (TupleStructItemsRange &tuple_items) override;
+ virtual void visit (TupleStructItemsNoRest &tuple_items) override;
+ virtual void visit (TupleStructItemsHasRest &tuple_items) override;
virtual void visit (TupleStructPattern &pattern) override;
- virtual void visit (TuplePatternItemsMultiple &tuple_items) override;
- virtual void visit (TuplePatternItemsRanged &tuple_items) override;
+ virtual void visit (TuplePatternItemsNoRest &tuple_items) override;
+ virtual void visit (TuplePatternItemsHasRest &tuple_items) override;
virtual void visit (TuplePattern &pattern) override;
+ virtual void visit (SlicePatternItemsNoRest &items) override;
+ virtual void visit (SlicePatternItemsHasRest &items) override;
virtual void visit (SlicePattern &pattern) override;
virtual void visit (AltPattern &pattern) override;
virtual void visit (EmptyStmt &stmt) override;
diff --git a/gcc/rust/checks/errors/rust-readonly-check.cc b/gcc/rust/checks/errors/rust-readonly-check.cc
index c128933..f484047 100644
--- a/gcc/rust/checks/errors/rust-readonly-check.cc
+++ b/gcc/rust/checks/errors/rust-readonly-check.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021-2025 Free Software Foundation, Inc.
+// Copyright (C) 2025 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -17,184 +17,252 @@
// <http://www.gnu.org/licenses/>.
#include "rust-readonly-check.h"
-#include "rust-tree.h"
-#include "rust-gcc.h"
-#include "print-tree.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 Analysis {
+namespace HIR {
-static std::map<tree, int> assignment_map = {};
+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);
+}
-// ported over from c-family/c-warn.cc
void
-readonly_error (location_t loc, tree arg, enum lvalue_use use)
+ReadonlyChecker::visit (AssignmentExpr &expr)
{
- gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
- || use == lv_asm);
- STRIP_ANY_LOCATION_WRAPPER (arg);
- /* Using this macro rather than (for example) arrays of messages
- ensures that all the format strings are checked at compile
- time. */
-#define READONLY_MSG(A, I, D, AS) \
- (use == lv_assign \
- ? (A) \
- : (use == lv_increment ? (I) : (use == lv_decrement ? (D) : (AS))))
- if (TREE_CODE (arg) == COMPONENT_REF)
+ 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)
{
- if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
- error_at (loc,
- READONLY_MSG (G_ ("assignment of member "
- "%qD in read-only object"),
- G_ ("increment of member "
- "%qD in read-only object"),
- G_ ("decrement of member "
- "%qD in read-only object"),
- G_ ("member %qD in read-only object "
- "used as %<asm%> output")),
- TREE_OPERAND (arg, 1));
- else
- error_at (
- loc,
- READONLY_MSG (G_ ("assignment of read-only member %qD"),
- G_ ("increment of read-only member %qD"),
- G_ ("decrement of read-only member %qD"),
- G_ ("read-only member %qD used as %<asm%> output")),
- TREE_OPERAND (arg, 1));
+ 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 ());
}
- else if (VAR_P (arg))
- error_at (loc,
- READONLY_MSG (G_ ("assignment of read-only variable %qD"),
- G_ ("increment of read-only variable %qD"),
- G_ ("decrement of read-only variable %qD"),
- G_ (
- "read-only variable %qD used as %<asm%> output")),
- arg);
- else if (TREE_CODE (arg) == PARM_DECL)
- error_at (loc,
- READONLY_MSG (G_ ("assignment of read-only parameter %qD"),
- G_ ("increment of read-only parameter %qD"),
- G_ ("decrement of read-only parameter %qD"),
- G_ (
- "read-only parameter %qD use as %<asm%> output")),
- arg);
- else if (TREE_CODE (arg) == RESULT_DECL)
+
+ // Check if the constant item is mutable.
+ if (maybe_item
+ && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant)
{
- error_at (loc,
- READONLY_MSG (G_ ("assignment of "
- "read-only named return value %qD"),
- G_ ("increment of "
- "read-only named return value %qD"),
- G_ ("decrement of "
- "read-only named return value %qD"),
- G_ ("read-only named return value %qD "
- "used as %<asm%>output")),
- arg);
+ 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 ());
}
- else if (TREE_CODE (arg) == FUNCTION_DECL)
- error_at (loc,
- READONLY_MSG (G_ ("assignment of function %qD"),
- G_ ("increment of function %qD"),
- G_ ("decrement of function %qD"),
- G_ ("function %qD used as %<asm%> output")),
- arg);
- else
- error_at (loc,
- READONLY_MSG (G_ ("assignment of read-only location %qE"),
- G_ ("increment of read-only location %qE"),
- G_ ("decrement of read-only location %qE"),
- G_ (
- "read-only location %qE used as %<asm%> output")),
- arg);
}
-static void
-emit_error (tree *t, tree lhs, enum lvalue_use use)
+void
+ReadonlyChecker::check_variable (IdentifierPattern *pattern,
+ location_t assigned_loc)
{
- readonly_error (EXPR_LOCATION (*t), lhs, use);
- TREE_OPERAND (*t, 0) = error_mark_node;
+ if (!mutable_context.is_in_context ())
+ return;
+
+ TyTy::BaseType *type;
+ if (context.lookup_type (pattern->get_mappings ().get_hirid (), &type)
+ && is_mutable_type (type))
+ 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);
}
-static void
-check_modify_expr (tree *t)
+void
+ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern,
+ bool has_init_expr)
{
- tree lhs = TREE_OPERAND (*t, 0);
- if (TREE_CODE (lhs) == ARRAY_REF || TREE_CODE (lhs) == COMPONENT_REF)
- lhs = TREE_OPERAND (lhs, 0);
-
- tree lhs_type = TREE_TYPE (lhs);
- if (TYPE_READONLY (lhs_type) || TREE_READONLY (lhs) || TREE_CONSTANT (lhs))
+ if (has_init_expr)
{
- if (TREE_CODE (lhs) != VAR_DECL)
- emit_error (t, lhs, lv_assign);
- else if (!DECL_ARTIFICIAL (lhs))
- {
- if (DECL_INITIAL (lhs) != NULL)
- emit_error (t, lhs, lv_assign);
- else
- {
- if (assignment_map.find (lhs) == assignment_map.end ())
- {
- assignment_map.insert ({lhs, 0});
- }
- assignment_map[lhs]++;
-
- if (assignment_map[lhs] > 1)
- emit_error (t, lhs, lv_assign);
- }
- }
+ HirId pattern_id = pattern.get_mappings ().get_hirid ();
+ already_assigned_variables.insert (pattern_id);
}
}
-static void
-check_decl (tree *t)
+void
+ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern,
+ bool has_init_expr)
{
- switch (TREE_CODE (*t))
+ switch (tuple_pattern.get_items ().get_item_type ())
{
- case MODIFY_EXPR:
- check_modify_expr (t);
+ case HIR::TuplePatternItems::ItemType::NO_REST:
+ {
+ auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> (
+ tuple_pattern.get_items ());
+ for (auto &sub : items_no_rest.get_patterns ())
+ {
+ collect_assignment (*sub, has_init_expr);
+ }
+ }
+ break;
+ case HIR::TuplePatternItems::ItemType::HAS_REST:
+ {
+ auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> (
+ tuple_pattern.get_items ());
+ for (auto &sub : items_has_rest.get_lower_patterns ())
+ collect_assignment (*sub, has_init_expr);
+ for (auto &sub : items_has_rest.get_upper_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;
}
}
-static tree
-readonly_walk_fn (tree *t, int *, void *)
+void
+ReadonlyChecker::visit (LetStmt &stmt)
+{
+ HIR::Pattern &pattern = stmt.get_pattern ();
+ collect_assignment (pattern, stmt.has_init_expr ());
+}
+
+void
+ReadonlyChecker::visit (FieldAccessExpr &expr)
{
- check_decl (t);
- return NULL_TREE;
+ if (mutable_context.is_in_context ())
+ {
+ expr.get_receiver_expr ().accept_vis (*this);
+ }
}
void
-ReadonlyCheck::Lint (Compile::Context &ctx)
+ReadonlyChecker::visit (TupleIndexExpr &expr)
{
- assignment_map.clear ();
- for (auto &fndecl : ctx.get_func_decls ())
+ if (mutable_context.is_in_context ())
{
- for (tree p = DECL_ARGUMENTS (fndecl); p != NULL_TREE; p = DECL_CHAIN (p))
- {
- check_decl (&p);
- }
+ expr.get_tuple_expr ().accept_vis (*this);
+ }
+}
- walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
- &readonly_walk_fn, &ctx);
+void
+ReadonlyChecker::visit (ArrayIndexExpr &expr)
+{
+ if (mutable_context.is_in_context ())
+ {
+ expr.get_array_expr ().accept_vis (*this);
}
+}
- assignment_map.clear ();
- for (auto &var : ctx.get_var_decls ())
+void
+ReadonlyChecker::visit (TupleExpr &expr)
+{
+ if (mutable_context.is_in_context ())
{
- tree decl = var->get_decl ();
- check_decl (&decl);
+ // TODO: Add check for tuple expression
}
+}
- assignment_map.clear ();
- for (auto &const_decl : ctx.get_const_decls ())
+void
+ReadonlyChecker::visit (LiteralExpr &expr)
+{
+ if (mutable_context.is_in_context ())
{
- check_decl (&const_decl);
+ rust_error_at (expr.get_locus (), "assignment of read-only location");
}
}
-} // namespace Analysis
+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 (!is_mutable_type (to_deref_type))
+ rust_error_at (expr.get_locus (), "assignment of read-only location");
+}
+
+bool
+ReadonlyChecker::is_mutable_type (TyTy::BaseType *type)
+{
+ if (type->get_kind () == TyTy::TypeKind::REF)
+ return static_cast<TyTy::ReferenceType *> (type)->is_mutable ();
+ if (type->get_kind () == TyTy::TypeKind::POINTER)
+ return static_cast<TyTy::PointerType *> (type)->is_mutable ();
+ return false;
+}
+} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/checks/errors/rust-readonly-check.h b/gcc/rust/checks/errors/rust-readonly-check.h
index b39eee3..3525620 100644
--- a/gcc/rust/checks/errors/rust-readonly-check.h
+++ b/gcc/rust/checks/errors/rust-readonly-check.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2021-2025 Free Software Foundation, Inc.
+// Copyright (C) 2025 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -16,21 +16,54 @@
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-#ifndef RUST_READONLY_CHECK
-#define RUST_READONLY_CHECK
-
-#include "rust-compile-context.h"
+#include "rust-hir-visitor.h"
+#include "rust-name-resolver.h"
+#include "rust-stacked-contexts.h"
+#include "rust-hir-type-check.h"
namespace Rust {
-namespace Analysis {
-
-class ReadonlyCheck
+namespace HIR {
+class ReadonlyChecker : public DefaultHIRVisitor
{
public:
- static void Lint (Compile::Context &ctx);
-};
+ 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;
-} // namespace Analysis
-} // namespace Rust
+ 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);
+
+ bool is_mutable_type (TyTy::BaseType *type);
+};
-#endif // RUST_READONLY_CHECK
+} // 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 8aa59ee..607d20f 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -481,9 +481,14 @@ UnsafeChecker::visit (MethodCallExpr &expr)
TyTy::BaseType *method_type;
context.lookup_type (expr.get_method_name ().get_mappings ().get_hirid (),
&method_type);
+ if (!method_type || !method_type->is<TyTy::FnType> ())
+ return;
auto &fn = static_cast<TyTy::FnType &> (*method_type);
+ // FIXME
+ // should probably use the defid lookup instead
+ // tl::optional<HIR::Item *> lookup_defid (DefId id);
auto method = mappings.lookup_hir_implitem (fn.get_ref ());
if (!unsafe_context.is_in_context () && method)
check_unsafe_call (static_cast<Function *> (method->first),
@@ -535,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 &)
{}
@@ -666,6 +683,23 @@ UnsafeChecker::visit (InlineAsm &expr)
}
void
+UnsafeChecker::visit (LlvmInlineAsm &expr)
+{
+ if (unsafe_context.is_in_context ())
+ return;
+
+ rust_error_at (
+ expr.get_locus (), ErrorCode::E0133,
+ "use of inline assembly is unsafe and requires unsafe function or block");
+}
+
+void
+UnsafeChecker::visit (OffsetOf &expr)
+{
+ // nothing to do, offset_of!() is safe
+}
+
+void
UnsafeChecker::visit (TypeParam &)
{}
@@ -892,11 +926,11 @@ UnsafeChecker::visit (StructPattern &)
{}
void
-UnsafeChecker::visit (TupleStructItemsNoRange &)
+UnsafeChecker::visit (TupleStructItemsNoRest &)
{}
void
-UnsafeChecker::visit (TupleStructItemsRange &)
+UnsafeChecker::visit (TupleStructItemsHasRest &)
{}
void
@@ -904,11 +938,11 @@ UnsafeChecker::visit (TupleStructPattern &)
{}
void
-UnsafeChecker::visit (TuplePatternItemsMultiple &)
+UnsafeChecker::visit (TuplePatternItemsNoRest &)
{}
void
-UnsafeChecker::visit (TuplePatternItemsRanged &)
+UnsafeChecker::visit (TuplePatternItemsHasRest &)
{}
void
@@ -916,6 +950,14 @@ UnsafeChecker::visit (TuplePattern &)
{}
void
+UnsafeChecker::visit (SlicePatternItemsNoRest &)
+{}
+
+void
+UnsafeChecker::visit (SlicePatternItemsHasRest &)
+{}
+
+void
UnsafeChecker::visit (SlicePattern &)
{}
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h
index 63098fe..420668f 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;
@@ -114,6 +116,8 @@ private:
virtual void visit (AwaitExpr &expr) override;
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;
@@ -157,12 +161,14 @@ private:
virtual void visit (StructPatternFieldIdentPat &field) override;
virtual void visit (StructPatternFieldIdent &field) override;
virtual void visit (StructPattern &pattern) override;
- virtual void visit (TupleStructItemsNoRange &tuple_items) override;
- virtual void visit (TupleStructItemsRange &tuple_items) override;
+ virtual void visit (TupleStructItemsNoRest &tuple_items) override;
+ virtual void visit (TupleStructItemsHasRest &tuple_items) override;
virtual void visit (TupleStructPattern &pattern) override;
- virtual void visit (TuplePatternItemsMultiple &tuple_items) override;
- virtual void visit (TuplePatternItemsRanged &tuple_items) override;
+ virtual void visit (TuplePatternItemsNoRest &tuple_items) override;
+ virtual void visit (TuplePatternItemsHasRest &tuple_items) override;
virtual void visit (TuplePattern &pattern) override;
+ virtual void visit (SlicePatternItemsNoRest &items) override;
+ virtual void visit (SlicePatternItemsHasRest &items) override;
virtual void visit (SlicePattern &pattern) override;
virtual void visit (AltPattern &pattern) override;
virtual void visit (EmptyStmt &stmt) override;
diff --git a/gcc/rust/checks/lints/rust-lint-marklive-base.h b/gcc/rust/checks/lints/rust-lint-marklive-base.h
index 2a97577..dec9396 100644
--- a/gcc/rust/checks/lints/rust-lint-marklive-base.h
+++ b/gcc/rust/checks/lints/rust-lint-marklive-base.h
@@ -19,9 +19,6 @@
#ifndef RUST_HIR_LIVENESS_BASE
#define RUST_HIR_LIVENESS_BASE
-#include "rust-diagnostics.h"
-#include "rust-lint-marklive.h"
-#include "rust-lint-marklive-base.h"
#include "rust-hir-visitor.h"
#include "rust-hir-map.h"
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..3c5e74e 100644
--- a/gcc/rust/expand/rust-cfg-strip.cc
+++ b/gcc/rust/expand/rust-cfg-strip.cc
@@ -22,6 +22,7 @@
#include "rust-path.h"
#include "rust-session-manager.h"
#include "rust-attribute-values.h"
+#include "rust-macro-expand.h"
namespace Rust {
@@ -30,7 +31,7 @@ namespace Rust {
* should be stripped. Note that attributes must be expanded before calling.
*/
bool
-fails_cfg (const AST::AttrVec &attrs)
+CfgStrip::fails_cfg (const AST::AttrVec &attrs) const
{
auto &session = Session::get_instance ();
@@ -39,6 +40,9 @@ fails_cfg (const AST::AttrVec &attrs)
if (attr.get_path () == Values::Attributes::CFG
&& !attr.check_cfg_predicate (session))
return true;
+ else if (!expansion_cfg.should_test
+ && attr.get_path () == Values::Attributes::TEST)
+ return true;
}
return false;
}
@@ -48,7 +52,7 @@ fails_cfg (const AST::AttrVec &attrs)
* should be stripped. Will expand attributes as well.
*/
bool
-fails_cfg_with_expand (AST::AttrVec &attrs)
+CfgStrip::fails_cfg_with_expand (AST::AttrVec &attrs) const
{
auto &session = Session::get_instance ();
@@ -85,6 +89,9 @@ fails_cfg_with_expand (AST::AttrVec &attrs)
attr.as_string ().c_str ());
}
}
+ else if (!expansion_cfg.should_test
+ && attr.get_path () == Values::Attributes::TEST)
+ return true;
}
return false;
}
@@ -289,7 +296,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 +306,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 +1199,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 +1772,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
@@ -2059,38 +2069,6 @@ CfgStrip::visit (AST::StaticItem &static_item)
}
void
-CfgStrip::visit (AST::TraitItemConst &item)
-{
- // initial test based on outer attrs
- expand_cfg_attrs (item.get_outer_attrs ());
- if (fails_cfg_with_expand (item.get_outer_attrs ()))
- {
- item.mark_for_strip ();
- return;
- }
-
- AST::DefaultASTVisitor::visit (item);
-
- // strip any sub-types
- auto &type = item.get_type ();
-
- if (type.is_marked_for_strip ())
- rust_error_at (type.get_locus (), "cannot strip type in this position");
-
- /* strip any internal sub-expressions - expression itself isn't
- * allowed to have external attributes in this position so can't be
- * stripped */
- if (item.has_expression ())
- {
- auto &expr = item.get_expr ();
- if (expr.is_marked_for_strip ())
- rust_error_at (expr.get_locus (),
- "cannot strip expression in this position - outer "
- "attributes not allowed");
- }
-}
-
-void
CfgStrip::visit (AST::TraitItemType &item)
{
// initial test based on outer attrs
@@ -2260,12 +2238,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");
@@ -2371,7 +2349,7 @@ CfgStrip::visit (AST::StructPattern &pattern)
maybe_strip_pointer_allow_strip (elems.get_struct_pattern_fields ());
// assuming you can strip the ".." part
- if (elems.has_etc ())
+ if (elems.has_rest ())
{
expand_cfg_attrs (elems.get_etc_outer_attrs ());
if (fails_cfg_with_expand (elems.get_etc_outer_attrs ()))
@@ -2380,7 +2358,7 @@ CfgStrip::visit (AST::StructPattern &pattern)
}
void
-CfgStrip::visit (AST::TupleStructItemsNoRange &tuple_items)
+CfgStrip::visit (AST::TupleStructItemsNoRest &tuple_items)
{
AST::DefaultASTVisitor::visit (tuple_items);
// can't strip individual patterns, only sub-patterns
@@ -2393,7 +2371,7 @@ CfgStrip::visit (AST::TupleStructItemsNoRange &tuple_items)
}
}
void
-CfgStrip::visit (AST::TupleStructItemsRange &tuple_items)
+CfgStrip::visit (AST::TupleStructItemsHasRest &tuple_items)
{
AST::DefaultASTVisitor::visit (tuple_items);
// can't strip individual patterns, only sub-patterns
@@ -2426,7 +2404,7 @@ CfgStrip::visit (AST::TupleStructPattern &pattern)
}
void
-CfgStrip::visit (AST::TuplePatternItemsMultiple &tuple_items)
+CfgStrip::visit (AST::TuplePatternItemsNoRest &tuple_items)
{
AST::DefaultASTVisitor::visit (tuple_items);
@@ -2441,7 +2419,7 @@ CfgStrip::visit (AST::TuplePatternItemsMultiple &tuple_items)
}
void
-CfgStrip::visit (AST::TuplePatternItemsRanged &tuple_items)
+CfgStrip::visit (AST::TuplePatternItemsHasRest &tuple_items)
{
AST::DefaultASTVisitor::visit (tuple_items);
@@ -2475,20 +2453,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..42cd266 100644
--- a/gcc/rust/expand/rust-cfg-strip.h
+++ b/gcc/rust/expand/rust-cfg-strip.h
@@ -23,14 +23,23 @@
#include "rust-item.h"
namespace Rust {
+
+// forward declare
+struct ExpansionCfg;
+
// Visitor used to maybe_strip attributes.
class CfgStrip : public AST::DefaultASTVisitor
{
private:
+ bool fails_cfg (const AST::AttrVec &attrs) const;
+
+ bool fails_cfg_with_expand (AST::AttrVec &attrs) const;
+
public:
using DefaultASTVisitor::visit;
- CfgStrip () {}
+ CfgStrip (const ExpansionCfg &expansion_cfg) : expansion_cfg (expansion_cfg)
+ {}
/* Run the AttrVisitor on an entire crate */
void go (AST::Crate &crate);
@@ -147,7 +156,6 @@ public:
void visit (AST::Union &union_item) override;
void visit (AST::ConstantItem &const_item) override;
void visit (AST::StaticItem &static_item) override;
- void visit (AST::TraitItemConst &item) override;
void visit (AST::TraitItemType &item) override;
void visit (AST::Trait &trait) override;
void visit (AST::InherentImpl &impl) override;
@@ -166,12 +174,14 @@ public:
void visit (AST::StructPatternFieldIdentPat &field) override;
void visit (AST::StructPatternFieldIdent &field) override;
void visit (AST::StructPattern &pattern) override;
- void visit (AST::TupleStructItemsNoRange &tuple_items) override;
- void visit (AST::TupleStructItemsRange &tuple_items) override;
+ void visit (AST::TupleStructItemsNoRest &tuple_items) override;
+ void visit (AST::TupleStructItemsHasRest &tuple_items) override;
void visit (AST::TupleStructPattern &pattern) override;
- void visit (AST::TuplePatternItemsMultiple &tuple_items) override;
- void visit (AST::TuplePatternItemsRanged &tuple_items) override;
+ void visit (AST::TuplePatternItemsNoRest &tuple_items) override;
+ void visit (AST::TuplePatternItemsHasRest &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;
@@ -192,6 +202,9 @@ public:
{
DefaultASTVisitor::visit (item);
}
+
+private:
+ const ExpansionCfg &expansion_cfg;
};
} // namespace Rust
diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc
index 074ea01..27dcc66 100644
--- a/gcc/rust/expand/rust-derive-clone.cc
+++ b/gcc/rust/expand/rust-derive-clone.cc
@@ -61,15 +61,13 @@ std::unique_ptr<AssociatedItem>
DeriveClone::clone_fn (std::unique_ptr<Expr> &&clone_expr)
{
auto block = std::unique_ptr<BlockExpr> (
- new BlockExpr ({}, std::move (clone_expr), {}, {}, AST::LoopLabel::error (),
- loc, loc));
+ new BlockExpr ({}, std::move (clone_expr), {}, {}, tl::nullopt, loc, loc));
auto big_self_type = builder.single_type_path ("Self");
- std::unique_ptr<SelfParam> self (new SelfParam (Lifetime::error (),
- /* is_mut */ false, loc));
-
std::vector<std::unique_ptr<Param>> params;
- params.push_back (std::move (self));
+
+ params.emplace_back (new SelfParam (tl::nullopt,
+ /* is_mut */ false, loc));
return std::unique_ptr<AssociatedItem> (
new Function ({"clone"}, builder.fn_qualifiers (), /* generics */ {},
@@ -212,7 +210,7 @@ DeriveClone::clone_enum_tuple (PathInExpression variant_path,
}
auto pattern_items = std::unique_ptr<TupleStructItems> (
- new TupleStructItemsNoRange (std::move (patterns)));
+ new TupleStructItemsNoRest (std::move (patterns)));
auto pattern = std::unique_ptr<Pattern> (new ReferencePattern (
std::unique_ptr<Pattern> (new TupleStructPattern (
@@ -294,8 +292,14 @@ DeriveClone::clone_enum_struct (PathInExpression variant_path,
new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern (
variant_path, loc, pattern_elts)),
false, false, loc));
+
+ PathInExpression new_path (variant_path.get_segments (),
+ variant_path.get_outer_attrs (),
+ variant_path.get_locus (),
+ variant_path.opening_scope_resolution ());
+
auto expr = std::unique_ptr<Expr> (
- new StructExprStructFields (variant_path, std::move (cloned_fields), loc));
+ new StructExprStructFields (new_path, std::move (cloned_fields), loc));
return builder.match_case (std::move (pattern), std::move (expr));
}
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..9890bb7
--- /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 TupleStructItemsNoRest (std::move (self_patterns)));
+ auto other_pattern_items = std::unique_ptr<TupleStructItems> (
+ new TupleStructItemsNoRest (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<TuplePatternItemsNoRest> (
+ 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<TuplePatternItemsNoRest> (
+ 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-debug.cc b/gcc/rust/expand/rust-derive-debug.cc
index 7ad3908..a0bf9d8 100644
--- a/gcc/rust/expand/rust-derive-debug.cc
+++ b/gcc/rust/expand/rust-derive-debug.cc
@@ -50,8 +50,7 @@ DeriveDebug::stub_debug_fn ()
// we can't use builder.block() here as it returns a unique_ptr<Expr> and
// Function's constructor expects a unique_ptr<BlockExpr>
auto block = std::unique_ptr<BlockExpr> (
- new BlockExpr ({}, std::move (stub_return), {}, {},
- AST::LoopLabel::error (), loc, loc));
+ new BlockExpr ({}, std::move (stub_return), {}, {}, tl::nullopt, loc, loc));
auto self = builder.self_ref_param ();
diff --git a/gcc/rust/expand/rust-derive-default.cc b/gcc/rust/expand/rust-derive-default.cc
index c54f8c3..26ee546 100644
--- a/gcc/rust/expand/rust-derive-default.cc
+++ b/gcc/rust/expand/rust-derive-default.cc
@@ -58,8 +58,7 @@ DeriveDefault::default_fn (std::unique_ptr<Expr> &&return_expr)
= std::unique_ptr<Type> (new TypePath (builder.type_path ("Self")));
auto block = std::unique_ptr<BlockExpr> (
- new BlockExpr ({}, std::move (return_expr), {}, {},
- AST::LoopLabel::error (), loc, loc));
+ new BlockExpr ({}, std::move (return_expr), {}, {}, tl::nullopt, loc, loc));
return builder.function ("default", {}, std::move (self_ty),
std::move (block));
@@ -99,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)));
@@ -120,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 dc173de..17332a4 100644
--- a/gcc/rust/expand/rust-derive-eq.cc
+++ b/gcc/rust/expand/rust-derive-eq.cc
@@ -49,8 +49,7 @@ DeriveEq::assert_receiver_is_total_eq_fn (
stmts.emplace_back (assert_type_is_eq (std::move (type)));
auto block = std::unique_ptr<BlockExpr> (
- new BlockExpr (std::move (stmts), nullptr, {}, {}, AST::LoopLabel::error (),
- loc, loc));
+ new BlockExpr (std::move (stmts), nullptr, {}, {}, tl::nullopt, loc, loc));
auto self = builder.self_ref_param ();
@@ -129,9 +128,13 @@ DeriveEq::eq_impls (
auto eq_impl = builder.trait_impl (eq, std::move (eq_generics.self_type),
std::move (trait_items),
std::move (eq_generics.impl));
+
+ // StructuralEq is a marker trait
+ decltype (trait_items) steq_trait_items = {};
+
auto steq_impl
= builder.trait_impl (steq, std::move (steq_generics.self_type),
- std::move (trait_items),
+ std::move (steq_trait_items),
std::move (steq_generics.impl));
return vec (std::move (eq_impl), std::move (steq_impl));
@@ -143,7 +146,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 (),
@@ -156,7 +159,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 (),
@@ -176,19 +179,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;
}
@@ -206,7 +210,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..616bfdb 100644
--- a/gcc/rust/expand/rust-derive-hash.cc
+++ b/gcc/rust/expand/rust-derive-hash.cc
@@ -151,7 +151,7 @@ DeriveHash::match_enum_tuple (PathInExpression variant_path,
}
auto patterns_elts = std::unique_ptr<TupleStructItems> (
- new TupleStructItemsNoRange (std::move (self_patterns)));
+ new TupleStructItemsNoRest (std::move (self_patterns)));
auto pattern = std::unique_ptr<Pattern> (
new ReferencePattern (std::unique_ptr<Pattern> (new TupleStructPattern (
variant_path, std::move (patterns_elts))),
@@ -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..6f3981f
--- /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 TupleStructItemsNoRest (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..287d8a7 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 ());
@@ -171,7 +146,7 @@ DerivePartialEq::match_enum_identifier (
builder.ref_pattern (
std::unique_ptr<Pattern> (new PathInExpression (variant_path))));
- auto tuple_items = std::make_unique<TuplePatternItemsMultiple> (
+ auto tuple_items = std::make_unique<TuplePatternItemsNoRest> (
std::move (inner_ref_patterns));
auto pattern = std::make_unique<TuplePattern> (std::move (tuple_items), loc);
@@ -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 (
@@ -213,9 +186,9 @@ DerivePartialEq::match_enum_tuple (PathInExpression variant_path,
}
auto self_pattern_items = std::unique_ptr<TupleStructItems> (
- new TupleStructItemsNoRange (std::move (self_patterns)));
+ new TupleStructItemsNoRest (std::move (self_patterns)));
auto other_pattern_items = std::unique_ptr<TupleStructItems> (
- new TupleStructItemsNoRange (std::move (other_patterns)));
+ new TupleStructItemsNoRest (std::move (other_patterns)));
auto self_pattern = std::unique_ptr<Pattern> (
new ReferencePattern (std::unique_ptr<Pattern> (new TupleStructPattern (
@@ -226,7 +199,7 @@ DerivePartialEq::match_enum_tuple (PathInExpression variant_path,
variant_path, std::move (other_pattern_items))),
false, false, loc));
- auto tuple_items = std::make_unique<TuplePatternItemsMultiple> (
+ auto tuple_items = std::make_unique<TuplePatternItemsNoRest> (
vec (std::move (self_pattern), std::move (other_pattern)));
auto pattern = std::make_unique<TuplePattern> (std::move (tuple_items), loc);
@@ -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<TuplePatternItemsNoRest> (
+ 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..2777f07 100644
--- a/gcc/rust/expand/rust-derive.cc
+++ b/gcc/rust/expand/rust-derive.cc
@@ -22,8 +22,10 @@
#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"
+#include "rust-system.h"
namespace Rust {
namespace AST {
@@ -38,6 +40,16 @@ DeriveVisitor::derive (Item &item, const Attribute &attr,
{
auto loc = attr.get_locus ();
+ using Kind = AST::Item::Kind;
+ auto item_kind = item.get_item_kind ();
+ if (item_kind != Kind::Enum && item_kind != Kind::Struct
+ && item_kind != Kind::Union)
+ {
+ rust_error_at (loc,
+ "derive may only be applied to structs, enums and unions");
+ return {};
+ }
+
switch (to_derive)
{
case BuiltinMacro::Clone:
@@ -59,10 +71,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 +92,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 +105,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 +119,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 +129,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_type (std::move (associated_type));
+ generic_args.push_back (std::move (type_arg));
- // GenericArg type_arg
- // = GenericArg::create_const (std::move (const_expr));
- // 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 d8cc0a4..d28bba9 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{};
@@ -171,6 +174,7 @@ private:
virtual void visit (AwaitExpr &expr) override final{};
virtual void visit (AsyncBlockExpr &expr) override final{};
virtual void visit (InlineAsm &expr) override final{};
+ virtual void visit (LlvmInlineAsm &expr) override final{};
virtual void visit (TypeParam &param) override final{};
virtual void visit (LifetimeWhereClauseItem &item) override final{};
virtual void visit (TypeBoundWhereClauseItem &item) override final{};
@@ -188,7 +192,6 @@ private:
virtual void visit (EnumItemDiscriminant &item) override final{};
virtual void visit (ConstantItem &const_item) override final{};
virtual void visit (StaticItem &static_item) override final{};
- virtual void visit (TraitItemConst &item) override final{};
virtual void visit (TraitItemType &item) override final{};
virtual void visit (Trait &trait) override final{};
virtual void visit (InherentImpl &impl) override final{};
@@ -220,13 +223,15 @@ private:
virtual void visit (StructPatternFieldIdentPat &field) override final{};
virtual void visit (StructPatternFieldIdent &field) override final{};
virtual void visit (StructPattern &pattern) override final{};
- virtual void visit (TupleStructItemsNoRange &tuple_items) override final{};
- virtual void visit (TupleStructItemsRange &tuple_items) override final{};
+ virtual void visit (TupleStructItemsNoRest &tuple_items) override final{};
+ virtual void visit (TupleStructItemsHasRest &tuple_items) override final{};
virtual void visit (TupleStructPattern &pattern) override final{};
- virtual void visit (TuplePatternItemsMultiple &tuple_items) override final{};
- virtual void visit (TuplePatternItemsRanged &tuple_items) override final{};
+ virtual void visit (TuplePatternItemsNoRest &tuple_items) override final{};
+ virtual void visit (TuplePatternItemsHasRest &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{};
@@ -250,9 +255,10 @@ 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
} // namespace Rust
-#endif // DERIVE_VISITOR_H
+#endif // DERIVE_VISITOR_H \ No newline at end of file
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 d4db313..6e98a5c 100644
--- a/gcc/rust/expand/rust-expand-visitor.cc
+++ b/gcc/rust/expand/rust-expand-visitor.cc
@@ -18,6 +18,8 @@
#include "rust-expand-visitor.h"
#include "rust-ast-fragment.h"
+#include "rust-hir-map.h"
+#include "rust-item.h"
#include "rust-proc-macro.h"
#include "rust-attributes.h"
#include "rust-ast.h"
@@ -47,7 +49,10 @@ static std::vector<std::unique_ptr<AST::Item>>
builtin_derive_item (AST::Item &item, const AST::Attribute &derive,
BuiltinMacro to_derive)
{
- return AST::DeriveVisitor::derive (item, derive, to_derive);
+ auto items = AST::DeriveVisitor::derive (item, derive, to_derive);
+ for (auto &item : items)
+ Analysis::Mappings::get ().add_derived_node (item->get_node_id ());
+ return items;
}
static std::vector<std::unique_ptr<AST::Item>>
@@ -62,7 +67,9 @@ derive_item (AST::Item &item, AST::SimplePath &to_derive,
{
switch (node.get_kind ())
{
- case AST::SingleASTNode::ITEM:
+ case AST::SingleASTNode::Kind::Item:
+ Analysis::Mappings::get ().add_derived_node (
+ node.get_item ()->get_node_id ());
result.push_back (node.take_item ());
break;
default:
@@ -85,7 +92,7 @@ expand_item_attribute (AST::Item &item, AST::SimplePath &name,
{
switch (node.get_kind ())
{
- case AST::SingleASTNode::ITEM:
+ case AST::SingleASTNode::Kind::Item:
result.push_back (node.take_item ());
break;
default:
@@ -114,7 +121,7 @@ expand_stmt_attribute (T &statement, AST::SimplePath &attribute,
{
switch (node.get_kind ())
{
- case AST::SingleASTNode::STMT:
+ case AST::SingleASTNode::Kind::Stmt:
result.push_back (node.take_stmt ());
break;
default:
@@ -233,10 +240,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 +328,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 ();
}
@@ -335,10 +336,15 @@ ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr)
void
ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
{
+ NodeId old_expect = expr->get_node_id ();
+ std::swap (macro_invoc_expect_id, old_expect);
+
expander.push_context (MacroExpander::ContextType::EXPR);
expr->accept_vis (*this);
expander.pop_context ();
+ std::swap (macro_invoc_expect_id, old_expect);
+
auto final_fragment = expander.take_expanded_fragment ();
if (final_fragment.should_expand ()
&& final_fragment.is_expression_fragment ())
@@ -348,14 +354,54 @@ ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
void
ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
{
- expander.push_context (MacroExpander::ContextType::TYPE);
+ NodeId old_expect = type->get_node_id ();
+ std::swap (macro_invoc_expect_id, old_expect);
+ expander.push_context (MacroExpander::ContextType::TYPE);
type->accept_vis (*this);
+ expander.pop_context ();
+
+ std::swap (macro_invoc_expect_id, old_expect);
+
auto final_fragment = expander.take_expanded_fragment ();
if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
type = final_fragment.take_type_fragment ();
+}
+
+// HACK: maybe we shouldn't have TypeNoBounds as a base class
+void
+ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type)
+{
+ NodeId old_expect = type->get_node_id ();
+ std::swap (macro_invoc_expect_id, old_expect);
+
+ expander.push_context (MacroExpander::ContextType::TYPE);
+ type->accept_vis (*this);
+ expander.pop_context ();
+
+ std::swap (macro_invoc_expect_id, old_expect);
+
+ auto final_fragment = expander.take_expanded_fragment ();
+ if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
+ type = std::make_unique<AST::ParenthesisedType> (
+ final_fragment.take_type_fragment (), BUILTINS_LOCATION);
+}
+
+void
+ExpandVisitor::maybe_expand_pattern (std::unique_ptr<AST::Pattern> &pattern)
+{
+ NodeId old_expect = pattern->get_node_id ();
+ std::swap (macro_invoc_expect_id, old_expect);
+ expander.push_context (MacroExpander::ContextType::PATTERN);
+ pattern->accept_vis (*this);
expander.pop_context ();
+
+ std::swap (macro_invoc_expect_id, old_expect);
+
+ auto final_fragment = expander.take_expanded_fragment ();
+ if (final_fragment.should_expand () && final_fragment.is_pattern_fragment ())
+ pattern = final_fragment.take_pattern_fragment ();
}
// FIXME: Can this be refactored into a `scoped` method? Which takes a
@@ -430,6 +476,8 @@ ExpandVisitor::expand_closure_params (std::vector<AST::ClosureParam> &params)
{
for (auto &param : params)
{
+ maybe_expand_pattern (param.get_pattern_ptr ());
+
if (param.has_type_given ())
maybe_expand_type (param.get_type_ptr ());
}
@@ -471,6 +519,14 @@ ExpandVisitor::visit (AST::ConstGenericParam &)
void
ExpandVisitor::visit (AST::MacroInvocation &macro_invoc)
{
+ if (macro_invoc_expect_id != macro_invoc.get_node_id ())
+ {
+ rust_internal_error_at (
+ macro_invoc.get_locus (),
+ "attempting to expand node with id %d into position with node id %d",
+ (int) macro_invoc.get_node_id (), (int) macro_invoc_expect_id);
+ }
+
// TODO: Can we do the AST fragment replacing here? Probably not, right?
expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon ()
? AST::InvocKind::Semicoloned
@@ -489,7 +545,8 @@ ExpandVisitor::visit (AST::PathInExpression &path)
void
ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment)
{
- expand_generic_args (segment.get_generic_args ());
+ if (segment.has_generic_args ())
+ expand_generic_args (segment.get_generic_args ());
}
void
@@ -543,16 +600,10 @@ ExpandVisitor::visit (AST::MetaItemLitExpr &)
{}
void
-ExpandVisitor::visit (AST::MetaItemPathLit &)
+ExpandVisitor::visit (AST::MetaItemPathExpr &)
{}
void
-ExpandVisitor::visit (AST::ErrorPropagationExpr &expr)
-{
- visit (expr.get_propagating_expr ());
-}
-
-void
ExpandVisitor::visit (AST::ArithmeticOrLogicalExpr &expr)
{
maybe_expand_expr (expr.get_left_expr_ptr ());
@@ -574,6 +625,13 @@ ExpandVisitor::visit (AST::LazyBooleanExpr &expr)
}
void
+ExpandVisitor::visit (AST::TypeCastExpr &expr)
+{
+ maybe_expand_expr (expr.get_casted_expr_ptr ());
+ maybe_expand_type (expr.get_type_to_cast_to_ptr ());
+}
+
+void
ExpandVisitor::visit (AST::AssignmentExpr &expr)
{
maybe_expand_expr (expr.get_left_expr_ptr ());
@@ -607,20 +665,11 @@ ExpandVisitor::visit (AST::CallExpr &expr)
}
void
-ExpandVisitor::visit (AST::MethodCallExpr &expr)
-{
- visit (expr.get_receiver_expr ());
-
- for (auto &param : expr.get_params ())
- maybe_expand_expr (param);
-}
-
-void
ExpandVisitor::visit (AST::ClosureExprInner &expr)
{
expand_closure_params (expr.get_params ());
- visit (expr.get_definition_expr ());
+ maybe_expand_expr (expr.get_definition_expr_ptr ());
}
void
@@ -640,7 +689,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
@@ -682,22 +731,10 @@ ExpandVisitor::visit (AST::IfLetExprConseqElse &expr)
}
void
-ExpandVisitor::visit (AST::MatchExpr &expr)
+ExpandVisitor::visit (AST::TupleExpr &expr)
{
- visit (expr.get_scrutinee_expr ());
-
- for (auto &match_case : expr.get_match_cases ())
- {
- auto &arm = match_case.get_arm ();
-
- for (auto &pattern : arm.get_patterns ())
- visit (pattern);
-
- if (arm.has_match_arm_guard ())
- maybe_expand_expr (arm.get_guard_expr_ptr ());
-
- maybe_expand_expr (match_case.get_expr_ptr ());
- }
+ for (auto &sub : expr.get_tuple_elems ())
+ maybe_expand_expr (sub);
}
void
@@ -843,15 +880,6 @@ ExpandVisitor::visit (AST::StaticItem &static_item)
}
void
-ExpandVisitor::visit (AST::TraitItemConst &const_item)
-{
- maybe_expand_type (const_item.get_type_ptr ());
-
- if (const_item.has_expr ())
- maybe_expand_expr (const_item.get_expr_ptr ());
-}
-
-void
ExpandVisitor::visit (AST::Trait &trait)
{
for (auto &generic : trait.get_generic_params ())
@@ -865,12 +893,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 ();
}
@@ -893,12 +918,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
@@ -921,12 +943,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
@@ -943,12 +962,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
@@ -986,13 +1003,70 @@ ExpandVisitor::visit (AST::StructPatternFieldIdent &field)
void
ExpandVisitor::visit (AST::GroupedPattern &pattern)
{
- visit (pattern.get_pattern_in_parens ());
+ maybe_expand_pattern (pattern.get_pattern_in_parens_ptr ());
+}
+
+void
+ExpandVisitor::visit (AST::SlicePatternItemsNoRest &items)
+{
+ for (auto &sub : items.get_patterns ())
+ maybe_expand_pattern (sub);
+}
+
+void
+ExpandVisitor::visit (AST::SlicePatternItemsHasRest &items)
+{
+ for (auto &sub : items.get_lower_patterns ())
+ maybe_expand_pattern (sub);
+ for (auto &sub : items.get_upper_patterns ())
+ maybe_expand_pattern (sub);
+}
+
+void
+ExpandVisitor::visit (AST::AltPattern &pattern)
+{
+ for (auto &alt : pattern.get_alts ())
+ maybe_expand_pattern (alt);
+}
+
+void
+ExpandVisitor::visit (AST::TupleStructItemsNoRest &tuple_items)
+{
+ for (auto &sub : tuple_items.get_patterns ())
+ maybe_expand_pattern (sub);
+}
+
+void
+ExpandVisitor::visit (AST::TupleStructItemsHasRest &tuple_items)
+{
+ for (auto &sub : tuple_items.get_lower_patterns ())
+ maybe_expand_pattern (sub);
+
+ for (auto &sub : tuple_items.get_upper_patterns ())
+ maybe_expand_pattern (sub);
+}
+
+void
+ExpandVisitor::visit (AST::TuplePatternItemsNoRest &tuple_items)
+{
+ for (auto &sub : tuple_items.get_patterns ())
+ maybe_expand_pattern (sub);
+}
+
+void
+ExpandVisitor::visit (AST::TuplePatternItemsHasRest &tuple_items)
+{
+ for (auto &sub : tuple_items.get_lower_patterns ())
+ maybe_expand_pattern (sub);
+
+ for (auto &sub : tuple_items.get_upper_patterns ())
+ maybe_expand_pattern (sub);
}
void
ExpandVisitor::visit (AST::LetStmt &stmt)
{
- visit (stmt.get_pattern ());
+ maybe_expand_pattern (stmt.get_pattern_ptr ());
if (stmt.has_type ())
maybe_expand_type (stmt.get_type_ptr ());
@@ -1022,10 +1096,18 @@ ExpandVisitor::visit (AST::BareFunctionType &type)
void
ExpandVisitor::visit (AST::FunctionParam &param)
{
+ maybe_expand_pattern (param.get_pattern_ptr ());
maybe_expand_type (param.get_type_ptr ());
}
void
+ExpandVisitor::visit (AST::VariadicParam &param)
+{
+ if (param.has_pattern ())
+ maybe_expand_pattern (param.get_pattern_ptr ());
+}
+
+void
ExpandVisitor::visit (AST::SelfParam &param)
{
/* TODO: maybe check for invariants being violated - e.g. both type and
diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h
index ad237c0..b79eb66 100644
--- a/gcc/rust/expand/rust-expand-visitor.h
+++ b/gcc/rust/expand/rust-expand-visitor.h
@@ -19,7 +19,9 @@
#ifndef RUST_EXPAND_VISITOR_H
#define RUST_EXPAND_VISITOR_H
+#include "rust-ast-pointer-visitor.h"
#include "rust-ast-visitor.h"
+#include "rust-item.h"
#include "rust-macro-expand.h"
#include "rust-proc-macro.h"
@@ -28,36 +30,55 @@ 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
+class ExpandVisitor : public AST::PointerVisitor
{
public:
- ExpandVisitor (MacroExpander &expander) : expander (expander) {}
+ ExpandVisitor (MacroExpander &expander)
+ : expander (expander), macro_invoc_expect_id (UNKNOWN_NODEID)
+ {}
/* Expand all of the macro invocations currently contained in a crate */
void go (AST::Crate &crate);
- using AST::DefaultASTVisitor::visit;
+ using AST::PointerVisitor::reseat;
+ using AST::PointerVisitor::visit;
- /*
- Maybe expand a macro invocation in lieu of an expression
- expr : Core guidelines R33, this function reseat the pointer.
- */
- void maybe_expand_expr (std::unique_ptr<AST::Expr> &expr);
+ void reseat (std::unique_ptr<AST::Expr> &ptr) override
+ {
+ maybe_expand_expr (ptr);
+ }
- /*
- Maybe expand a macro invocation in lieu of a type
- type : Core guidelines R33, this function reseat the pointer.
+ void reseat (std::unique_ptr<AST::Type> &ptr) override
+ {
+ maybe_expand_type (ptr);
+ }
+
+ void reseat (std::unique_ptr<AST::TypeNoBounds> &ptr) override
+ {
+ maybe_expand_type (ptr);
+ }
+
+ void reseat (std::unique_ptr<AST::Pattern> &ptr) override
+ {
+ maybe_expand_pattern (ptr);
+ }
+
+ /**
+ * Maybe expand a macro invocation in lieu of an expression, type or pattern.
+ *
+ * @ptr Core guidelines R33, this function reseats the pointer.
*/
- void maybe_expand_type (std::unique_ptr<AST::Type> &type);
+ void maybe_expand_expr (std::unique_ptr<AST::Expr> &ptr);
+ void maybe_expand_type (std::unique_ptr<AST::Type> &ptr);
+ void maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type);
+ void maybe_expand_pattern (std::unique_ptr<AST::Pattern> &ptr);
/**
* Expand all macro invocations in lieu of types within a vector of struct
@@ -107,7 +128,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,14 +144,17 @@ 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 ();)
{
auto &value = *it;
// Perform expansion
+ NodeId old_expect = value->get_node_id ();
+ std::swap (macro_invoc_expect_id, old_expect);
value->accept_vis (*this);
+ std::swap (macro_invoc_expect_id, old_expect);
auto final_fragment = expander.take_expanded_fragment ();
@@ -140,7 +164,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,18 +235,17 @@ public:
void visit (AST::AttrInputLiteral &) override;
void visit (AST::AttrInputMacro &) override;
void visit (AST::MetaItemLitExpr &) override;
- void visit (AST::MetaItemPathLit &) override;
- void visit (AST::ErrorPropagationExpr &expr) override;
+ void visit (AST::MetaItemPathExpr &) override;
void visit (AST::ArithmeticOrLogicalExpr &expr) override;
void visit (AST::ComparisonExpr &expr) override;
void visit (AST::LazyBooleanExpr &expr) override;
+ void visit (AST::TypeCastExpr &expr) override;
void visit (AST::AssignmentExpr &expr) override;
void visit (AST::CompoundAssignmentExpr &expr) override;
void visit (AST::GroupedExpr &expr) override;
void visit (AST::StructExprStruct &expr) override;
void visit (AST::CallExpr &expr) override;
- void visit (AST::MethodCallExpr &expr) override;
void visit (AST::ClosureExprInner &expr) override;
void visit (AST::BlockExpr &expr) override;
@@ -233,7 +256,7 @@ public:
void visit (AST::IfExprConseqElse &expr) override;
void visit (AST::IfLetExpr &expr) override;
void visit (AST::IfLetExprConseqElse &expr) override;
- void visit (AST::MatchExpr &expr) override;
+ void visit (AST::TupleExpr &expr) override;
void visit (AST::TypeParam &param) override;
void visit (AST::LifetimeWhereClauseItem &) override;
void visit (AST::TypeBoundWhereClauseItem &item) override;
@@ -253,7 +276,6 @@ public:
void visit (AST::Union &union_item) override;
void visit (AST::ConstantItem &const_item) override;
void visit (AST::StaticItem &static_item) override;
- void visit (AST::TraitItemConst &item) override;
void visit (AST::Trait &trait) override;
void visit (AST::InherentImpl &impl) override;
void visit (AST::TraitImpl &impl) override;
@@ -271,12 +293,20 @@ public:
void visit (AST::MetaListNameValueStr &) override;
void visit (AST::StructPatternFieldIdent &field) override;
void visit (AST::GroupedPattern &pattern) override;
+ void visit (AST::SlicePatternItemsNoRest &items) override;
+ void visit (AST::SlicePatternItemsHasRest &items) override;
+ void visit (AST::AltPattern &pattern) override;
+ void visit (AST::TupleStructItemsNoRest &tuple_items) override;
+ void visit (AST::TupleStructItemsHasRest &tuple_items) override;
+ void visit (AST::TuplePatternItemsNoRest &tuple_items) override;
+ void visit (AST::TuplePatternItemsHasRest &tuple_items) override;
void visit (AST::LetStmt &stmt) override;
void visit (AST::ExprStmt &stmt) override;
void visit (AST::BareFunctionType &type) override;
- void visit (AST::FunctionParam &type) override;
+ void visit (AST::FunctionParam &param) override;
+ void visit (AST::VariadicParam &param) override;
void visit (AST::SelfParam &type) override;
template <typename T>
@@ -289,6 +319,7 @@ public:
private:
MacroExpander &expander;
+ NodeId macro_invoc_expect_id;
};
} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc
index 4d02604..c991ca7 100644
--- a/gcc/rust/expand/rust-macro-builtins-asm.cc
+++ b/gcc/rust/expand/rust-macro-builtins-asm.cc
@@ -22,20 +22,9 @@
#include "rust-ast.h"
#include "rust-fmt.h"
#include "rust-stmt.h"
+#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"};
@@ -112,7 +101,7 @@ parse_clobber_abi (InlineAsmContext inline_asm_ctx)
if (token->get_id () == STRING_LITERAL)
{
// TODO: Caring for span in here.
- new_abis.push_back ({token->as_string (), token->get_locus ()});
+ new_abis.emplace_back (token->as_string (), token->get_locus ());
}
else
{
@@ -395,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"))
{
@@ -412,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;
@@ -425,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:
@@ -443,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
// }
@@ -499,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;
@@ -508,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
@@ -535,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
{
@@ -660,6 +659,15 @@ MacroBuiltin::asm_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
return parse_asm (invoc_locus, invoc, semicolon, is_global_asm);
}
+tl::optional<AST::Fragment>
+MacroBuiltin::llvm_asm_handler (location_t invoc_locus,
+ AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon,
+ AST::AsmKind is_global_asm)
+{
+ return parse_llvm_asm (invoc_locus, invoc, semicolon, is_global_asm);
+}
+
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_asm_arg (InlineAsmContext inline_asm_ctx)
{
@@ -671,6 +679,14 @@ parse_asm_arg (InlineAsmContext inline_asm_ctx)
{
token = parser.peek_current_token ();
+ if (token->get_id () == COLON || token->get_id () == SCOPE_RESOLUTION)
+ {
+ rust_error_at (
+ token->get_locus (),
+ "the legacy LLVM-style %<asm!%> syntax is no longer supported");
+ return tl::unexpected<InlineAsmParseError> (COMMITTED);
+ }
+
// We accept a comma token here.
if (token->get_id () != COMMA
&& inline_asm_ctx.consumed_comma_without_formatted_string)
@@ -771,12 +787,12 @@ expand_inline_asm_strings (InlineAsmContext inline_asm_ctx)
auto pieces = Fmt::Pieces::collect (template_str.symbol, false,
Fmt::ffi::ParseMode::InlineAsm);
- auto pieces_vec = pieces.get_pieces ();
+ auto &pieces_vec = pieces.get_pieces ();
std::string transformed_template_str = "";
for (size_t i = 0; i < pieces_vec.size (); i++)
{
- auto piece = pieces_vec[i];
+ auto &piece = pieces_vec[i];
if (piece.tag == Fmt::ffi::Piece::Tag::String)
{
transformed_template_str += piece.string._0.to_string ();
@@ -789,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);*/
@@ -811,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");
@@ -858,7 +880,8 @@ parse_asm (location_t invoc_locus, AST::MacroInvocData &invoc,
// context.
if (resulting_context)
{
- auto node = (*resulting_context).inline_asm.clone_expr_without_block ();
+ auto resulting_ctx = resulting_context.value ();
+ auto node = resulting_ctx.inline_asm.clone_expr_without_block ();
std::vector<AST::SingleASTNode> single_vec = {};
@@ -915,7 +938,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
@@ -962,4 +987,228 @@ validate (InlineAsmContext inline_asm_ctx)
{
return tl::expected<InlineAsmContext, InlineAsmParseError> (inline_asm_ctx);
}
+
+tl::optional<LlvmAsmContext>
+parse_llvm_templates (LlvmAsmContext ctx)
+{
+ auto &parser = ctx.parser;
+
+ auto token = parser.peek_current_token ();
+
+ if (token->get_id () == ctx.last_token_id
+ || token->get_id () != STRING_LITERAL)
+ {
+ return tl::nullopt;
+ }
+
+ ctx.llvm_asm.get_templates ().emplace_back (token->get_locus (),
+ strip_double_quotes (
+ token->as_string ()));
+ ctx.parser.skip_token ();
+
+ token = parser.peek_current_token ();
+ if (token->get_id () != ctx.last_token_id && token->get_id () != COLON
+ && token->get_id () != SCOPE_RESOLUTION)
+ {
+ // We do not handle multiple template string, we provide minimal support
+ // for the black_box intrinsics.
+ rust_unreachable ();
+ }
+
+ return ctx;
+}
+
+tl::optional<LlvmAsmContext>
+parse_llvm_arguments (LlvmAsmContext ctx)
+{
+ auto &parser = ctx.parser;
+ enum State
+ {
+ Templates = 0,
+ Output,
+ Input,
+ Clobbers,
+ Options
+ } current_state
+ = State::Templates;
+
+ while (parser.peek_current_token ()->get_id () != ctx.last_token_id
+ && parser.peek_current_token ()->get_id () != END_OF_FILE)
+ {
+ if (parser.peek_current_token ()->get_id () == SCOPE_RESOLUTION)
+ {
+ parser.skip_token (SCOPE_RESOLUTION);
+ current_state = static_cast<State> (current_state + 2);
+ }
+ else
+ {
+ parser.skip_token (COLON);
+ current_state = static_cast<State> (current_state + 1);
+ }
+
+ switch (current_state)
+ {
+ case State::Output:
+ parse_llvm_outputs (ctx);
+ break;
+ case State::Input:
+ parse_llvm_inputs (ctx);
+ break;
+ case State::Clobbers:
+ parse_llvm_clobbers (ctx);
+ break;
+ case State::Options:
+ parse_llvm_options (ctx);
+ break;
+ case State::Templates:
+ default:
+ rust_unreachable ();
+ }
+ }
+
+ return ctx;
+}
+
+void
+parse_llvm_operands (LlvmAsmContext &ctx, std::vector<AST::LlvmOperand> &result)
+{
+ auto &parser = ctx.parser;
+ auto token = parser.peek_current_token ();
+ while (token->get_id () != COLON && token->get_id () != SCOPE_RESOLUTION
+ && token->get_id () != ctx.last_token_id)
+ {
+ std::string constraint;
+ if (token->get_id () == STRING_LITERAL)
+ {
+ constraint = strip_double_quotes (token->as_string ());
+ }
+ parser.skip_token (STRING_LITERAL);
+ parser.skip_token (LEFT_PAREN);
+
+ token = parser.peek_current_token ();
+
+ ParseRestrictions restrictions;
+ restrictions.expr_can_be_null = true;
+ auto expr = parser.parse_expr ();
+
+ parser.skip_token (RIGHT_PAREN);
+
+ result.emplace_back (constraint, std::move (expr));
+
+ if (parser.peek_current_token ()->get_id () == COMMA)
+ parser.skip_token (COMMA);
+
+ token = parser.peek_current_token ();
+ }
+}
+
+void
+parse_llvm_outputs (LlvmAsmContext &ctx)
+{
+ parse_llvm_operands (ctx, ctx.llvm_asm.get_outputs ());
+}
+
+void
+parse_llvm_inputs (LlvmAsmContext &ctx)
+{
+ parse_llvm_operands (ctx, ctx.llvm_asm.get_inputs ());
+}
+
+void
+parse_llvm_clobbers (LlvmAsmContext &ctx)
+{
+ auto &parser = ctx.parser;
+ auto token = parser.peek_current_token ();
+ while (token->get_id () != COLON && token->get_id () != ctx.last_token_id)
+ {
+ if (token->get_id () == STRING_LITERAL)
+ {
+ ctx.llvm_asm.get_clobbers ().push_back (
+ {strip_double_quotes (token->as_string ()), token->get_locus ()});
+
+ parser.skip_token (STRING_LITERAL);
+ }
+
+ parser.maybe_skip_token (COMMA);
+ token = parser.peek_current_token ();
+ }
+}
+
+void
+parse_llvm_options (LlvmAsmContext &ctx)
+{
+ auto &parser = ctx.parser;
+ auto token = parser.peek_current_token ();
+
+ while (token->get_id () != ctx.last_token_id)
+ {
+ if (token->get_id () == STRING_LITERAL)
+ {
+ auto token_str = strip_double_quotes (token->as_string ());
+
+ if (token_str == "volatile")
+ ctx.llvm_asm.set_volatile (true);
+ else if (token_str == "alignstack")
+ ctx.llvm_asm.set_align_stack (true);
+ else if (token_str == "intel")
+ ctx.llvm_asm.set_dialect (AST::LlvmInlineAsm::Dialect::Intel);
+ else
+ rust_error_at (token->get_locus (),
+ "Unknown llvm assembly option %qs",
+ token_str.c_str ());
+ }
+ parser.skip_token (STRING_LITERAL);
+
+ token = parser.peek_current_token ();
+
+ if (token->get_id () == ctx.last_token_id)
+ continue;
+ parser.skip_token (COMMA);
+ }
+
+ parser.skip_token ();
+}
+
+tl::optional<AST::Fragment>
+parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon, AST::AsmKind is_global_asm)
+{
+ MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
+ Parser<MacroInvocLexer> parser (lex);
+ auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser);
+
+ AST::LlvmInlineAsm llvm_asm{invoc_locus};
+
+ auto asm_ctx = LlvmAsmContext (llvm_asm, parser, last_token_id);
+
+ tl::optional<LlvmAsmContext> resulting_context
+ = parse_llvm_templates (asm_ctx).and_then (parse_llvm_arguments);
+
+ if (resulting_context)
+ {
+ auto resulting_ctx = resulting_context.value ();
+ auto node = resulting_ctx.llvm_asm.clone_expr_without_block ();
+
+ std::vector<AST::SingleASTNode> single_vec = {};
+
+ // If the macro invocation has a semicolon (`asm!("...");`), then we
+ // need to make it a statement. This way, it will be expanded
+ // properly.
+ if (semicolon == AST::InvocKind::Semicoloned)
+ {
+ single_vec.emplace_back (
+ std::make_unique<AST::ExprStmt> (std::move (node), invoc_locus,
+ true /* has semicolon */));
+ }
+ else
+ single_vec.emplace_back (std::move (node));
+
+ AST::Fragment fragment_ast
+ = AST::Fragment (single_vec,
+ std::vector<std::unique_ptr<AST::Token>> ());
+ return fragment_ast;
+ }
+ return tl::nullopt;
+}
+
} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-builtins-asm.h b/gcc/rust/expand/rust-macro-builtins-asm.h
index 8081dae..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,8 +168,36 @@ 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
+
+class LlvmAsmContext
+{
+public:
+ AST::LlvmInlineAsm &llvm_asm;
+ Parser<MacroInvocLexer> &parser;
+ int last_token_id;
+
+public:
+ LlvmAsmContext (AST::LlvmInlineAsm &llvm_asm, Parser<MacroInvocLexer> &parser,
+ int last_token_id)
+ : llvm_asm (llvm_asm), parser (parser), last_token_id (last_token_id)
+ {}
+};
+
+void parse_llvm_outputs (LlvmAsmContext &ctx);
+
+void parse_llvm_inputs (LlvmAsmContext &ctx);
+
+void parse_llvm_clobbers (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,
+ AST::InvocKind semicolon, AST::AsmKind is_global_asm);
} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-builtins-format-args.cc b/gcc/rust/expand/rust-macro-builtins-format-args.cc
index 8eb32d5..eb2a1cc 100644
--- a/gcc/rust/expand/rust-macro-builtins-format-args.cc
+++ b/gcc/rust/expand/rust-macro-builtins-format-args.cc
@@ -37,30 +37,42 @@ struct FormatArgsParseError
} kind;
};
-static tl::expected<FormatArgsInput, FormatArgsParseError>
-format_args_parse_arguments (AST::MacroInvocData &invoc)
+static inline tl::expected<std::string, AST::Fragment>
+format_args_parse_expr (location_t invoc_locus, AST::MacroInvocData &invoc,
+ Parser<MacroInvocLexer> &parser,
+ BuiltinMacro macro_kind)
{
- MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
- Parser<MacroInvocLexer> parser (lex);
+ std::unique_ptr<AST::Expr> format_expr = parser.parse_expr ();
+ rust_assert (format_expr);
- // TODO: check if EOF - return that format_args!() requires at least one
- // argument
-
- auto args = AST::FormatArguments ();
- auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser);
- std::unique_ptr<AST::Expr> format_expr = nullptr;
-
- // 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 ();
+ if (format_expr->get_expr_kind () == AST::Expr::Kind::MacroInvocation)
+ {
+ std::vector<std::unique_ptr<AST::MacroInvocation>> pending;
+ pending.emplace_back (
+ static_cast<AST::MacroInvocation *> (format_expr.release ()));
+ return tl::unexpected<AST::Fragment> (
+ make_eager_builtin_invocation (macro_kind, invoc_locus,
+ invoc.get_delim_tok_tree (),
+ std::move (pending)));
+ }
// TODO(Arthur): Clean this up - if we haven't parsed a string literal but a
// macro invocation, what do we do here? return a tl::unexpected?
- auto format_str = static_cast<AST::LiteralExpr &> (*format_expr)
- .get_literal ()
- .as_string ();
+ rust_assert (format_expr->is_literal ());
+ return static_cast<AST::LiteralExpr &> (*format_expr)
+ .get_literal ()
+ .as_string ();
+}
+
+static inline tl::expected<AST::FormatArguments, FormatArgsParseError>
+format_args_parse_arguments (AST::MacroInvocData &invoc,
+ Parser<MacroInvocLexer> &parser,
+ TokenId last_token_id)
+{
+ // TODO: check if EOF - return that format_args!() requires at least one
+ // argument
+ auto args = AST::FormatArguments ();
// TODO: Allow implicit captures ONLY if the the first arg is a string literal
// and not a macro invocation
@@ -81,6 +93,11 @@ format_args_parse_arguments (AST::MacroInvocData &invoc)
{
parser.skip_token (COMMA);
+ // Check in case of an extraneous comma in the args list, which is
+ // allowed - format_args!("fmt", arg, arg2,)
+ if (parser.peek_current_token ()->get_id () == last_token_id)
+ break;
+
if (parser.peek_current_token ()->get_id () == IDENTIFIER
&& parser.peek (1)->get_id () == EQUAL)
{
@@ -112,7 +129,7 @@ format_args_parse_arguments (AST::MacroInvocData &invoc)
// we need to skip commas, don't we?
}
- return FormatArgsInput{std::move (format_str), std::move (args)};
+ return args;
}
tl::optional<AST::Fragment>
@@ -121,9 +138,24 @@ MacroBuiltin::format_args_handler (location_t invoc_locus,
AST::InvocKind semicolon,
AST::FormatArgs::Newline nl)
{
- auto input = format_args_parse_arguments (invoc);
+ MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
+ Parser<MacroInvocLexer> parser (lex);
+
+ auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser);
+
+ auto format_str = format_args_parse_expr (invoc_locus, invoc, parser,
+ nl == AST::FormatArgs::Newline::Yes
+ ? BuiltinMacro::FormatArgsNl
+ : BuiltinMacro::FormatArgs);
+
+ if (!format_str)
+ {
+ return std::move (format_str.error ());
+ }
+
+ auto args = format_args_parse_arguments (invoc, parser, last_token_id);
- if (!input)
+ if (!args)
{
rust_error_at (invoc_locus,
"could not parse arguments to %<format_args!()%>");
@@ -159,7 +191,7 @@ MacroBuiltin::format_args_handler (location_t invoc_locus,
bool append_newline = nl == AST::FormatArgs::Newline::Yes;
- auto fmt_str = std::move (input->format_str);
+ auto fmt_str = std::move (format_str.value ());
if (append_newline)
fmt_str += '\n';
@@ -175,7 +207,7 @@ MacroBuiltin::format_args_handler (location_t invoc_locus,
// for creating the `template`
auto fmt_args_node = AST::FormatArgs (invoc_locus, std::move (pieces),
- std::move (input->args));
+ std::move (args.value ()));
auto expanded
= Fmt::expand_format_args (fmt_args_node,
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..ce63017 100644
--- a/gcc/rust/expand/rust-macro-builtins-helpers.h
+++ b/gcc/rust/expand/rust-macro-builtins-helpers.h
@@ -22,7 +22,6 @@
#include "rust-ast.h"
#include "rust-cfg-strip.h"
#include "rust-diagnostics.h"
-#include "rust-early-name-resolver.h"
#include "rust-expr.h"
#include "rust-lex.h"
#include "rust-macro-builtins.h"
@@ -33,29 +32,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 +63,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..02c637b
--- /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->should_have_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 39c4c46..948f389 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -29,7 +29,6 @@
#include "rust-ast.h"
#include "rust-cfg-strip.h"
#include "rust-diagnostics.h"
-#include "rust-early-name-resolver.h"
#include "rust-expr.h"
#include "rust-lex.h"
#include "rust-macro-invoc-lexer.h"
@@ -83,7 +82,6 @@ const BiMap<std::string, BuiltinMacro> MacroBuiltin::builtins = {{
{"Ord", BuiltinMacro::Ord},
{"PartialOrd", BuiltinMacro::PartialOrd},
{"Hash", BuiltinMacro::Hash},
-
}};
AST::MacroTranscriberFunc
@@ -104,6 +102,15 @@ inline_asm_maker (AST::AsmKind global_asm)
};
}
+AST::MacroTranscriberFunc
+inline_llvm_asm_maker (AST::AsmKind global_asm)
+{
+ return [global_asm] (location_t loc, AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon) {
+ return MacroBuiltin::llvm_asm_handler (loc, invoc, semicolon, global_asm);
+ };
+}
+
std::unordered_map<std::string, AST::MacroTranscriberFunc>
MacroBuiltin::builtin_transcribers = {
{"assert", MacroBuiltin::assert_handler},
@@ -122,7 +129,7 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc>
{"format_args_nl", format_args_maker (AST::FormatArgs::Newline::Yes)},
{"asm", inline_asm_maker (AST::AsmKind::Inline)},
// FIXME: Is that okay?
- {"llvm_asm", inline_asm_maker (AST::AsmKind::Inline)},
+ {"llvm_asm", inline_llvm_asm_maker (AST::AsmKind::Inline)},
{"global_asm", inline_asm_maker (AST::AsmKind::Global)},
{"option_env", MacroBuiltin::option_env_handler},
/* Unimplemented macro builtins */
@@ -137,6 +144,7 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc>
{"cfg_accessible", MacroBuiltin::sorry},
{"rustc_const_stable", MacroBuiltin::sorry},
{"rustc_const_unstable", MacroBuiltin::sorry},
+ {"track_caller", MacroBuiltin::sorry},
/* Derive builtins do not need a real transcriber, but still need one. It
should however never be called since builtin derive macros get expanded
differently, and benefit from knowing on what kind of items they are
@@ -153,6 +161,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 ff06ebf..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"
@@ -181,9 +182,16 @@ public:
AST::AsmKind is_global_asm);
static tl::optional<AST::Fragment>
+ llvm_asm_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon, AST::AsmKind is_global_asm);
+
+ static tl::optional<AST::Fragment>
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 cd17a3f..b47e43a 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"
@@ -26,8 +27,8 @@
#include "rust-macro.h"
#include "rust-parse.h"
#include "rust-cfg-strip.h"
-#include "rust-early-name-resolver.h"
#include "rust-proc-macro.h"
+#include "rust-token-tree-desugar.h"
namespace Rust {
@@ -78,7 +79,10 @@ MacroExpander::expand_decl_macro (location_t invoc_locus,
* trees.
*/
- AST::DelimTokenTree &invoc_token_tree = invoc.get_delim_tok_tree ();
+ AST::DelimTokenTree &invoc_token_tree_sugar = invoc.get_delim_tok_tree ();
+
+ // We must first desugar doc comments into proper attributes
+ auto invoc_token_tree = AST::TokenTreeDesugar ().go (invoc_token_tree_sugar);
// find matching arm
AST::MacroRule *matched_rule = nullptr;
@@ -283,6 +287,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)
@@ -426,7 +450,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);
@@ -476,19 +501,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;
}
@@ -506,7 +534,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))
@@ -520,14 +549,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))
@@ -535,7 +566,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++;
@@ -552,19 +584,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;
}
@@ -613,7 +648,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);
@@ -621,26 +657,30 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
// matched fragment get the offset in the token stream
size_t offs_end = source.get_offs ();
- sub_stack.insert_metavar (
- MatchedFragment (fragment->get_ident ().as_string (),
- offs_begin, offs_end));
+ if (valid_current_match)
+ sub_stack.insert_metavar (
+ MatchedFragment (fragment->get_ident ().as_string (),
+ offs_begin, offs_end));
}
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);
@@ -650,15 +690,15 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
}
auto old_stack = sub_stack.pop ();
- // nest metavars into repetitions
- for (auto &ent : old_stack)
- sub_stack.append_fragment (ent.first, std::move (ent.second));
-
// If we've encountered an error once, stop trying to match more
// repetitions
if (!valid_current_match)
break;
+ // nest metavars into repetitions
+ for (auto &ent : old_stack)
+ sub_stack.append_fragment (ent.first, std::move (ent.second));
+
match_amount++;
// Break early if we notice there's too many expressions already
@@ -920,8 +960,11 @@ transcribe_expression (Parser<MacroInvocLexer> &parser)
auto &lexer = parser.get_token_source ();
auto start = lexer.get_offs ();
- auto expr = parser.parse_expr ();
- if (expr == nullptr)
+ auto attrs = parser.parse_outer_attributes ();
+ auto expr = parser.parse_expr (std::move (attrs));
+ for (auto error : parser.get_errors ())
+ error.emit ();
+ if (!expr)
return AST::Fragment::create_error ();
// FIXME: make this an error for some edititons
@@ -952,12 +995,38 @@ transcribe_type (Parser<MacroInvocLexer> &parser)
auto type = parser.parse_type (true);
for (auto err : parser.get_errors ())
err.emit ();
+ if (!type)
+ return AST::Fragment::create_error ();
auto end = lexer.get_offs ();
return AST::Fragment ({std::move (type)}, lexer.get_token_slice (start, end));
}
+/**
+ * Transcribe one pattern from a macro invocation
+ *
+ * @param parser Parser to extract statements from
+ */
+static AST::Fragment
+transcribe_pattern (Parser<MacroInvocLexer> &parser)
+{
+ auto &lexer = parser.get_token_source ();
+ auto start = lexer.get_offs ();
+
+ auto pattern = parser.parse_pattern ();
+ for (auto err : parser.get_errors ())
+ err.emit ();
+
+ if (!pattern)
+ return AST::Fragment::create_error ();
+
+ auto end = lexer.get_offs ();
+
+ return AST::Fragment ({std::move (pattern)},
+ lexer.get_token_slice (start, end));
+}
+
static AST::Fragment
transcribe_context (MacroExpander::ContextType ctx,
Parser<MacroInvocLexer> &parser, bool semicolon,
@@ -970,6 +1039,7 @@ transcribe_context (MacroExpander::ContextType ctx,
// -- Trait --> parser.parse_trait_item();
// -- Impl --> parser.parse_impl_item();
// -- Extern --> parser.parse_extern_item();
+ // -- Pattern --> parser.parse_pattern();
// -- None --> [has semicolon?]
// -- Yes --> parser.parse_stmt();
// -- No --> [switch invocation.delimiter()]
@@ -998,6 +1068,8 @@ transcribe_context (MacroExpander::ContextType ctx,
break;
case MacroExpander::ContextType::TYPE:
return transcribe_type (parser);
+ case MacroExpander::ContextType::PATTERN:
+ return transcribe_pattern (parser);
break;
case MacroExpander::ContextType::STMT:
return transcribe_many_stmts (parser, last_token_id, semicolon);
@@ -1039,8 +1111,9 @@ MacroExpander::transcribe_rule (
auto invoc_stream = invoc_token_tree.to_token_stream ();
auto macro_rule_tokens = transcribe_tree.to_token_stream ();
- auto substitute_context = SubstituteCtx (invoc_stream, macro_rule_tokens,
- matched_fragments, definition);
+ auto substitute_context
+ = SubstituteCtx (invoc_stream, macro_rule_tokens, matched_fragments,
+ definition, invoc_token_tree.get_locus ());
std::vector<std::unique_ptr<AST::Token>> substituted_tokens
= substitute_context.substitute_tokens ();
@@ -1087,11 +1160,7 @@ MacroExpander::transcribe_rule (
// emit any errors
if (parser.has_errors ())
- {
- for (auto &err : parser.get_errors ())
- rust_error_at (err.locus, "%s", err.message.c_str ());
- return AST::Fragment::create_error ();
- }
+ return AST::Fragment::create_error ();
// are all the tokens used?
bool did_delimit = parser.skip_token (last_token_id);
@@ -1124,7 +1193,7 @@ MacroExpander::parse_proc_macro_output (ProcMacro::TokenStream ts)
auto result = parser.parse_item (false);
if (result == nullptr)
break;
- nodes.push_back ({std::move (result)});
+ nodes.emplace_back (std::move (result));
}
break;
case ContextType::STMT:
@@ -1133,7 +1202,7 @@ MacroExpander::parse_proc_macro_output (ProcMacro::TokenStream ts)
auto result = parser.parse_stmt ();
if (result == nullptr)
break;
- nodes.push_back ({std::move (result)});
+ nodes.emplace_back (std::move (result));
}
break;
case ContextType::TRAIT:
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index 360294c..0e79466 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -27,7 +27,6 @@
#include "rust-ast.h"
#include "rust-macro.h"
#include "rust-hir-map.h"
-#include "rust-early-name-resolver.h"
#include "rust-name-resolver.h"
#include "rust-macro-invoc-lexer.h"
#include "rust-proc-macro-invoc-lexer.h"
@@ -291,6 +290,7 @@ struct MacroExpander
TRAIT,
IMPL,
TRAIT_IMPL,
+ PATTERN,
};
ExpansionCfg cfg;
@@ -358,7 +358,7 @@ struct MacroExpander
*
* @param parser Parser to use for matching
* @param rep Repetition to try and match
- * @param match_amount Reference in which to store the ammount of succesful
+ * @param match_amount Reference in which to store the amount of successful
* and valid matches
*
* @param lo_bound Lower bound of the matcher. When specified, the matcher
diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc
index 02e4e3b..36bae5b 100644
--- a/gcc/rust/expand/rust-macro-substitute-ctx.cc
+++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc
@@ -40,7 +40,7 @@ SubstituteCtx::substitute_dollar_crate (
if (*def_crate == current_crate)
{
expanded.push_back (std::make_unique<AST::Token> (
- Rust::Token::make_identifier (UNKNOWN_LOCATION, "crate")));
+ Rust::Token::make_identifier (origin, "crate")));
}
else
{
@@ -49,9 +49,9 @@ SubstituteCtx::substitute_dollar_crate (
rust_assert (name);
expanded.push_back (std::make_unique<AST::Token> (
- Rust::Token::make (SCOPE_RESOLUTION, UNKNOWN_LOCATION)));
+ Rust::Token::make (SCOPE_RESOLUTION, origin)));
expanded.push_back (std::make_unique<AST::Token> (
- Rust::Token::make_identifier (UNKNOWN_LOCATION, std::string (*name))));
+ Rust::Token::make_identifier (origin, std::string (*name))));
}
return true;
@@ -108,6 +108,12 @@ SubstituteCtx::substitute_metavar (
return true;
}
+static bool
+is_builtin_metavariable (AST::Token &token)
+{
+ return token.get_id () == CRATE;
+}
+
bool
SubstituteCtx::check_repetition_amount (size_t pattern_start,
size_t pattern_end,
@@ -125,6 +131,10 @@ SubstituteCtx::check_repetition_amount (size_t pattern_start,
|| frag_token->get_id () == IDENTIFIER)
{
auto it = fragments.find (frag_token->get_str ());
+
+ if (is_builtin_metavariable (*frag_token))
+ continue;
+
if (it == fragments.end ())
{
// If the repetition is not anything we know (ie no declared
@@ -136,6 +146,7 @@ SubstituteCtx::check_repetition_amount (size_t pattern_start,
frag_token->get_str ().c_str ());
is_valid = false;
+ continue;
}
auto &fragment = *it->second;
@@ -226,7 +237,7 @@ SubstituteCtx::substitute_repetition (
}
auto substitute_context
- = SubstituteCtx (input, new_macro, sub_map, definition);
+ = SubstituteCtx (input, new_macro, sub_map, definition, origin);
auto new_tokens = substitute_context.substitute_tokens ();
// Skip the first repetition, but add the separator to the expanded
@@ -273,7 +284,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-macro-substitute-ctx.h b/gcc/rust/expand/rust-macro-substitute-ctx.h
index c5c4956..3829a5a 100644
--- a/gcc/rust/expand/rust-macro-substitute-ctx.h
+++ b/gcc/rust/expand/rust-macro-substitute-ctx.h
@@ -27,6 +27,8 @@ class SubstituteCtx
std::vector<std::unique_ptr<AST::Token>> &macro;
std::map<std::string, MatchedFragmentContainer *> &fragments;
AST::MacroRulesDefinition &definition;
+ // Macro invocation location
+ location_t origin;
/**
* Find the repetition amount to use when expanding a repetition, and
@@ -43,9 +45,9 @@ public:
SubstituteCtx (std::vector<std::unique_ptr<AST::Token>> &input,
std::vector<std::unique_ptr<AST::Token>> &macro,
std::map<std::string, MatchedFragmentContainer *> &fragments,
- AST::MacroRulesDefinition &definition)
+ AST::MacroRulesDefinition &definition, location_t origin)
: input (input), macro (macro), fragments (fragments),
- definition (definition)
+ definition (definition), origin (origin)
{}
/**
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
new file mode 100644
index 0000000..aa20d50
--- /dev/null
+++ b/gcc/rust/expand/rust-token-tree-desugar.cc
@@ -0,0 +1,72 @@
+// 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-token-tree-desugar.h"
+#include "rust-ast.h"
+#include "rust-token.h"
+
+namespace Rust {
+namespace AST {
+
+DelimTokenTree
+TokenTreeDesugar::go (DelimTokenTree &tts)
+{
+ tts.accept_vis (*this);
+
+ return DelimTokenTree (tts.get_delim_type (), std::move (desugared),
+ tts.get_locus ());
+}
+
+void
+TokenTreeDesugar::append (TokenPtr &&new_token)
+{
+ desugared.emplace_back (std::make_unique<Token> (std::move (new_token)));
+}
+
+void
+TokenTreeDesugar::append (std::unique_ptr<TokenTree> &&new_token)
+{
+ desugared.emplace_back (std::move (new_token));
+}
+
+void
+TokenTreeDesugar::visit (Token &tts)
+{
+ if (tts.get_id () == TokenId::OUTER_DOC_COMMENT
+ || tts.get_id () == TokenId::INNER_DOC_COMMENT)
+ {
+ append (Rust::Token::make (TokenId::HASH, tts.get_locus ()));
+
+ if (tts.get_id () == TokenId::INNER_DOC_COMMENT)
+ append (Rust::Token::make (EXCLAM, tts.get_locus ()));
+
+ append (Rust::Token::make (TokenId::LEFT_SQUARE, tts.get_locus ()));
+ append (Rust::Token::make_identifier (tts.get_locus (), "doc"));
+ append (Rust::Token::make (TokenId::EQUAL, tts.get_locus ()));
+ append (Rust::Token::make_string (tts.get_locus (),
+ std::string (tts.get_str ())));
+ append (Rust::Token::make (TokenId::RIGHT_SQUARE, tts.get_locus ()));
+ }
+ else
+ {
+ append (tts.clone_token ());
+ }
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-token-tree-desugar.h b/gcc/rust/expand/rust-token-tree-desugar.h
new file mode 100644
index 0000000..da9d732
--- /dev/null
+++ b/gcc/rust/expand/rust-token-tree-desugar.h
@@ -0,0 +1,55 @@
+// 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_TOKEN_TREE_DESUGAR_H
+#define RUST_TOKEN_TREE_DESUGAR_H
+
+#include "rust-ast-visitor.h"
+#include "rust-system.h"
+#include "rust-ast.h"
+
+namespace Rust {
+namespace AST {
+
+/**
+ * Desugar a given token-tree before parsing it for a macro invocation. At the
+ * moment, the sole purpose of this desugar is to transform doc-comments into
+ * their attribute form (/// comment -> #[doc = "comment"])
+ */
+class TokenTreeDesugar : public DefaultASTVisitor
+{
+public:
+ TokenTreeDesugar () : desugared (std::vector<std::unique_ptr<TokenTree>> ())
+ {}
+
+ DelimTokenTree go (DelimTokenTree &tts);
+
+private:
+ std::vector<std::unique_ptr<TokenTree>> desugared;
+ void append (TokenPtr &&new_token);
+ void append (std::unique_ptr<TokenTree> &&new_token);
+
+ using DefaultASTVisitor::visit;
+
+ virtual void visit (Token &tts) override;
+};
+
+} // 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 b0d347e..8984c98 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
@@ -267,6 +288,10 @@ void
ASTLoweringBase::visit (AST::InlineAsm &)
{}
+void
+ASTLoweringBase::visit (AST::LlvmInlineAsm &)
+{}
+
// void ASTLoweringBase::visit(MatchCasematch_case) {}
// void ASTLoweringBase:: (AST::MatchCaseBlockExpr &) {}
// void ASTLoweringBase:: (AST::MatchCaseExpr &) {}
@@ -347,9 +372,6 @@ void
ASTLoweringBase::visit (AST::StaticItem &)
{}
void
-ASTLoweringBase::visit (AST::TraitItemConst &)
-{}
-void
ASTLoweringBase::visit (AST::TraitItemType &)
{}
void
@@ -448,20 +470,20 @@ ASTLoweringBase::visit (AST::StructPattern &)
{}
// void ASTLoweringBase::visit(TupleStructItemstuple_items) {}
void
-ASTLoweringBase::visit (AST::TupleStructItemsNoRange &)
+ASTLoweringBase::visit (AST::TupleStructItemsNoRest &)
{}
void
-ASTLoweringBase::visit (AST::TupleStructItemsRange &)
+ASTLoweringBase::visit (AST::TupleStructItemsHasRest &)
{}
void
ASTLoweringBase::visit (AST::TupleStructPattern &)
{}
// void ASTLoweringBase::visit(TuplePatternItemstuple_items) {}
void
-ASTLoweringBase::visit (AST::TuplePatternItemsMultiple &)
+ASTLoweringBase::visit (AST::TuplePatternItemsNoRest &)
{}
void
-ASTLoweringBase::visit (AST::TuplePatternItemsRanged &)
+ASTLoweringBase::visit (AST::TuplePatternItemsHasRest &)
{}
void
ASTLoweringBase::visit (AST::TuplePattern &)
@@ -470,6 +492,12 @@ void
ASTLoweringBase::visit (AST::GroupedPattern &)
{}
void
+ASTLoweringBase::visit (AST::SlicePatternItemsNoRest &)
+{}
+void
+ASTLoweringBase::visit (AST::SlicePatternItemsHasRest &)
+{}
+void
ASTLoweringBase::visit (AST::SlicePattern &)
{}
void
@@ -547,6 +575,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)
@@ -587,11 +619,10 @@ ASTLoweringBase::lower_generic_params (
std::vector<std::unique_ptr<AST::GenericParam>> &params)
{
std::vector<std::unique_ptr<HIR::GenericParam>> lowered;
+ lowered.reserve (params.size ());
+
for (auto &ast_param : params)
- {
- auto hir_param = ASTLowerGenericParam::translate (*ast_param);
- lowered.push_back (std::unique_ptr<HIR::GenericParam> (hir_param));
- }
+ lowered.emplace_back (ASTLowerGenericParam::translate (*ast_param));
return lowered;
}
@@ -624,18 +655,16 @@ HIR::GenericArgs
ASTLoweringBase::lower_generic_args (AST::GenericArgs &args)
{
std::vector<HIR::GenericArgsBinding> binding_args;
+ binding_args.reserve (args.get_binding_args ().size ());
+
for (auto &binding : args.get_binding_args ())
- {
- HIR::GenericArgsBinding b = lower_binding (binding);
- binding_args.push_back (std::move (b));
- }
+ binding_args.emplace_back (lower_binding (binding));
std::vector<HIR::Lifetime> lifetime_args;
+ lifetime_args.reserve (args.get_lifetime_args ().size ());
+
for (auto &lifetime : args.get_lifetime_args ())
- {
- HIR::Lifetime l = lower_lifetime (lifetime);
- lifetime_args.push_back (std::move (l));
- }
+ lifetime_args.emplace_back (lower_lifetime (lifetime));
std::vector<std::unique_ptr<HIR::Type>> type_args;
std::vector<HIR::ConstGenericArg> const_args;
@@ -644,16 +673,17 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args)
{
switch (arg.get_kind ())
{
- case AST::GenericArg::Kind::Type: {
- auto type = ASTLoweringType::translate (arg.get_type ());
- type_args.emplace_back (std::unique_ptr<HIR::Type> (type));
+ case AST::GenericArg::Kind::Type:
+ {
+ type_args.emplace_back (
+ ASTLoweringType::translate (arg.get_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),
- expr->get_locus ()));
+ const_args.emplace_back (std::unique_ptr<HIR::Expr> (expr),
+ expr->get_locus ());
break;
}
default:
@@ -690,8 +720,12 @@ ASTLoweringBase::lower_self (AST::Param &param)
self.get_is_mut (), self.get_locus ());
}
- AST::Lifetime l = self.get_lifetime ();
- return HIR::SelfParam (mapping, lower_lifetime (l), self.get_is_mut (),
+ tl::optional<HIR::Lifetime> lifetime = tl::nullopt;
+
+ if (self.has_lifetime ())
+ lifetime = lower_lifetime (self.get_lifetime ());
+
+ return HIR::SelfParam (mapping, lifetime, self.get_is_mut (),
self.get_locus ());
}
@@ -786,9 +820,17 @@ void
ASTLoweringBase::handle_doc_item_attribute (const ItemWrapper &,
const AST::Attribute &attr)
{
- auto simple_doc_comment = attr.has_attr_input ()
- && attr.get_attr_input ().get_attr_input_type ()
- == AST::AttrInput::AttrInputType::LITERAL;
+ if (!attr.has_attr_input ())
+ {
+ rust_error_at (attr.get_locus (),
+ "attribute must be of the form %qs or %qs",
+ "#[doc(hidden|inline|...)]", "#[doc = string]");
+ return;
+ }
+
+ auto simple_doc_comment = attr.get_attr_input ().get_attr_input_type ()
+ == AST::AttrInput::AttrInputType::LITERAL;
+
if (simple_doc_comment)
return;
@@ -809,9 +851,10 @@ void
ASTLoweringBase::handle_lang_item_attribute (const ItemWrapper &item,
const AST::Attribute &attr)
{
- auto &literal = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
- const auto &lang_item_type_str = literal.get_literal ().as_string ();
- auto lang_item_type = LangItem::Parse (lang_item_type_str);
+ auto lang_item_type_str = Analysis::Attributes::extract_string_literal (attr);
+ rust_assert (lang_item_type_str.has_value ());
+
+ auto lang_item_type = LangItem::Parse (*lang_item_type_str);
if (lang_item_type)
mappings.insert_lang_item (*lang_item_type,
@@ -836,41 +879,71 @@ ASTLoweringBase::attribute_handled_in_another_pass (
std::unique_ptr<HIR::TuplePatternItems>
ASTLoweringBase::lower_tuple_pattern_multiple (
- AST::TuplePatternItemsMultiple &pattern)
+ AST::TuplePatternItemsNoRest &pattern)
{
std::vector<std::unique_ptr<HIR::Pattern>> patterns;
+ patterns.reserve (pattern.get_patterns ().size ());
+
for (auto &p : pattern.get_patterns ())
- {
- HIR::Pattern *translated = ASTLoweringPattern::translate (*p);
- patterns.push_back (std::unique_ptr<HIR::Pattern> (translated));
- }
+ patterns.emplace_back (ASTLoweringPattern::translate (*p));
return std::unique_ptr<HIR::TuplePatternItems> (
- new HIR::TuplePatternItemsMultiple (std::move (patterns)));
+ new HIR::TuplePatternItemsNoRest (std::move (patterns)));
}
std::unique_ptr<TuplePatternItems>
ASTLoweringBase::lower_tuple_pattern_ranged (
- AST::TuplePatternItemsRanged &pattern)
+ AST::TuplePatternItemsHasRest &pattern)
{
std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns;
+ lower_patterns.reserve (pattern.get_lower_patterns ().size ());
std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns;
+ upper_patterns.reserve (pattern.get_upper_patterns ().size ());
for (auto &p : pattern.get_lower_patterns ())
- {
- HIR::Pattern *translated = ASTLoweringPattern::translate (*p);
- lower_patterns.push_back (std::unique_ptr<HIR::Pattern> (translated));
- }
+ lower_patterns.emplace_back (ASTLoweringPattern::translate (*p));
for (auto &p : pattern.get_upper_patterns ())
- {
- HIR::Pattern *translated = ASTLoweringPattern::translate (*p);
- upper_patterns.push_back (std::unique_ptr<HIR::Pattern> (translated));
- }
+ upper_patterns.emplace_back (ASTLoweringPattern::translate (*p));
return std::unique_ptr<HIR::TuplePatternItems> (
- new HIR::TuplePatternItemsRanged (std::move (lower_patterns),
- std::move (upper_patterns)));
+ new HIR::TuplePatternItemsHasRest (std::move (lower_patterns),
+ std::move (upper_patterns)));
+}
+
+std::unique_ptr<HIR::SlicePatternItems>
+ASTLoweringBase::lower_slice_pattern_no_rest (
+ AST::SlicePatternItemsNoRest &pattern)
+{
+ std::vector<std::unique_ptr<HIR::Pattern>> patterns;
+ patterns.reserve (pattern.get_patterns ().size ());
+ for (auto &p : pattern.get_patterns ())
+ patterns.emplace_back (ASTLoweringPattern::translate (*p));
+
+ return std::unique_ptr<HIR::SlicePatternItems> (
+ new HIR::SlicePatternItemsNoRest (std::move (patterns)));
+}
+
+std::unique_ptr<HIR::SlicePatternItems>
+ASTLoweringBase::lower_slice_pattern_has_rest (
+ AST::SlicePatternItemsHasRest &pattern)
+{
+ std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns;
+ lower_patterns.reserve (pattern.get_lower_patterns ().size ());
+ std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns;
+ upper_patterns.reserve (pattern.get_upper_patterns ().size ());
+
+ for (auto &p : pattern.get_lower_patterns ())
+ lower_patterns.emplace_back (
+ std::unique_ptr<HIR::Pattern> (ASTLoweringPattern::translate (*p)));
+
+ for (auto &p : pattern.get_upper_patterns ())
+ upper_patterns.emplace_back (
+ std::unique_ptr<HIR::Pattern> (ASTLoweringPattern::translate (*p)));
+
+ return std::unique_ptr<HIR::SlicePatternItems> (
+ new HIR::SlicePatternItemsHasRest (std::move (lower_patterns),
+ std::move (upper_patterns)));
}
std::unique_ptr<HIR::RangePatternBound>
@@ -879,7 +952,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);
@@ -890,7 +964,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
@@ -900,7 +975,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
@@ -964,14 +1040,15 @@ ASTLoweringBase::lower_extern_block (AST::ExternBlock &extern_block)
mappings.get_next_localdef_id (crate_num));
std::vector<std::unique_ptr<HIR::ExternalItem>> extern_items;
+ extern_items.reserve (extern_block.get_extern_items ().size ());
+
for (auto &item : extern_block.get_extern_items ())
{
if (item->is_marked_for_strip ())
continue;
- HIR::ExternalItem *lowered
- = ASTLoweringExternItem::translate (item.get (), mapping.get_hirid ());
- extern_items.push_back (std::unique_ptr<HIR::ExternalItem> (lowered));
+ extern_items.emplace_back (
+ ASTLoweringExternItem::translate (item.get (), mapping.get_hirid ()));
}
ABI abi = ABI::C;
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index b3bb174..933f77b 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,13 +152,12 @@ 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;
virtual void visit (AST::IfLetExprConseqElse &expr) override;
virtual void visit (AST::InlineAsm &expr) override;
+ virtual void visit (AST::LlvmInlineAsm &expr) override;
// virtual void visit(MatchCase& match_case) override;
// virtual void visit (AST::MatchCaseBlockExpr &match_case) override;
// virtual void visit (AST::MatchCaseExpr &match_case) override;
@@ -183,7 +189,6 @@ public:
virtual void visit (AST::Union &union_item) override;
virtual void visit (AST::ConstantItem &const_item) override;
virtual void visit (AST::StaticItem &static_item) override;
- virtual void visit (AST::TraitItemConst &item) override;
virtual void visit (AST::TraitItemType &item) override;
virtual void visit (AST::Trait &trait) override;
virtual void visit (AST::InherentImpl &impl) override;
@@ -222,14 +227,16 @@ public:
virtual void visit (AST::StructPatternFieldIdent &field) override;
virtual void visit (AST::StructPattern &pattern) override;
// virtual void visit(TupleStructItems& tuple_items) override;
- virtual void visit (AST::TupleStructItemsNoRange &tuple_items) override;
- virtual void visit (AST::TupleStructItemsRange &tuple_items) override;
+ virtual void visit (AST::TupleStructItemsNoRest &tuple_items) override;
+ virtual void visit (AST::TupleStructItemsHasRest &tuple_items) override;
virtual void visit (AST::TupleStructPattern &pattern) override;
// virtual void visit(TuplePatternItems& tuple_items) override;
- virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) override;
- virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override;
+ virtual void visit (AST::TuplePatternItemsNoRest &tuple_items) override;
+ virtual void visit (AST::TuplePatternItemsHasRest &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;
@@ -258,6 +265,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 ()
@@ -308,10 +316,16 @@ protected:
attribute_handled_in_another_pass (const std::string &attribute_path) const;
std::unique_ptr<TuplePatternItems>
- lower_tuple_pattern_multiple (AST::TuplePatternItemsMultiple &pattern);
+ lower_tuple_pattern_multiple (AST::TuplePatternItemsNoRest &pattern);
std::unique_ptr<TuplePatternItems>
- lower_tuple_pattern_ranged (AST::TuplePatternItemsRanged &pattern);
+ lower_tuple_pattern_ranged (AST::TuplePatternItemsHasRest &pattern);
+
+ std::unique_ptr<SlicePatternItems>
+ lower_slice_pattern_no_rest (AST::SlicePatternItemsNoRest &pattern);
+
+ std::unique_ptr<SlicePatternItems>
+ lower_slice_pattern_has_rest (AST::SlicePatternItemsHasRest &pattern);
std::unique_ptr<HIR::RangePatternBound>
lower_range_pattern_bound (AST::RangePatternBound &bound);
diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h
index a39c010..f10039b 100644
--- a/gcc/rust/hir/rust-ast-lower-block.h
+++ b/gcc/rust/hir/rust-ast-lower-block.h
@@ -195,7 +195,9 @@ public:
HIR::BlockExpr *loop_block
= ASTLoweringBlock::translate (expr.get_loop_block (), &terminated);
- HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ());
+ tl::optional<HIR::LoopLabel> loop_label = tl::nullopt;
+ if (expr.has_loop_label ())
+ loop_label = lower_loop_label (expr.get_loop_label ());
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
@@ -211,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-enumitem.h b/gcc/rust/hir/rust-ast-lower-enumitem.h
index 1b95345..8e28c08 100644
--- a/gcc/rust/hir/rust-ast-lower-enumitem.h
+++ b/gcc/rust/hir/rust-ast-lower-enumitem.h
@@ -80,6 +80,8 @@ public:
item.get_visibility ().as_string ().c_str ());
std::vector<HIR::TupleField> fields;
+ fields.reserve (item.get_tuple_fields ().size ());
+
for (auto &field : item.get_tuple_fields ())
{
HIR::Visibility vis = translate_visibility (field.get_visibility ());
@@ -90,11 +92,8 @@ public:
crate_num, field.get_node_id (), mappings.get_next_hir_id (crate_num),
mappings.get_next_localdef_id (crate_num));
- HIR::TupleField translated_field (field_mapping,
- std::unique_ptr<HIR::Type> (type),
- vis, field.get_locus (),
- field.get_outer_attrs ());
- fields.push_back (std::move (translated_field));
+ fields.emplace_back (field_mapping, std::unique_ptr<HIR::Type> (type),
+ vis, field.get_locus (), field.get_outer_attrs ());
}
translated
diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc
index 9f363c0..a1e24ee 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"
@@ -79,11 +81,10 @@ void
ASTLoweringExpr::visit (AST::TupleExpr &expr)
{
std::vector<std::unique_ptr<HIR::Expr>> tuple_elements;
+ tuple_elements.reserve (expr.get_tuple_elems ().size ());
+
for (auto &e : expr.get_tuple_elems ())
- {
- HIR::Expr *t = ASTLoweringExpr::translate (*e);
- tuple_elements.push_back (std::unique_ptr<HIR::Expr> (t));
- }
+ tuple_elements.emplace_back (ASTLoweringExpr::translate (*e));
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
@@ -127,6 +128,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);
@@ -175,12 +220,12 @@ ASTLoweringExpr::visit (AST::CallExpr &expr)
HIR::Expr *func = ASTLoweringExpr::translate (expr.get_function_expr ());
auto const &in_params = expr.get_params ();
+
std::vector<std::unique_ptr<HIR::Expr>> params;
+ params.reserve (in_params.size ());
+
for (auto &param : in_params)
- {
- auto trans = ASTLoweringExpr::translate (*param);
- params.push_back (std::unique_ptr<HIR::Expr> (trans));
- }
+ params.emplace_back (ASTLoweringExpr::translate (*param));
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (
@@ -202,11 +247,10 @@ ASTLoweringExpr::visit (AST::MethodCallExpr &expr)
auto const &in_params = expr.get_params ();
std::vector<std::unique_ptr<HIR::Expr>> params;
+ params.reserve (in_params.size ());
+
for (auto &param : in_params)
- {
- auto trans = ASTLoweringExpr::translate (*param);
- params.push_back (std::unique_ptr<HIR::Expr> (trans));
- }
+ params.emplace_back (ASTLoweringExpr::translate (*param));
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
@@ -292,11 +336,10 @@ void
ASTLoweringExpr::visit (AST::ArrayElemsValues &elems)
{
std::vector<std::unique_ptr<HIR::Expr>> elements;
+ elements.reserve (elems.get_values ().size ());
+
for (auto &elem : elems.get_values ())
- {
- HIR::Expr *translated_elem = ASTLoweringExpr::translate (*elem);
- elements.push_back (std::unique_ptr<HIR::Expr> (translated_elem));
- }
+ elements.emplace_back (ASTLoweringExpr::translate (*elem));
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (mappings.get_current_crate (),
@@ -523,13 +566,12 @@ ASTLoweringExpr::visit (AST::StructExprStructFields &struct_expr)
}
auto const &in_fields = struct_expr.get_fields ();
+
std::vector<std::unique_ptr<HIR::StructExprField>> fields;
+ fields.reserve (in_fields.size ());
+
for (auto &field : in_fields)
- {
- HIR::StructExprField *translated
- = ASTLowerStructExprField::translate (*field);
- fields.push_back (std::unique_ptr<HIR::StructExprField> (translated));
- }
+ fields.emplace_back (ASTLowerStructExprField::translate (*field));
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (),
@@ -589,16 +631,12 @@ ASTLoweringExpr::visit (AST::WhileLoopExpr &expr)
}
void
-ASTLoweringExpr::visit (AST::ForLoopExpr &expr)
-{
- rust_unreachable ();
-}
-
-void
ASTLoweringExpr::visit (AST::BreakExpr &expr)
{
- HIR::Lifetime break_label
- = lower_lifetime (expr.get_label ().get_lifetime ());
+ tl::optional<HIR::Lifetime> break_label = tl::nullopt;
+ if (expr.has_label ())
+ break_label = lower_lifetime (expr.get_label_unchecked ().get_lifetime ());
+
HIR::Expr *break_expr
= expr.has_break_expr ()
? ASTLoweringExpr::translate (expr.get_break_expr ())
@@ -618,7 +656,9 @@ ASTLoweringExpr::visit (AST::BreakExpr &expr)
void
ASTLoweringExpr::visit (AST::ContinueExpr &expr)
{
- HIR::Lifetime break_label = lower_lifetime (expr.get_label ());
+ tl::optional<HIR::Lifetime> break_label;
+ if (expr.has_label ())
+ break_label = lower_lifetime (expr.get_label_unchecked ());
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
@@ -633,9 +673,6 @@ ASTLoweringExpr::visit (AST::ContinueExpr &expr)
void
ASTLoweringExpr::visit (AST::BorrowExpr &expr)
{
- if (expr.is_raw_borrow ())
- rust_unreachable ();
-
HIR::Expr *borrow_lvalue
= ASTLoweringExpr::translate (expr.get_borrowed_expr ());
@@ -646,8 +683,8 @@ ASTLoweringExpr::visit (AST::BorrowExpr &expr)
auto *borrow_expr
= new HIR::BorrowExpr (mapping, std::unique_ptr<HIR::Expr> (borrow_lvalue),
- expr.get_mutability (), expr.get_outer_attrs (),
- expr.get_locus ());
+ expr.get_mutability (), expr.is_raw_borrow (),
+ expr.get_outer_attrs (), expr.get_locus ());
if (expr.get_is_double_borrow ())
{
@@ -659,8 +696,8 @@ ASTLoweringExpr::visit (AST::BorrowExpr &expr)
borrow_expr
= new HIR::BorrowExpr (mapping,
std::unique_ptr<HIR::Expr> (borrow_expr),
- expr.get_mutability (), expr.get_outer_attrs (),
- expr.get_locus ());
+ expr.get_mutability (), expr.is_raw_borrow (),
+ expr.get_outer_attrs (), expr.get_locus ());
}
translated = borrow_expr;
@@ -773,11 +810,10 @@ ASTLoweringExpr::visit (AST::ClosureExprInner &expr)
= ASTLoweringExpr::translate (expr.get_definition_expr ());
std::vector<HIR::ClosureParam> closure_params;
+ closure_params.reserve (expr.get_params ().size ());
+
for (auto &param : expr.get_params ())
- {
- HIR::ClosureParam p = lower_closure_param (param);
- closure_params.push_back (std::move (p));
- }
+ closure_params.emplace_back (lower_closure_param (param));
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
@@ -797,14 +833,13 @@ 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;
+ closure_params.reserve (expr.get_params ().size ());
+
for (auto &param : expr.get_params ())
- {
- HIR::ClosureParam p = lower_closure_param (param);
- closure_params.push_back (std::move (p));
- }
+ closure_params.emplace_back (lower_closure_param (param));
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
@@ -840,6 +875,7 @@ translate_operand_out (const AST::InlineAsmOperand &operand)
*out_value.expr.get ())));
return out;
}
+
HIR::InlineAsmOperand
translate_operand_inout (const AST::InlineAsmOperand &operand)
{
@@ -850,6 +886,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)
{
@@ -862,19 +899,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
@@ -954,6 +993,72 @@ ASTLoweringExpr::visit (AST::InlineAsm &expr)
hir_operands, expr.get_clobber_abi (),
expr.get_options (), mapping);
}
+
+namespace {
+// We're not really supporting llvm_asm, only the bare minimum for libcore's
+// blackbox
+// llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
+bool
+check_llvm_asm_support (const std::vector<LlvmOperand> &inputs,
+ const std::vector<LlvmOperand> &outputs,
+ const AST::LlvmInlineAsm &expr)
+{
+ return outputs.size () == 0 && inputs.size () <= 1
+ && expr.get_clobbers ().size () <= 1
+ && expr.get_templates ().size () == 1
+ && expr.get_templates ()[0].symbol == "";
+}
+
+} // namespace
+
+void
+ASTLoweringExpr::visit (AST::LlvmInlineAsm &expr)
+{
+ auto crate_num = mappings.get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings.get_next_hir_id (crate_num),
+ mappings.get_next_localdef_id (crate_num));
+
+ std::vector<LlvmOperand> inputs;
+ inputs.reserve (expr.get_inputs ().size ());
+
+ std::vector<LlvmOperand> outputs;
+ outputs.reserve (expr.get_outputs ().size ());
+
+ for (auto i : expr.get_inputs ())
+ {
+ std::unique_ptr<Expr> inner_expr
+ = std::unique_ptr<Expr> (translate (*i.expr.get ()));
+ inputs.emplace_back (i.constraint, std::move (inner_expr));
+ }
+
+ for (auto o : expr.get_outputs ())
+ {
+ std::unique_ptr<Expr> inner_expr
+ = std::unique_ptr<Expr> (translate (*o.expr.get ()));
+ outputs.emplace_back (o.constraint, std::move (inner_expr));
+ }
+
+ HIR::LlvmInlineAsm::Options options{expr.is_volatile (),
+ expr.is_stack_aligned (),
+ expr.get_dialect ()};
+
+ if (!check_llvm_asm_support (inputs, outputs, expr))
+ {
+ rust_error_at (expr.get_locus (), "unsupported %qs construct",
+ "llvm_asm");
+ rust_inform (
+ expr.get_locus (),
+ "%<llvm_asm%> has been replaced with %<asm%>, gccrs only supports a "
+ "subset of %<llvm_asm%> to compile libcore");
+ }
+
+ translated
+ = new HIR::LlvmInlineAsm (expr.get_locus (), inputs, outputs,
+ expr.get_templates (), expr.get_clobbers (),
+ options, expr.get_outer_attrs (), mapping);
+}
+
void
ASTLoweringExpr::visit (AST::FormatArgs &fmt)
{
@@ -961,5 +1066,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 af60e01..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;
@@ -122,9 +124,11 @@ public:
void visit (AST::ClosureExprInner &expr) override;
void visit (AST::ClosureExprInnerTyped &expr) override;
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..1f3ceda 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 ());
@@ -109,9 +109,8 @@ public:
mappings.get_next_localdef_id (
crate_num));
- function_params.push_back (
- HIR::NamedFunctionParam (mapping, param_name,
- std::unique_ptr<HIR::Type> (param_type)));
+ function_params.emplace_back (mapping, param_name,
+ std::unique_ptr<HIR::Type> (param_type));
}
auto crate_num = mappings.get_current_crate ();
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.cc b/gcc/rust/hir/rust-ast-lower-implitem.cc
index 5380d25..87f1e01 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.cc
+++ b/gcc/rust/hir/rust-ast-lower-implitem.cc
@@ -22,6 +22,7 @@
#include "rust-ast-lower-expr.h"
#include "rust-ast-lower-pattern.h"
#include "rust-ast-lower-block.h"
+#include "rust-hir-item.h"
#include "rust-item.h"
namespace Rust {
@@ -54,11 +55,11 @@ ASTLowerImplItem::translate (AST::AssociatedItem &item, HirId parent_impl_id)
void
ASTLowerImplItem::visit (AST::TypeAlias &alias)
{
- std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+ std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::Visibility vis = translate_visibility (alias.get_visibility ());
- std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+ std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
if (alias.has_generics ())
generic_params = lower_generic_params (alias.get_generic_params ());
@@ -109,12 +110,12 @@ void
ASTLowerImplItem::visit (AST::Function &function)
{
// ignore for now and leave empty
- std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+ std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
for (auto &item : function.get_where_clause ().get_items ())
{
HIR::WhereClauseItem *i
= ASTLowerWhereClauseItem::translate (*item.get ());
- where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
+ where_clause_items.emplace_back (i);
}
HIR::WhereClause where_clause (std::move (where_clause_items));
@@ -123,7 +124,7 @@ ASTLowerImplItem::visit (AST::Function &function)
HIR::Visibility vis = translate_visibility (function.get_visibility ());
// need
- std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+ std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
if (function.has_generics ())
{
generic_params = lower_generic_params (function.get_generic_params ());
@@ -131,15 +132,19 @@ ASTLowerImplItem::visit (AST::Function &function)
Identifier function_name = function.get_function_name ();
location_t locus = function.get_locus ();
- HIR::SelfParam self_param = HIR::SelfParam::error ();
+ tl::optional<HIR::SelfParam> self_param = tl::nullopt;
if (function.has_self_param ())
self_param = lower_self (function.get_self_param ());
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
+ = function.is_default () ? Defaultness::Default : Defaultness::Final;
+
std::vector<HIR::FunctionParam> function_params;
for (auto &p : function.get_function_params ())
{
@@ -157,10 +162,9 @@ ASTLowerImplItem::visit (AST::Function &function)
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- auto hir_param
- = HIR::FunctionParam (mapping, std::move (translated_pattern),
- std::move (translated_type), param.get_locus ());
- function_params.push_back (std::move (hir_param));
+ function_params.emplace_back (mapping, std::move (translated_pattern),
+ std::move (translated_type),
+ param.get_locus ());
}
bool terminated = false;
@@ -183,15 +187,15 @@ ASTLowerImplItem::visit (AST::Function &function)
std::move (function_params), std::move (return_type),
std::move (where_clause), std::move (function_body),
std::move (vis), function.get_outer_attrs (),
- std::move (self_param), locus);
+ std::move (self_param), defaultness, locus);
- if (!fn->get_self_param ().is_error ())
+ if (fn->is_method ())
{
// insert mappings for self
- mappings.insert_hir_self_param (&fn->get_self_param ());
+ mappings.insert_hir_self_param (&fn->get_self_param_unchecked ());
mappings.insert_location (
- fn->get_self_param ().get_mappings ().get_hirid (),
- fn->get_self_param ().get_locus ());
+ fn->get_self_param_unchecked ().get_mappings ().get_hirid (),
+ fn->get_self_param_unchecked ().get_locus ());
}
// add the mappings for the function params at the end
@@ -229,12 +233,12 @@ ASTLowerTraitItem::translate (AST::AssociatedItem &item)
void
ASTLowerTraitItem::visit (AST::Function &func)
{
- std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+ std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::FunctionQualifiers qualifiers
= lower_qualifiers (func.get_qualifiers ());
- std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+ std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
if (func.has_generics ())
generic_params = lower_generic_params (func.get_generic_params ());
@@ -245,9 +249,9 @@ ASTLowerTraitItem::visit (AST::Function &func)
// set self parameter to error if this is a method
// else lower to hir
- HIR::SelfParam self_param = func.has_self_param ()
- ? lower_self (func.get_self_param ())
- : HIR::SelfParam::error ();
+ tl::optional<HIR::SelfParam> self_param = tl::nullopt;
+ if (func.has_self_param ())
+ self_param = lower_self (func.get_self_param ());
std::vector<HIR::FunctionParam> function_params;
for (auto &p : func.get_function_params ())
@@ -267,10 +271,18 @@ ASTLowerTraitItem::visit (AST::Function &func)
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- 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.emplace_back (mapping, std::move (translated_pattern),
+ std::move (translated_type),
+ param.get_locus ());
+ }
+
+ 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 (),
@@ -296,13 +308,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
- 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 ())
@@ -313,10 +318,10 @@ ASTLowerTraitItem::visit (AST::Function &func)
}
void
-ASTLowerTraitItem::visit (AST::TraitItemConst &constant)
+ASTLowerTraitItem::visit (AST::ConstantItem &constant)
{
HIR::Type *type = ASTLoweringType::translate (constant.get_type ());
- HIR::Expr *expr = constant.has_expression ()
+ HIR::Expr *expr = constant.has_expr ()
? ASTLoweringExpr::translate (constant.get_expr ())
: nullptr;
@@ -337,7 +342,24 @@ ASTLowerTraitItem::visit (AST::TraitItemConst &constant)
void
ASTLowerTraitItem::visit (AST::TraitItemType &type)
{
- std::vector<std::unique_ptr<HIR::TypeParamBound> > type_param_bounds;
+ // Lower generic parameters (for GATs)
+ std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+ for (auto &param : type.get_generic_params ())
+ {
+ auto lowered_param = ASTLowerGenericParam::translate (*param.get ());
+ generic_params.push_back (
+ std::unique_ptr<HIR::GenericParam> (lowered_param));
+ }
+
+ // Lower type parameter bounds
+ std::vector<std::unique_ptr<HIR::TypeParamBound>> type_param_bounds;
+ for (auto &bound : type.get_type_param_bounds ())
+ {
+ auto lowered_bound = lower_bound (*bound.get ());
+ type_param_bounds.push_back (
+ std::unique_ptr<HIR::TypeParamBound> (lowered_bound));
+ }
+
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
mappings.get_next_hir_id (crate_num),
@@ -345,6 +367,7 @@ ASTLowerTraitItem::visit (AST::TraitItemType &type)
HIR::TraitItemType *trait_item
= new HIR::TraitItemType (mapping, type.get_identifier (),
+ std::move (generic_params),
std::move (type_param_bounds),
type.get_outer_attrs (), type.get_locus ());
translated = trait_item;
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h
index 8331bba..dfcf567 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.h
+++ b/gcc/rust/hir/rust-ast-lower-implitem.h
@@ -49,7 +49,7 @@ class ASTLowerTraitItem : public ASTLoweringBase
public:
static HIR::TraitItem *translate (AST::AssociatedItem &item);
void visit (AST::Function &func) override;
- void visit (AST::TraitItemConst &constant) override;
+ void visit (AST::ConstantItem &constant) override;
void visit (AST::TraitItemType &type) override;
private:
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc
index 5dbcad5..81815ff 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -72,7 +72,7 @@ ASTLoweringItem::visit (AST::Module &module)
// The item may be null if it doesn't need to live in the HIR - for
// example, macro rules definitions
if (transitem)
- items.push_back (std::unique_ptr<Item> (transitem));
+ items.emplace_back (transitem);
}
// should be lowered/copied from module.get_in/outer_attrs()
@@ -90,12 +90,11 @@ void
ASTLoweringItem::visit (AST::TypeAlias &alias)
{
std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+ where_clause_items.reserve (alias.get_where_clause ().get_items ().size ());
+
for (auto &item : alias.get_where_clause ().get_items ())
- {
- HIR::WhereClauseItem *i
- = ASTLowerWhereClauseItem::translate (*item.get ());
- where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
- }
+ where_clause_items.emplace_back (
+ ASTLowerWhereClauseItem::translate (*item.get ()));
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::Visibility vis = translate_visibility (alias.get_visibility ());
@@ -130,17 +129,19 @@ ASTLoweringItem::visit (AST::TupleStruct &struct_decl)
}
std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+ where_clause_items.reserve (
+ struct_decl.get_where_clause ().get_items ().size ());
+
for (auto &item : struct_decl.get_where_clause ().get_items ())
- {
- HIR::WhereClauseItem *i
- = ASTLowerWhereClauseItem::translate (*item.get ());
- where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
- }
+ where_clause_items.emplace_back (
+ ASTLowerWhereClauseItem::translate (*item.get ()));
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::Visibility vis = translate_visibility (struct_decl.get_visibility ());
std::vector<HIR::TupleField> fields;
+ fields.reserve (struct_decl.get_fields ().size ());
+
for (AST::TupleField &field : struct_decl.get_fields ())
{
if (field.get_field_type ().is_marked_for_strip ())
@@ -155,11 +156,8 @@ ASTLoweringItem::visit (AST::TupleStruct &struct_decl)
mappings.get_next_hir_id (crate_num),
mappings.get_next_localdef_id (crate_num));
- HIR::TupleField translated_field (mapping,
- std::unique_ptr<HIR::Type> (type), vis,
- field.get_locus (),
- field.get_outer_attrs ());
- fields.push_back (std::move (translated_field));
+ fields.emplace_back (mapping, std::unique_ptr<HIR::Type> (type), vis,
+ field.get_locus (), field.get_outer_attrs ());
}
auto crate_num = mappings.get_current_crate ();
@@ -185,12 +183,12 @@ ASTLoweringItem::visit (AST::StructStruct &struct_decl)
}
std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+ where_clause_items.reserve (
+ struct_decl.get_where_clause ().get_items ().size ());
+
for (auto &item : struct_decl.get_where_clause ().get_items ())
- {
- HIR::WhereClauseItem *i
- = ASTLowerWhereClauseItem::translate (*item.get ());
- where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
- }
+ where_clause_items.emplace_back (
+ ASTLowerWhereClauseItem::translate (*item.get ()));
HIR::WhereClause where_clause (std::move (where_clause_items));
@@ -217,7 +215,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));
}
@@ -245,25 +243,26 @@ ASTLoweringItem::visit (AST::Enum &enum_decl)
}
std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+ where_clause_items.reserve (
+ enum_decl.get_where_clause ().get_items ().size ());
+
for (auto &item : enum_decl.get_where_clause ().get_items ())
- {
- HIR::WhereClauseItem *i
- = ASTLowerWhereClauseItem::translate (*item.get ());
- where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
- }
+ where_clause_items.emplace_back (
+ ASTLowerWhereClauseItem::translate (*item.get ()));
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::Visibility vis = translate_visibility (enum_decl.get_visibility ());
// bool is_unit = enum_decl.is_zero_variant ();
std::vector<std::unique_ptr<HIR::EnumItem>> items;
+ items.reserve (enum_decl.get_variants ().size ());
+
for (auto &variant : enum_decl.get_variants ())
{
if (variant->is_marked_for_strip ())
continue;
- HIR::EnumItem *hir_item = ASTLoweringEnumItem::translate (variant.get ());
- items.push_back (std::unique_ptr<HIR::EnumItem> (hir_item));
+ items.emplace_back (ASTLoweringEnumItem::translate (variant.get ()));
}
auto crate_num = mappings.get_current_crate ();
@@ -288,17 +287,16 @@ ASTLoweringItem::visit (AST::Union &union_decl)
{
std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
if (union_decl.has_generics ())
- {
- generic_params = lower_generic_params (union_decl.get_generic_params ());
- }
+ generic_params = lower_generic_params (union_decl.get_generic_params ());
std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+ where_clause_items.reserve (
+ union_decl.get_where_clause ().get_items ().size ());
+
for (auto &item : union_decl.get_where_clause ().get_items ())
- {
- HIR::WhereClauseItem *i
- = ASTLowerWhereClauseItem::translate (*item.get ());
- where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
- }
+ where_clause_items.emplace_back (
+ ASTLowerWhereClauseItem::translate (*item.get ()));
+
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::Visibility vis = translate_visibility (union_decl.get_visibility ());
@@ -367,7 +365,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 (),
@@ -388,12 +388,12 @@ ASTLoweringItem::visit (AST::Function &function)
return;
std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+ where_clause_items.reserve (
+ function.get_where_clause ().get_items ().size ());
+
for (auto &item : function.get_where_clause ().get_items ())
- {
- HIR::WhereClauseItem *i
- = ASTLowerWhereClauseItem::translate (*item.get ());
- where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
- }
+ where_clause_items.emplace_back (
+ ASTLowerWhereClauseItem::translate (*item.get ()));
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::FunctionQualifiers qualifiers
@@ -411,14 +411,46 @@ 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;
+ function_params.reserve (function.get_function_params ().size ());
+
+ auto crate_num = mappings.get_current_crate ();
for (auto &p : function.get_function_params ())
{
- if (p->is_variadic () || p->is_self ())
+ if (p->is_variadic ())
continue;
+ if (p->is_self ())
+ {
+ rich_location r (line_table, p->get_locus ());
+ r.add_range (function.get_locus ());
+ rust_error_at (
+ r, "%<self%> parameter is only allowed in associated functions");
+
+ // rustc creates a synthetic regular fn-param here pointing to a
+ // generic Self as far as i can see but that seems over the top for
+ // now.
+ //
+ // see this example (invalid code):
+ //
+ // pub trait X {
+ // fn x() {
+ // fn f(&mut self) {}
+ // f();
+ // }
+ // }
+ //
+ // without a synthetic param we wont get the number of args error as
+ // well but i think this is fine for now.
+ //
+ // problem is what we make the param type to become...
+
+ continue;
+ }
+
auto param = static_cast<AST::FunctionParam &> (*p);
auto translated_pattern = std::unique_ptr<HIR::Pattern> (
@@ -431,10 +463,9 @@ ASTLoweringItem::visit (AST::Function &function)
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- auto hir_param
- = HIR::FunctionParam (mapping, std::move (translated_pattern),
- std::move (translated_type), param.get_locus ());
- function_params.push_back (std::move (hir_param));
+ function_params.emplace_back (mapping, std::move (translated_pattern),
+ std::move (translated_type),
+ param.get_locus ());
}
bool terminated = false;
@@ -443,7 +474,6 @@ ASTLoweringItem::visit (AST::Function &function)
ASTLoweringBlock::translate (*function.get_definition ().value (),
&terminated));
- auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, function.get_node_id (),
mappings.get_next_hir_id (crate_num),
mappings.get_next_localdef_id (crate_num));
@@ -451,13 +481,16 @@ ASTLoweringItem::visit (AST::Function &function)
mappings.insert_location (function_body->get_mappings ().get_hirid (),
function.get_locus ());
+ Defaultness defaultness
+ = function.is_default () ? Defaultness::Default : Defaultness::Final;
+
auto fn
= new HIR::Function (mapping, std::move (function_name),
std::move (qualifiers), std::move (generic_params),
std::move (function_params), std::move (return_type),
std::move (where_clause), std::move (function_body),
std::move (vis), function.get_outer_attrs (),
- HIR::SelfParam::error (), locus);
+ tl::nullopt, defaultness, locus);
// add the mappings for the function params at the end
for (auto &param : fn->get_function_params ())
@@ -473,11 +506,12 @@ void
ASTLoweringItem::visit (AST::InherentImpl &impl_block)
{
std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+ where_clause_items.reserve (
+ impl_block.get_where_clause ().get_items ().size ());
+
for (auto &item : impl_block.get_where_clause ().get_items ())
- {
- HIR::WhereClauseItem *i = ASTLowerWhereClauseItem::translate (*item);
- where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
- }
+ where_clause_items.emplace_back (
+ ASTLowerWhereClauseItem::translate (*item));
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::Visibility vis = translate_visibility (impl_block.get_visibility ());
@@ -491,7 +525,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);
@@ -533,7 +568,7 @@ ASTLoweringItem::visit (AST::InherentImpl &impl_block)
HIR::ImplItem *lowered
= ASTLowerImplItem::translate (*impl_item, mapping.get_hirid ());
rust_assert (lowered != nullptr);
- impl_items.push_back (std::unique_ptr<HIR::ImplItem> (lowered));
+ impl_items.emplace_back (lowered);
impl_item_ids.push_back (lowered->get_impl_mappings ().get_hirid ());
}
@@ -556,12 +591,12 @@ void
ASTLoweringItem::visit (AST::Trait &trait)
{
std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+ where_clause_items.reserve (trait.get_where_clause ().get_items ().size ());
+
for (auto &item : trait.get_where_clause ().get_items ())
- {
- HIR::WhereClauseItem *i
- = ASTLowerWhereClauseItem::translate (*item.get ());
- where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
- }
+ where_clause_items.emplace_back (
+ ASTLowerWhereClauseItem::translate (*item.get ()));
+
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::Visibility vis = translate_visibility (trait.get_visibility ());
@@ -582,23 +617,24 @@ ASTLoweringItem::visit (AST::Trait &trait)
if (trait.has_type_param_bounds ())
{
for (auto &bound : trait.get_type_param_bounds ())
- {
- HIR::TypeParamBound *b = lower_bound (*bound);
- type_param_bounds.push_back (
- std::unique_ptr<HIR::TypeParamBound> (b));
- }
+ type_param_bounds.emplace_back (lower_bound (*bound));
}
+ auto trait_item_size = trait.get_trait_items ().size ();
+
std::vector<std::unique_ptr<HIR::TraitItem>> trait_items;
+ trait_items.reserve (trait_item_size);
std::vector<HirId> trait_item_ids;
+ trait_item_ids.reserve (trait_item_size);
+
for (auto &item : trait.get_trait_items ())
{
if (item->is_marked_for_strip ())
continue;
HIR::TraitItem *lowered = ASTLowerTraitItem::translate (*item);
- trait_items.push_back (std::unique_ptr<HIR::TraitItem> (lowered));
trait_item_ids.push_back (lowered->get_mappings ().get_hirid ());
+ trait_items.emplace_back (lowered);
}
auto crate_num = mappings.get_current_crate ();
@@ -629,13 +665,16 @@ ASTLoweringItem::visit (AST::Trait &trait)
void
ASTLoweringItem::visit (AST::TraitImpl &impl_block)
{
- std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
bool unsafe = impl_block.is_unsafe ();
+
+ std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+ where_clause_items.reserve (
+ impl_block.get_where_clause ().get_items ().size ());
+
for (auto &item : impl_block.get_where_clause ().get_items ())
- {
- HIR::WhereClauseItem *i = ASTLowerWhereClauseItem::translate (*item);
- where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i));
- }
+ where_clause_items.emplace_back (
+ ASTLowerWhereClauseItem::translate (*item));
+
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::Visibility vis = translate_visibility (impl_block.get_visibility ());
@@ -648,7 +687,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);
@@ -682,8 +722,13 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block)
mappings.get_next_hir_id (crate_num),
mappings.get_next_localdef_id (crate_num));
+ auto impl_items_size = impl_block.get_impl_items ().size ();
+
std::vector<std::unique_ptr<HIR::ImplItem>> impl_items;
+ impl_items.reserve (impl_items_size);
std::vector<HirId> impl_item_ids;
+ impl_item_ids.reserve (impl_items_size);
+
for (auto &impl_item : impl_block.get_impl_items ())
{
if (impl_item->is_marked_for_strip ())
@@ -692,8 +737,8 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block)
HIR::ImplItem *lowered
= ASTLowerImplItem::translate (*impl_item, mapping.get_hirid ());
rust_assert (lowered != nullptr);
- impl_items.push_back (std::unique_ptr<HIR::ImplItem> (lowered));
impl_item_ids.push_back (lowered->get_impl_mappings ().get_hirid ());
+ impl_items.emplace_back (lowered);
}
BoundPolarity polarity = impl_block.is_exclam ()
@@ -726,6 +771,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..c941a5c 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,24 +81,45 @@ ASTLoweringPattern::visit (AST::TupleStructPattern &pattern)
auto &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case AST::TupleStructItems::RANGE: {
- // TODO
- rust_unreachable ();
+ case AST::TupleStructItems::HAS_REST:
+ {
+ AST::TupleStructItemsHasRest &items_has_rest
+ = static_cast<AST::TupleStructItemsHasRest &> (items);
+
+ std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns;
+ lower_patterns.reserve (items_has_rest.get_lower_patterns ().size ());
+ for (auto &pattern_member : items_has_rest.get_lower_patterns ())
+ {
+ lower_patterns.emplace_back (
+ ASTLoweringPattern::translate (*pattern_member));
+ }
+
+ std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns;
+ upper_patterns.reserve (items_has_rest.get_upper_patterns ().size ());
+ for (auto &pattern_member : items_has_rest.get_upper_patterns ())
+ {
+ upper_patterns.emplace_back (
+ ASTLoweringPattern::translate (*pattern_member));
+ }
+
+ lowered = new HIR::TupleStructItemsHasRest (std::move (lower_patterns),
+ std::move (upper_patterns));
}
break;
- case AST::TupleStructItems::NO_RANGE: {
- AST::TupleStructItemsNoRange &items_no_range
- = static_cast<AST::TupleStructItemsNoRange &> (items);
+ case AST::TupleStructItems::NO_REST:
+ {
+ AST::TupleStructItemsNoRest &items_no_rest
+ = static_cast<AST::TupleStructItemsNoRest &> (items);
std::vector<std::unique_ptr<HIR::Pattern>> patterns;
- for (auto &inner_pattern : items_no_range.get_patterns ())
- {
- HIR::Pattern *p = ASTLoweringPattern::translate (*inner_pattern);
- patterns.push_back (std::unique_ptr<HIR::Pattern> (p));
- }
+ patterns.reserve (items_no_rest.get_patterns ().size ());
+
+ for (auto &inner_pattern : items_no_rest.get_patterns ())
+ patterns.emplace_back (
+ ASTLoweringPattern::translate (*inner_pattern));
- lowered = new HIR::TupleStructItemsNoRange (std::move (patterns));
+ lowered = new HIR::TupleStructItemsNoRest (std::move (patterns));
}
break;
}
@@ -112,7 +140,6 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
= ASTLowerPathInExpression::translate (pattern.get_path ());
auto &raw_elems = pattern.get_struct_pattern_elems ();
- rust_assert (!raw_elems.has_etc ());
std::vector<std::unique_ptr<HIR::StructPatternField>> fields;
for (auto &field : raw_elems.get_struct_pattern_fields ())
@@ -120,7 +147,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 +168,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 +189,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 ());
@@ -184,7 +214,7 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
mappings.insert_node_to_hir (field_node_id, field_id);
// add it to the lowered fields list
- fields.push_back (std::unique_ptr<HIR::StructPatternField> (f));
+ fields.emplace_back (f);
}
auto crate_num = mappings.get_current_crate ();
@@ -192,7 +222,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- HIR::StructPatternElements elems (std::move (fields));
+ HIR::StructPatternElements elems (
+ std::move (fields), pattern.get_struct_pattern_elems ().has_rest ());
translated = new HIR::StructPattern (mapping, *path, std::move (elems));
}
@@ -211,19 +242,20 @@ void
ASTLoweringPattern::visit (AST::TuplePattern &pattern)
{
std::unique_ptr<HIR::TuplePatternItems> items;
- switch (pattern.get_items ().get_pattern_type ())
+ switch (pattern.get_items ().get_item_type ())
{
- case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
- AST::TuplePatternItemsMultiple &ref
- = static_cast<AST::TuplePatternItemsMultiple &> (
- pattern.get_items ());
+ case AST::TuplePatternItems::ItemType::NO_REST:
+ {
+ AST::TuplePatternItemsNoRest &ref
+ = static_cast<AST::TuplePatternItemsNoRest &> (pattern.get_items ());
items = lower_tuple_pattern_multiple (ref);
}
break;
- case AST::TuplePatternItems::TuplePatternItemType::RANGED: {
- AST::TuplePatternItemsRanged &ref
- = static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ());
+ case AST::TuplePatternItems::ItemType::HAS_REST:
+ {
+ AST::TuplePatternItemsHasRest &ref
+ = static_cast<AST::TuplePatternItemsHasRest &> (pattern.get_items ());
items = lower_tuple_pattern_ranged (ref);
}
break;
@@ -248,14 +280,13 @@ ASTLoweringPattern::visit (AST::LiteralPattern &pattern)
HIR::Literal l = lower_literal (pattern.get_literal ());
translated
- = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus ());
+ = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus (),
+ pattern.get_has_minus ());
}
void
ASTLoweringPattern::visit (AST::RangePattern &pattern)
{
- if (pattern.get_range_kind () == AST::RangeKind::EXCLUDED)
- rust_unreachable (); // Not supported yet
auto upper_bound = lower_range_pattern_bound (pattern.get_upper_bound ());
auto lower_bound = lower_range_pattern_bound (pattern.get_lower_bound ());
@@ -264,9 +295,11 @@ ASTLoweringPattern::visit (AST::RangePattern &pattern)
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- translated
- = new HIR::RangePattern (mapping, std::move (lower_bound),
- std::move (upper_bound), pattern.get_locus ());
+ bool is_inclusive = (pattern.get_range_kind () == AST::RangeKind::INCLUDED);
+
+ translated = new HIR::RangePattern (mapping, std::move (lower_bound),
+ std::move (upper_bound),
+ pattern.get_locus (), is_inclusive);
}
void
@@ -308,11 +341,24 @@ ASTLoweringPattern::visit (AST::ReferencePattern &pattern)
void
ASTLoweringPattern::visit (AST::SlicePattern &pattern)
{
- std::vector<std::unique_ptr<HIR::Pattern>> items;
- for (auto &p : pattern.get_items ())
+ std::unique_ptr<HIR::SlicePatternItems> items;
+
+ switch (pattern.get_items ().get_item_type ())
{
- HIR::Pattern *item = ASTLoweringPattern::translate (*p);
- items.push_back (std::unique_ptr<HIR::Pattern> (item));
+ case AST::SlicePatternItems::ItemType::NO_REST:
+ {
+ auto &ref
+ = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ());
+ items = ASTLoweringBase::lower_slice_pattern_no_rest (ref);
+ }
+ break;
+ case AST::SlicePatternItems::ItemType::HAS_REST:
+ {
+ auto &ref
+ = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ());
+ items = ASTLoweringBase::lower_slice_pattern_has_rest (ref);
+ }
+ break;
}
auto crate_num = mappings.get_current_crate ();
@@ -333,12 +379,10 @@ ASTLoweringPattern::visit (AST::AltPattern &pattern)
UNKNOWN_LOCAL_DEFID);
std::vector<std::unique_ptr<HIR::Pattern>> alts;
+ alts.reserve (pattern.get_alts ().size ());
for (auto &alt : pattern.get_alts ())
- {
- alts.push_back (
- std::unique_ptr<HIR::Pattern> (ASTLoweringPattern::translate (*alt)));
- }
+ alts.emplace_back (ASTLoweringPattern::translate (*alt));
translated
= new HIR::AltPattern (mapping, std::move (alts), pattern.get_locus ());
diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc
index d3e528d..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)
{
@@ -557,7 +584,7 @@ ASTLowerGenericParam::visit (AST::ConstGenericParam &param)
HIR::Expr *default_expr = nullptr;
if (param.has_default_value ())
default_expr = ASTLoweringExpr::translate (
- param.get_default_value ().get_expression ());
+ param.get_default_value_unchecked ().get_expression ());
translated = new HIR::ConstGenericParam (param.get_name ().as_string (),
std::unique_ptr<Type> (type),
@@ -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 ebdf981..5b8e7c5 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -80,7 +80,7 @@ ASTLowering::go ()
{
auto translated = ASTLoweringItem::translate (*item);
if (translated != nullptr)
- items.push_back (std::unique_ptr<HIR::Item> (translated));
+ items.emplace_back (translated);
}
auto &mappings = Analysis::Mappings::get ();
@@ -97,7 +97,11 @@ ASTLowering::go ()
void
ASTLoweringBlock::visit (AST::BlockExpr &expr)
{
- auto label = lower_loop_label (expr.get_label ());
+ tl::optional<HIR::LoopLabel> label;
+ if (expr.has_label ())
+ label = lower_loop_label (expr.get_label ());
+ else
+ label = tl::nullopt;
std::vector<std::unique_ptr<HIR::Stmt>> block_stmts;
bool block_did_terminate = false;
@@ -123,7 +127,7 @@ ASTLoweringBlock::visit (AST::BlockExpr &expr)
block_did_terminate |= terminated;
if (translated_stmt)
- block_stmts.push_back (std::unique_ptr<HIR::Stmt> (translated_stmt));
+ block_stmts.emplace_back (translated_stmt);
}
if (expr.has_tail_expr () && block_did_terminate)
@@ -227,6 +231,7 @@ ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr,
{
HIR::Expr *kase_expr;
std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns;
+ match_arm_patterns.reserve (expr.get_patterns ().size ());
*branch_value = ASTLoweringExpr::translate (expr.get_value_expr ());
kase_expr = ASTLoweringExpr::translate (expr.get_if_block ());
@@ -237,10 +242,7 @@ ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr,
rust_assert (expr.get_patterns ().size () == 1);
for (auto &pattern : expr.get_patterns ())
- {
- HIR::Pattern *ptrn = ASTLoweringPattern::translate (*pattern);
- match_arm_patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn));
- }
+ match_arm_patterns.emplace_back (ASTLoweringPattern::translate (*pattern));
// The match arm corresponding to the if let pattern when it matches.
HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (), nullptr,
@@ -251,9 +253,8 @@ ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr,
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- HIR::MatchCase kase (std::move (mapping), std::move (arm),
- std::unique_ptr<HIR::Expr> (kase_expr));
- match_arms.push_back (std::move (kase));
+ match_arms.emplace_back (std::move (mapping), std::move (arm),
+ std::unique_ptr<HIR::Expr> (kase_expr));
// The default match arm when the if let pattern does not match
std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns_wildcard;
@@ -261,19 +262,14 @@ ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr,
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- std::unique_ptr<HIR::WildcardPattern> wc
- = std::unique_ptr<HIR::WildcardPattern> (
- new HIR::WildcardPattern (mapping_default, expr.get_locus ()));
-
- match_arm_patterns_wildcard.push_back (std::move (wc));
+ match_arm_patterns_wildcard.emplace_back (
+ new HIR::WildcardPattern (mapping_default, expr.get_locus ()));
HIR::MatchArm arm_default (std::move (match_arm_patterns_wildcard),
expr.get_locus (), nullptr, {});
- HIR::MatchCase kase_else (std::move (mapping_default),
- std::move (arm_default),
- std::unique_ptr<HIR::Expr> (kase_else_expr));
- match_arms.push_back (std::move (kase_else));
+ match_arms.emplace_back (std::move (mapping_default), std::move (arm_default),
+ std::unique_ptr<HIR::Expr> (kase_else_expr));
}
void
@@ -398,7 +394,10 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr)
HIR::BlockExpr *loop_block
= ASTLoweringBlock::translate (expr.get_loop_block (), &terminated);
- HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ());
+ tl::optional<HIR::LoopLabel> loop_label;
+ if (expr.has_loop_label ())
+ loop_label = lower_loop_label (expr.get_loop_label ());
+
HIR::Expr *loop_condition
= ASTLoweringExpr::translate (expr.get_predicate_expr (), &terminated);
@@ -416,12 +415,6 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr)
}
void
-ASTLoweringExprWithBlock::visit (AST::ForLoopExpr &expr)
-{
- rust_unreachable ();
-}
-
-void
ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr)
{
HIR::Expr *branch_value
@@ -441,11 +434,12 @@ ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr)
}
std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns;
+ match_arm_patterns.reserve (
+ match_case.get_arm ().get_patterns ().size ());
+
for (auto &pattern : match_case.get_arm ().get_patterns ())
- {
- HIR::Pattern *ptrn = ASTLoweringPattern::translate (*pattern);
- match_arm_patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn));
- }
+ match_arm_patterns.emplace_back (
+ ASTLoweringPattern::translate (*pattern));
HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (),
std::unique_ptr<HIR::Expr> (kase_guard_expr),
@@ -456,9 +450,8 @@ ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr)
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- HIR::MatchCase kase (std::move (mapping), std::move (arm),
- std::unique_ptr<HIR::Expr> (kase_expr));
- match_arms.push_back (std::move (kase));
+ match_arms.emplace_back (std::move (mapping), std::move (arm),
+ std::unique_ptr<HIR::Expr> (kase_expr));
}
auto crate_num = mappings.get_current_crate ();
@@ -489,8 +482,11 @@ ASTLowerPathInExpression::visit (AST::PathInExpression &expr)
return;
}
- std::vector<HIR::PathExprSegment> path_segments;
auto &segments = expr.get_segments ();
+
+ std::vector<HIR::PathExprSegment> path_segments;
+ path_segments.reserve (segments.size ());
+
for (auto &s : segments)
{
path_segments.push_back (lower_path_expr_seg ((s)));
@@ -530,8 +526,11 @@ ASTLowerQualPathInExpression::visit (AST::QualifiedPathInExpression &expr)
HIR::QualifiedPathType qual_path_type
= lower_qual_path_type (expr.get_qualified_path_type ());
- std::vector<HIR::PathExprSegment> path_segments;
auto &segments = expr.get_segments ();
+
+ std::vector<HIR::PathExprSegment> path_segments;
+ path_segments.reserve (segments.size ());
+
for (auto &s : segments)
{
path_segments.push_back (lower_path_expr_seg ((s)));
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 89fcc3d..49ce143 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.
@@ -546,7 +546,8 @@ Dump::do_traitfunctiondecl (TraitFunctionDecl &e)
else
put_field ("where_clause", "none");
- put_field ("self", e.get_self ().as_string ());
+ if (e.is_method ())
+ put_field ("self", e.get_self_unchecked ().as_string ());
end ("TraitFunctionDecl");
}
@@ -1283,7 +1284,9 @@ Dump::visit (BlockExpr &e)
do_expr (e);
do_inner_attrs (e);
put_field ("tail_reachable", std::to_string (e.is_tail_reachable ()));
- put_field ("label", e.get_label ().as_string ());
+
+ if (e.has_label ())
+ put_field ("label", e.get_label ().as_string ());
visit_collection ("statements", e.get_statements ());
@@ -1294,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");
@@ -1504,9 +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");
@@ -1595,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;
@@ -1623,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;
@@ -1693,7 +1805,8 @@ Dump::visit (Function &e)
put_field ("where clause", e.get_where_clause ().as_string ());
visit_field ("function_body", e.get_definition ());
- put_field ("self", e.get_self_param ().as_string ());
+ if (e.is_method ())
+ put_field ("self", e.get_self_param_unchecked ().as_string ());
end ("Function");
}
@@ -1894,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");
}
@@ -2083,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");
}
@@ -2164,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");
}
@@ -2193,20 +2307,20 @@ Dump::visit (StructPattern &e)
}
void
-Dump::visit (TupleStructItemsNoRange &e)
+Dump::visit (TupleStructItemsNoRest &e)
{
- begin ("TupleStructItemsNoRange");
+ begin ("TupleStructItemsNoRest");
visit_collection ("patterns", e.get_patterns ());
- end ("TupleStructItemsNoRange");
+ end ("TupleStructItemsNoRest");
}
void
-Dump::visit (TupleStructItemsRange &e)
+Dump::visit (TupleStructItemsHasRest &e)
{
- begin ("TupleStructItemsRange");
+ begin ("TupleStructItemsHasRest");
visit_collection ("lower_patterns", e.get_lower_patterns ());
visit_collection ("upper_patterns", e.get_upper_patterns ());
- end ("TupleStructItemsRange");
+ end ("TupleStructItemsHasRest");
}
void
@@ -2223,20 +2337,20 @@ Dump::visit (TupleStructPattern &e)
}
void
-Dump::visit (TuplePatternItemsMultiple &e)
+Dump::visit (TuplePatternItemsNoRest &e)
{
- begin ("TuplePatternItemsMultiple");
+ begin ("TuplePatternItemsNoRest");
visit_collection ("patterns", e.get_patterns ());
- end ("TuplePatternItemsMultiple");
+ end ("TuplePatternItemsNoRest");
}
void
-Dump::visit (TuplePatternItemsRanged &e)
+Dump::visit (TuplePatternItemsHasRest &e)
{
- begin ("TuplePatternItemsRanged");
+ begin ("TuplePatternItemsHasRest");
visit_collection ("lower_patterns", e.get_lower_patterns ());
visit_collection ("upper_patterns", e.get_upper_patterns ());
- end ("TuplePatternItemsRanged");
+ end ("TuplePatternItemsHasRest");
}
void
@@ -2249,11 +2363,28 @@ Dump::visit (TuplePattern &e)
}
void
+Dump::visit (SlicePatternItemsNoRest &e)
+{
+ begin ("SlicePatternItemsNoRest");
+ visit_collection ("patterns", e.get_patterns ());
+ end ("SlicePatternItemsNoRest");
+}
+
+void
+Dump::visit (SlicePatternItemsHasRest &e)
+{
+ begin ("SlicePatternItemsHasRest");
+ visit_collection ("lower_patterns", e.get_lower_patterns ());
+ visit_collection ("upper_patterns", e.get_upper_patterns ());
+ end ("SlicePatternItemsHasRest");
+}
+
+void
Dump::visit (SlicePattern &e)
{
begin ("SlicePattern");
do_mappings (e.get_mappings ());
- visit_collection ("items", e.get_items ());
+ visit_field ("items", e.get_items ());
end ("SlicePattern");
}
@@ -2282,7 +2413,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 afcd668..4dfc885 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;
@@ -166,6 +168,8 @@ private:
virtual void visit (AwaitExpr &) override;
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;
@@ -219,14 +223,18 @@ private:
virtual void visit (StructPatternFieldIdent &) override;
virtual void visit (StructPattern &) override;
- virtual void visit (TupleStructItemsNoRange &) override;
- virtual void visit (TupleStructItemsRange &) override;
+ virtual void visit (TupleStructItemsNoRest &) override;
+ virtual void visit (TupleStructItemsHasRest &) override;
virtual void visit (TupleStructPattern &) override;
- virtual void visit (TuplePatternItemsMultiple &) override;
- virtual void visit (TuplePatternItemsRanged &) override;
+ virtual void visit (TuplePatternItemsNoRest &) override;
+ virtual void visit (TuplePatternItemsHasRest &) override;
virtual void visit (TuplePattern &) override;
+
+ virtual void visit (SlicePatternItemsNoRest &) override;
+ virtual void visit (SlicePatternItemsHasRest &) override;
virtual void visit (SlicePattern &) override;
+
virtual void visit (AltPattern &) override;
virtual void visit (EmptyStmt &) override;
@@ -251,7 +259,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-bound.h b/gcc/rust/hir/tree/rust-hir-bound.h
index 78bb133..8fa6a22 100644
--- a/gcc/rust/hir/tree/rust-hir-bound.h
+++ b/gcc/rust/hir/tree/rust-hir-bound.h
@@ -44,18 +44,6 @@ public:
{}
// Returns true if the lifetime is in an error state.
- bool is_error () const
- {
- return lifetime_type == AST::Lifetime::LifetimeType::NAMED
- && lifetime_name.empty ();
- }
-
- static Lifetime error ()
- {
- return Lifetime (Analysis::NodeMapping::get_error (),
- AST::Lifetime::LifetimeType::NAMED, "", UNDEF_LOCATION);
- }
-
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
diff --git a/gcc/rust/hir/tree/rust-hir-expr-abstract.h b/gcc/rust/hir/tree/rust-hir-expr-abstract.h
index ecf9bd1..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,
@@ -71,6 +73,8 @@ public:
AsyncBlock,
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 2ded789..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"
@@ -81,10 +83,10 @@ OperatorExpr::operator= (OperatorExpr const &other)
BorrowExpr::BorrowExpr (Analysis::NodeMapping mappings,
std::unique_ptr<Expr> borrow_lvalue, Mutability mut,
- AST::AttrVec outer_attribs, location_t locus)
+ bool raw, AST::AttrVec outer_attribs, location_t locus)
: OperatorExpr (std::move (mappings), std::move (borrow_lvalue),
std::move (outer_attribs), locus),
- mut (mut)
+ mut (mut), raw (raw)
{}
DereferenceExpr::DereferenceExpr (Analysis::NodeMapping mappings,
@@ -749,7 +751,7 @@ BlockExpr::BlockExpr (Analysis::NodeMapping mappings,
std::vector<std::unique_ptr<Stmt>> block_statements,
std::unique_ptr<Expr> block_expr, bool tail_reachable,
AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
- LoopLabel label, location_t start_locus,
+ tl::optional<LoopLabel> label, location_t start_locus,
location_t end_locus)
: ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
WithInnerAttrs (std::move (inner_attribs)),
@@ -790,14 +792,71 @@ 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,
- Lifetime label, AST::AttrVec outer_attribs)
+ tl::optional<Lifetime> label,
+ AST::AttrVec outer_attribs)
: ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
label (std::move (label)), locus (locus)
{}
BreakExpr::BreakExpr (Analysis::NodeMapping mappings, location_t locus,
- Lifetime break_label, std::unique_ptr<Expr> expr_in_break,
+ tl::optional<Lifetime> break_label,
+ std::unique_ptr<Expr> expr_in_break,
AST::AttrVec outer_attribs)
: ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
label (std::move (break_label)), break_expr (std::move (expr_in_break)),
@@ -985,7 +1044,8 @@ UnsafeBlockExpr::operator= (UnsafeBlockExpr const &other)
BaseLoopExpr::BaseLoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr<BlockExpr> loop_block,
- location_t locus, LoopLabel loop_label,
+ location_t locus,
+ tl::optional<LoopLabel> loop_label,
AST::AttrVec outer_attribs)
: ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
loop_label (std::move (loop_label)), loop_block (std::move (loop_block)),
@@ -1011,7 +1071,8 @@ BaseLoopExpr::operator= (BaseLoopExpr const &other)
LoopExpr::LoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label, AST::AttrVec outer_attribs)
+ tl::optional<LoopLabel> loop_label,
+ AST::AttrVec outer_attribs)
: BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
std::move (loop_label), std::move (outer_attribs))
{}
@@ -1019,7 +1080,8 @@ LoopExpr::LoopExpr (Analysis::NodeMapping mappings,
WhileLoopExpr::WhileLoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr<Expr> loop_condition,
std::unique_ptr<BlockExpr> loop_block,
- location_t locus, LoopLabel loop_label,
+ location_t locus,
+ tl::optional<LoopLabel> loop_label,
AST::AttrVec outer_attribs)
: BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
std::move (loop_label), std::move (outer_attribs)),
@@ -1046,7 +1108,8 @@ WhileLetLoopExpr::WhileLetLoopExpr (
Analysis::NodeMapping mappings,
std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
std::unique_ptr<Expr> condition, std::unique_ptr<BlockExpr> loop_block,
- location_t locus, LoopLabel loop_label, AST::AttrVec outer_attribs)
+ location_t locus, tl::optional<LoopLabel> loop_label,
+ AST::AttrVec outer_attribs)
: BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
std::move (loop_label), std::move (outer_attribs)),
match_arm_patterns (std::move (match_arm_patterns)),
@@ -1271,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)
@@ -1470,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)),
@@ -1480,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 f8f2128..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 {
@@ -45,9 +48,6 @@ public:
LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label,
location_t locus);
- // Returns whether the LoopLabel is in an error state.
- bool is_error () const { return label.is_error (); }
-
location_t get_locus () const { return locus; }
Analysis::NodeMapping &get_mappings () { return mappings; }
@@ -199,12 +199,13 @@ public:
class BorrowExpr : public OperatorExpr
{
Mutability mut;
+ bool raw;
public:
std::string as_string () const override;
BorrowExpr (Analysis::NodeMapping mappings,
- std::unique_ptr<Expr> borrow_lvalue, Mutability mut,
+ std::unique_ptr<Expr> borrow_lvalue, Mutability mut, bool raw,
AST::AttrVec outer_attribs, location_t locus);
void accept_vis (HIRFullVisitor &vis) override;
@@ -212,6 +213,7 @@ public:
Mutability get_mut () const { return mut; }
bool is_mut () const { return mut == Mutability::Mut; }
+ bool is_raw_borrow () const { return raw; }
protected:
/* Use covariance to implement clone function as returning this object rather
@@ -1715,7 +1717,7 @@ public:
std::vector<std::unique_ptr<Stmt>> statements;
std::unique_ptr<Expr> expr;
bool tail_reachable;
- LoopLabel label;
+ tl::optional<LoopLabel> label;
location_t start_locus;
location_t end_locus;
@@ -1735,7 +1737,8 @@ public:
std::vector<std::unique_ptr<Stmt>> block_statements,
std::unique_ptr<Expr> block_expr, bool tail_reachable,
AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
- LoopLabel label, location_t start_locus, location_t end_locus);
+ tl::optional<LoopLabel> label, location_t start_locus,
+ location_t end_locus);
// Copy constructor with clone
BlockExpr (BlockExpr const &other);
@@ -1774,8 +1777,8 @@ public:
return ExprType::Block;
}
- bool has_label () const { return !label.is_error (); }
- LoopLabel &get_label () { return label; }
+ bool has_label () const { return label.has_value (); }
+ LoopLabel &get_label () { return label.value (); }
protected:
/* Use covariance to implement clone function as returning this object rather
@@ -1800,28 +1803,116 @@ 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
{
- Lifetime label;
+ tl::optional<Lifetime> label;
location_t locus;
public:
std::string as_string () const override;
// Returns true if the continue expr has a label.
- bool has_label () const { return !label.is_error (); }
+ bool has_label () const { return label.has_value (); }
// Constructor for a ContinueExpr with a label.
ContinueExpr (Analysis::NodeMapping mappings, location_t locus,
- Lifetime label, AST::AttrVec outer_attribs = AST::AttrVec ());
+ tl::optional<Lifetime> label,
+ AST::AttrVec outer_attribs = AST::AttrVec ());
location_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
- Lifetime &get_label () { return label; }
+ Lifetime &get_label () { return label.value (); }
+ const Lifetime &get_label () const { return label.value (); }
ExprType get_expression_type () const final override
{
@@ -1848,7 +1939,7 @@ protected:
class BreakExpr : public ExprWithoutBlock
{
// bool has_label;
- Lifetime label;
+ tl::optional<Lifetime> label;
// bool has_break_expr;
std::unique_ptr<Expr> break_expr;
@@ -1859,7 +1950,7 @@ public:
std::string as_string () const override;
// Returns whether the break expression has a label or not.
- bool has_label () const { return !label.is_error (); }
+ bool has_label () const { return label.has_value (); }
/* Returns whether the break expression has an expression used in the break or
* not. */
@@ -1867,7 +1958,7 @@ public:
// Constructor for a break expression
BreakExpr (Analysis::NodeMapping mappings, location_t locus,
- Lifetime break_label,
+ tl::optional<Lifetime> break_label,
std::unique_ptr<Expr> expr_in_break = nullptr,
AST::AttrVec outer_attribs = AST::AttrVec ());
@@ -1886,7 +1977,8 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
- Lifetime &get_label () { return label; }
+ Lifetime &get_label () { return label.value (); }
+ const Lifetime &get_label () const { return label.value (); }
Expr &get_expr () { return *break_expr; }
@@ -2293,7 +2385,7 @@ protected:
class BaseLoopExpr : public ExprWithBlock
{
protected:
- LoopLabel loop_label;
+ tl::optional<LoopLabel> loop_label;
std::unique_ptr<BlockExpr> loop_block;
private:
@@ -2303,7 +2395,7 @@ protected:
// Constructor for BaseLoopExpr
BaseLoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label,
+ tl::optional<LoopLabel> loop_label,
AST::AttrVec outer_attribs = AST::AttrVec ());
// Copy constructor for BaseLoopExpr with clone
@@ -2322,13 +2414,14 @@ protected:
}
public:
- bool has_loop_label () const { return !loop_label.is_error (); }
+ bool has_loop_label () const { return loop_label.has_value (); }
location_t get_locus () const override final { return locus; }
HIR::BlockExpr &get_loop_block () { return *loop_block; };
- LoopLabel &get_loop_label () { return loop_label; }
+ LoopLabel &get_loop_label () { return loop_label.value (); }
+ const LoopLabel &get_loop_label () const { return loop_label.value (); }
};
// 'Loop' expression (i.e. the infinite loop) HIR node
@@ -2340,7 +2433,8 @@ public:
// Constructor for LoopExpr
LoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label, AST::AttrVec outer_attribs = AST::AttrVec ());
+ tl::optional<LoopLabel> loop_label,
+ AST::AttrVec outer_attribs = AST::AttrVec ());
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
@@ -2370,7 +2464,7 @@ public:
WhileLoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr<Expr> loop_condition,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label,
+ tl::optional<LoopLabel> loop_label,
AST::AttrVec outer_attribs = AST::AttrVec ());
// Copy constructor with clone
@@ -2419,7 +2513,7 @@ public:
std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
std::unique_ptr<Expr> condition,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label,
+ tl::optional<LoopLabel> loop_label,
AST::AttrVec outer_attribs = AST::AttrVec ());
// Copy constructor with clone
@@ -2626,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
@@ -2818,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
@@ -2825,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;
};
@@ -2887,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:
@@ -2987,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;
@@ -3032,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
@@ -3054,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;
@@ -3085,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 ()
{
@@ -3108,11 +3231,121 @@ 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;
+ std::unique_ptr<Expr> expr;
+
+ LlvmOperand (std::string constraint, std::unique_ptr<Expr> &&expr)
+ : constraint (constraint), expr (std::move (expr))
+ {}
+
+ LlvmOperand (const LlvmOperand &other)
+ : constraint (other.constraint), expr (other.expr->clone_expr ())
+ {}
+ LlvmOperand &operator= (const LlvmOperand &other)
+ {
+ constraint = other.constraint;
+ expr = other.expr->clone_expr ();
+
+ return *this;
+ }
+};
+
+class LlvmInlineAsm : public ExprWithoutBlock
+{
+public:
+ struct Options
+ {
+ bool is_volatile;
+ bool align_stack;
+ AST::LlvmInlineAsm::Dialect dialect;
+ };
+
+ location_t locus;
+ AST::AttrVec outer_attrs;
+ std::vector<LlvmOperand> inputs;
+ std::vector<LlvmOperand> outputs;
+ std::vector<AST::TupleTemplateStr> templates;
+ std::vector<AST::TupleClobber> clobbers;
+ Options options;
+
+ LlvmInlineAsm (location_t locus, std::vector<LlvmOperand> inputs,
+ std::vector<LlvmOperand> outputs,
+ std::vector<AST::TupleTemplateStr> templates,
+ std::vector<AST::TupleClobber> clobbers, Options options,
+ AST::AttrVec outer_attrs, Analysis::NodeMapping mappings)
+ : ExprWithoutBlock (mappings, std::move (outer_attrs)), locus (locus),
+ inputs (std::move (inputs)), outputs (std::move (outputs)),
+ templates (std::move (templates)), clobbers (std::move (clobbers)),
+ options (options)
+ {}
+
+ AST::LlvmInlineAsm::Dialect get_dialect () { return options.dialect; }
+
+ location_t get_locus () const override { return locus; }
+
+ std::vector<AST::Attribute> &get_outer_attrs () { return outer_attrs; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ LlvmInlineAsm *clone_expr_without_block_impl () const override
+ {
+ return new LlvmInlineAsm (*this);
+ }
+
+ std::vector<AST::TupleTemplateStr> &get_templates () { return templates; }
+
+ Expr::ExprType get_expression_type () const override
+ {
+ return Expr::ExprType::LlvmInlineAsm;
+ }
+
+ std::vector<AST::TupleClobber> get_clobbers () { return clobbers; }
+};
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h
index 6c19f24..aec2f36 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,9 +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;
@@ -196,13 +199,15 @@ class StructPatternFieldIdentPat;
class StructPatternFieldIdent;
class StructPattern;
class TupleStructItems;
-class TupleStructItemsNoRange;
-class TupleStructItemsRange;
+class TupleStructItemsNoRest;
+class TupleStructItemsHasRest;
class TupleStructPattern;
class TuplePatternItems;
-class TuplePatternItemsMultiple;
-class TuplePatternItemsRanged;
+class TuplePatternItemsNoRest;
+class TuplePatternItemsHasRest;
class TuplePattern;
+class SlicePatternItemsNoRest;
+class SlicePatternItemsHasRest;
class SlicePattern;
class AltPattern;
diff --git a/gcc/rust/hir/tree/rust-hir-generic-param.h b/gcc/rust/hir/tree/rust-hir-generic-param.h
index a1c59bf..340b5c6 100644
--- a/gcc/rust/hir/tree/rust-hir-generic-param.h
+++ b/gcc/rust/hir/tree/rust-hir-generic-param.h
@@ -97,9 +97,6 @@ public:
AST::AttrVec &get_outer_attrs () override { return outer_attrs; }
- // Returns whether the lifetime param is in an error state.
- bool is_error () const { return lifetime.is_error (); }
-
// Constructor
LifetimeParam (Analysis::NodeMapping mappings, Lifetime lifetime,
location_t locus = UNDEF_LOCATION,
@@ -153,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 ()
@@ -163,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 cff06d3..268b09b 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 ())
@@ -123,7 +126,8 @@ TypeBoundWhereClauseItem::get_type_param_bounds ()
}
SelfParam::SelfParam (Analysis::NodeMapping mappings,
- ImplicitSelfKind self_kind, Lifetime lifetime, Type *type)
+ ImplicitSelfKind self_kind,
+ tl::optional<Lifetime> lifetime, Type *type)
: self_kind (self_kind), lifetime (std::move (lifetime)), type (type),
mappings (mappings)
{}
@@ -131,13 +135,13 @@ SelfParam::SelfParam (Analysis::NodeMapping mappings,
SelfParam::SelfParam (Analysis::NodeMapping mappings,
std::unique_ptr<Type> type, bool is_mut, location_t locus)
: self_kind (is_mut ? ImplicitSelfKind::MUT : ImplicitSelfKind::IMM),
- lifetime (
- Lifetime (mappings, AST::Lifetime::LifetimeType::NAMED, "", locus)),
- type (std::move (type)), locus (locus), mappings (mappings)
+ lifetime (tl::nullopt), type (std::move (type)), locus (locus),
+ mappings (mappings)
{}
-SelfParam::SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime,
- bool is_mut, location_t locus)
+SelfParam::SelfParam (Analysis::NodeMapping mappings,
+ tl::optional<Lifetime> lifetime, bool is_mut,
+ location_t locus)
: self_kind (is_mut ? ImplicitSelfKind::MUT_REF : ImplicitSelfKind::IMM_REF),
lifetime (std::move (lifetime)), locus (locus), mappings (mappings)
{}
@@ -263,7 +267,8 @@ Function::Function (Analysis::NodeMapping mappings, Identifier function_name,
std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type, WhereClause where_clause,
std::unique_ptr<BlockExpr> function_body, Visibility vis,
- AST::AttrVec outer_attrs, SelfParam self, location_t locus)
+ AST::AttrVec outer_attrs, tl::optional<SelfParam> self,
+ Defaultness defaultness, location_t locus)
: VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
qualifiers (std::move (qualifiers)),
function_name (std::move (function_name)),
@@ -272,7 +277,7 @@ Function::Function (Analysis::NodeMapping mappings, Identifier function_name,
return_type (std::move (return_type)),
where_clause (std::move (where_clause)),
function_body (std::move (function_body)), self (std::move (self)),
- locus (locus)
+ locus (locus), defaultness (defaultness)
{}
Function::Function (Function const &other)
@@ -280,7 +285,7 @@ Function::Function (Function const &other)
function_name (other.function_name),
function_params (other.function_params), where_clause (other.where_clause),
function_body (other.function_body->clone_block_expr ()), self (other.self),
- locus (other.locus)
+ locus (other.locus), defaultness (other.defaultness)
{
// guard to prevent null dereference (always required)
if (other.return_type != nullptr)
@@ -312,6 +317,8 @@ Function::operator= (Function const &other)
locus = other.locus;
self = other.self;
+ defaultness = other.defaultness;
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -609,9 +616,9 @@ StaticItem::operator= (StaticItem const &other)
TraitFunctionDecl::TraitFunctionDecl (
Identifier function_name, FunctionQualifiers qualifiers,
- std::vector<std::unique_ptr<GenericParam>> generic_params, SelfParam self,
- std::vector<FunctionParam> function_params, std::unique_ptr<Type> return_type,
- WhereClause where_clause)
+ std::vector<std::unique_ptr<GenericParam>> generic_params,
+ tl::optional<SelfParam> self, std::vector<FunctionParam> function_params,
+ std::unique_ptr<Type> return_type, WhereClause where_clause)
: qualifiers (std::move (qualifiers)),
function_name (std::move (function_name)),
generic_params (std::move (generic_params)),
@@ -709,17 +716,21 @@ TraitItemConst::operator= (TraitItemConst const &other)
TraitItemType::TraitItemType (
Analysis::NodeMapping mappings, Identifier name,
+ std::vector<std::unique_ptr<GenericParam>> generic_params,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
AST::AttrVec outer_attrs, location_t locus)
: TraitItem (mappings), outer_attrs (std::move (outer_attrs)),
- name (std::move (name)), type_param_bounds (std::move (type_param_bounds)),
- locus (locus)
+ name (std::move (name)), generic_params (std::move (generic_params)),
+ type_param_bounds (std::move (type_param_bounds)), locus (locus)
{}
TraitItemType::TraitItemType (TraitItemType const &other)
: TraitItem (other.mappings), outer_attrs (other.outer_attrs),
name (other.name), locus (other.locus)
{
+ generic_params.reserve (other.generic_params.size ());
+ for (const auto &e : other.generic_params)
+ generic_params.push_back (e->clone_generic_param ());
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
type_param_bounds.push_back (e->clone_type_param_bound ());
@@ -734,6 +745,9 @@ TraitItemType::operator= (TraitItemType const &other)
locus = other.locus;
mappings = other.mappings;
+ generic_params.reserve (other.generic_params.size ());
+ for (const auto &e : other.generic_params)
+ generic_params.push_back (e->clone_generic_param ());
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
type_param_bounds.push_back (e->clone_type_param_bound ());
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 4744717..7629406 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; }
@@ -371,13 +369,13 @@ public:
private:
ImplicitSelfKind self_kind;
- Lifetime lifetime;
+ tl::optional<Lifetime> lifetime;
std::unique_ptr<Type> type;
location_t locus;
Analysis::NodeMapping mappings;
SelfParam (Analysis::NodeMapping mappings, ImplicitSelfKind self_kind,
- Lifetime lifetime, Type *type);
+ tl::optional<Lifetime> lifetime, Type *type);
public:
// Type-based self parameter (not ref, no lifetime)
@@ -385,8 +383,8 @@ public:
bool is_mut, location_t locus);
// Lifetime-based self parameter (is ref, no type)
- SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime, bool is_mut,
- location_t locus);
+ SelfParam (Analysis::NodeMapping mappings, tl::optional<Lifetime> lifetime,
+ bool is_mut, location_t locus);
// Copy constructor requires clone
SelfParam (SelfParam const &other);
@@ -398,22 +396,15 @@ public:
SelfParam (SelfParam &&other) = default;
SelfParam &operator= (SelfParam &&other) = default;
- static SelfParam error ()
- {
- return SelfParam (Analysis::NodeMapping::get_error (),
- ImplicitSelfKind::NONE, Lifetime::error (), nullptr);
- }
-
// Returns whether the self-param has a type field.
bool has_type () const { return type != nullptr; }
// Returns whether the self-param has a valid lifetime.
- bool has_lifetime () const { return !lifetime.is_error (); }
+ bool has_lifetime () const { return lifetime.has_value (); }
- const Lifetime &get_lifetime () const { return lifetime; }
+ const Lifetime &get_lifetime () const { return lifetime.value (); }
- // Returns whether the self-param is in an error state.
- bool is_error () const { return self_kind == ImplicitSelfKind::NONE; }
+ Lifetime &get_lifetime () { return lifetime.value (); }
std::string as_string () const;
@@ -461,6 +452,7 @@ public:
bool is_unsafe () const { return unsafety == Unsafety::Unsafe; }
bool is_async () const { return async_status == Async::Yes; }
+ Unsafety get_unsafety () const { return unsafety; }
ABI get_abi () const { return abi; }
};
@@ -945,6 +937,12 @@ protected:
class LetStmt;
+enum class Defaultness
+{
+ Default,
+ Final,
+};
+
// Rust function declaration HIR node
class Function : public VisItem, public ImplItem
{
@@ -955,9 +953,14 @@ class Function : public VisItem, public ImplItem
std::unique_ptr<Type> return_type;
WhereClause where_clause;
std::unique_ptr<BlockExpr> function_body;
- SelfParam self;
+ tl::optional<SelfParam> self;
location_t locus;
+ // NOTE: This should be moved to the trait item base class once we start
+ // implementing specialization for real, instead of just stubbing out the
+ // feature
+ Defaultness defaultness;
+
public:
std::string as_string () const override;
@@ -973,6 +976,9 @@ public:
// Returns whether function has a where clause.
bool has_where_clause () const { return !where_clause.is_empty (); }
+ // Returns whether function has a default qualifier
+ bool is_default () const { return defaultness == Defaultness::Default; }
+
ImplItemType get_impl_item_type () const override final
{
return ImplItem::ImplItemType::FUNCTION;
@@ -987,7 +993,8 @@ public:
std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type, WhereClause where_clause,
std::unique_ptr<BlockExpr> function_body, Visibility vis,
- AST::AttrVec outer_attrs, SelfParam self, location_t locus);
+ AST::AttrVec outer_attrs, tl::optional<SelfParam> self,
+ Defaultness defaultness, location_t locus);
// Copy constructor with clone
Function (Function const &other);
@@ -1041,9 +1048,13 @@ public:
// TODO: is this better? Or is a "vis_block" better?
Type &get_return_type () { return *return_type; }
- bool is_method () const { return !self.is_error (); }
+ bool is_method () const { return self.has_value (); }
+
+ tl::optional<SelfParam> &get_self_param () { return self; }
+ const tl::optional<SelfParam> &get_self_param () const { return self; }
- SelfParam &get_self_param () { return self; }
+ SelfParam &get_self_param_unchecked () { return self.value (); }
+ const SelfParam &get_self_param_unchecked () const { return self.value (); }
std::string get_impl_item_name () const override final
{
@@ -1791,6 +1802,8 @@ public:
return *type;
}
+ bool has_expr () const { return const_expr != nullptr; }
+
Expr &get_expr () { return *const_expr; }
Identifier get_identifier () const { return identifier; }
@@ -1898,13 +1911,14 @@ private:
std::vector<FunctionParam> function_params;
std::unique_ptr<Type> return_type;
WhereClause where_clause;
- SelfParam self;
+ tl::optional<SelfParam> self;
public:
// Mega-constructor
TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers,
std::vector<std::unique_ptr<GenericParam>> generic_params,
- SelfParam self, std::vector<FunctionParam> function_params,
+ tl::optional<SelfParam> self,
+ std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type,
WhereClause where_clause);
@@ -1936,9 +1950,13 @@ public:
WhereClause &get_where_clause () { return where_clause; }
- bool is_method () const { return !self.is_error (); }
+ bool is_method () const { return self.has_value (); }
+
+ SelfParam &get_self_unchecked () { return self.value (); }
+ const SelfParam &get_self_unchecked () const { return self.value (); }
- SelfParam &get_self () { return self; }
+ tl::optional<SelfParam> &get_self () { return self; }
+ const tl::optional<SelfParam> &get_self () const { return self; }
Identifier get_function_name () const { return function_name; }
@@ -2055,6 +2073,8 @@ public:
Identifier get_name () const { return name; }
+ bool has_type () const { return expr != nullptr; }
+
bool has_expr () const { return expr != nullptr; }
Type &get_type ()
@@ -2101,15 +2121,20 @@ class TraitItemType : public TraitItem
AST::AttrVec outer_attrs;
Identifier name;
+ // Generic parameters for GATs (Generic Associated Types)
+ std::vector<std::unique_ptr<GenericParam>> generic_params;
std::vector<std::unique_ptr<TypeParamBound>>
type_param_bounds; // inlined form
location_t locus;
public:
+ bool has_generics () const { return !generic_params.empty (); }
+
// Returns whether trait item type has type param bounds.
bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
TraitItemType (Analysis::NodeMapping mappings, Identifier name,
+ std::vector<std::unique_ptr<GenericParam>> generic_params,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
AST::AttrVec outer_attrs, location_t locus);
@@ -2132,6 +2157,15 @@ public:
Identifier get_name () const { return name; }
+ std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
+ {
+ return generic_params;
+ }
+
std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
{
return type_param_bounds;
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..a2c408f 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -32,19 +32,27 @@ class LiteralPattern : public Pattern
Literal lit;
location_t locus;
Analysis::NodeMapping mappings;
+ bool has_minus;
public:
std::string as_string () const override;
// Constructor for a literal pattern
LiteralPattern (Analysis::NodeMapping mappings, Literal lit, location_t locus)
- : lit (std::move (lit)), locus (locus), mappings (mappings)
+ : lit (std::move (lit)), locus (locus), mappings (mappings),
+ has_minus (false)
+ {}
+
+ LiteralPattern (Analysis::NodeMapping mappings, Literal lit, location_t locus,
+ bool has_minus)
+ : lit (std::move (lit)), locus (locus), mappings (mappings),
+ has_minus (has_minus)
{}
LiteralPattern (Analysis::NodeMapping mappings, std::string val,
Literal::LitType type, location_t locus)
: lit (Literal (std::move (val), type, PrimitiveCoreType::CORETYPE_STR)),
- locus (locus), mappings (mappings)
+ locus (locus), mappings (mappings), has_minus (false)
{}
location_t get_locus () const override { return locus; }
@@ -65,6 +73,8 @@ public:
Literal &get_literal () { return lit; }
const Literal &get_literal () const { return lit; }
+ bool get_has_minus () const { return has_minus; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -80,7 +90,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 +98,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 +115,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 +129,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 +143,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;
@@ -350,6 +360,7 @@ class RangePattern : public Pattern
/* location only stored to avoid a dereference - lower pattern should give
* correct location so maybe change in future */
location_t locus;
+ bool is_inclusive;
Analysis::NodeMapping mappings;
public:
@@ -359,10 +370,10 @@ public:
RangePattern (Analysis::NodeMapping mappings,
std::unique_ptr<RangePatternBound> lower,
std::unique_ptr<RangePatternBound> upper, location_t locus,
- bool has_ellipsis_syntax = false)
+ bool is_inclusive, bool has_ellipsis_syntax = false)
: lower (std::move (lower)), upper (std::move (upper)),
has_ellipsis_syntax (has_ellipsis_syntax), locus (locus),
- mappings (mappings)
+ is_inclusive (is_inclusive), mappings (mappings)
{}
// Copy constructor with clone
@@ -370,7 +381,7 @@ public:
: lower (other.lower->clone_range_pattern_bound ()),
upper (other.upper->clone_range_pattern_bound ()),
has_ellipsis_syntax (other.has_ellipsis_syntax), locus (other.locus),
- mappings (other.mappings)
+ is_inclusive (other.is_inclusive), mappings (other.mappings)
{}
// Overloaded assignment operator to clone
@@ -380,6 +391,7 @@ public:
upper = other.upper->clone_range_pattern_bound ();
has_ellipsis_syntax = other.has_ellipsis_syntax;
locus = other.locus;
+ is_inclusive = other.is_inclusive;
mappings = other.mappings;
return *this;
@@ -395,6 +407,7 @@ public:
void accept_vis (HIRPatternVisitor &vis) override;
bool get_has_ellipsis_syntax () { return has_ellipsis_syntax; };
+ bool is_inclusive_range () const { return is_inclusive; }
const Analysis::NodeMapping &get_mappings () const override final
{
@@ -680,6 +693,7 @@ protected:
class StructPatternElements
{
std::vector<std::unique_ptr<StructPatternField>> fields;
+ bool has_rest_pattern;
public:
// Returns whether there are any struct pattern fields
@@ -689,10 +703,18 @@ public:
* no etc). */
bool is_empty () const { return !has_struct_pattern_fields (); }
+ bool has_rest () const { return has_rest_pattern; }
+
// Constructor for StructPatternElements with both (potentially)
StructPatternElements (
std::vector<std::unique_ptr<StructPatternField>> fields)
- : fields (std::move (fields))
+ : fields (std::move (fields)), has_rest_pattern (false)
+ {}
+
+ StructPatternElements (
+ std::vector<std::unique_ptr<StructPatternField>> fields,
+ bool has_rest_pattern)
+ : fields (std::move (fields)), has_rest_pattern (has_rest_pattern)
{}
// Copy constructor with vector clone
@@ -700,7 +722,8 @@ public:
{
fields.reserve (other.fields.size ());
for (const auto &e : other.fields)
- fields.push_back (e->clone_struct_pattern_field ());
+ fields.emplace_back (e->clone_struct_pattern_field ());
+ has_rest_pattern = other.has_rest_pattern;
}
// Overloaded assignment operator with vector clone
@@ -709,8 +732,8 @@ public:
fields.clear ();
fields.reserve (other.fields.size ());
for (const auto &e : other.fields)
- fields.push_back (e->clone_struct_pattern_field ());
-
+ fields.emplace_back (e->clone_struct_pattern_field ());
+ has_rest_pattern = other.has_rest_pattern;
return *this;
}
@@ -778,24 +801,25 @@ protected:
}
};
-// Base abstract class for TupleStructItems and TuplePatternItems
-class TupleItems : public FullVisitable
+// Base abstract class for TupleStructItems, TuplePatternItems &
+// SlicePatternItems
+class PatternItems : public FullVisitable
{
public:
enum ItemType
{
- MULTIPLE,
- RANGED,
+ NO_REST,
+ HAS_REST,
};
- virtual ~TupleItems () {}
+ virtual ~PatternItems () {}
// TODO: should this store location data?
// Unique pointer custom clone function
- std::unique_ptr<TupleItems> clone_tuple_items () const
+ std::unique_ptr<PatternItems> clone_pattern_items () const
{
- return std::unique_ptr<TupleItems> (clone_tuple_items_impl ());
+ return std::unique_ptr<PatternItems> (clone_pattern_items_impl ());
}
virtual ItemType get_item_type () const = 0;
@@ -804,36 +828,36 @@ public:
protected:
// pure virtual clone implementation
- virtual TupleItems *clone_tuple_items_impl () const = 0;
+ virtual PatternItems *clone_pattern_items_impl () const = 0;
};
// Base abstract class for patterns used in TupleStructPattern
-class TupleStructItems : public TupleItems
+class TupleStructItems : public PatternItems
{
public:
// Unique pointer custom clone function
std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const
{
- return std::unique_ptr<TupleStructItems> (clone_tuple_items_impl ());
+ return std::unique_ptr<TupleStructItems> (clone_pattern_items_impl ());
}
protected:
// pure virtual clone implementation
- virtual TupleStructItems *clone_tuple_items_impl () const override = 0;
+ virtual TupleStructItems *clone_pattern_items_impl () const override = 0;
};
-// Class for non-ranged tuple struct pattern patterns
-class TupleStructItemsNoRange : public TupleStructItems
+// Class for patterns within a tuple struct pattern, without a rest pattern
+class TupleStructItemsNoRest : public TupleStructItems
{
std::vector<std::unique_ptr<Pattern>> patterns;
public:
- TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern>> patterns)
+ TupleStructItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
: patterns (std::move (patterns))
{}
// Copy constructor with vector clone
- TupleStructItemsNoRange (TupleStructItemsNoRange const &other)
+ TupleStructItemsNoRest (TupleStructItemsNoRest const &other)
{
patterns.reserve (other.patterns.size ());
for (const auto &e : other.patterns)
@@ -841,7 +865,7 @@ public:
}
// Overloaded assignment operator with vector clone
- TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other)
+ TupleStructItemsNoRest &operator= (TupleStructItemsNoRest const &other)
{
patterns.clear ();
patterns.reserve (other.patterns.size ());
@@ -852,9 +876,8 @@ public:
}
// move constructors
- TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default;
- TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other)
- = default;
+ TupleStructItemsNoRest (TupleStructItemsNoRest &&other) = default;
+ TupleStructItemsNoRest &operator= (TupleStructItemsNoRest &&other) = default;
std::string as_string () const override;
@@ -866,32 +889,33 @@ public:
return patterns;
}
- ItemType get_item_type () const override final { return ItemType::MULTIPLE; }
+ ItemType get_item_type () const override final { return ItemType::NO_REST; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- TupleStructItemsNoRange *clone_tuple_items_impl () const override
+ TupleStructItemsNoRest *clone_pattern_items_impl () const override
{
- return new TupleStructItemsNoRange (*this);
+ return new TupleStructItemsNoRest (*this);
}
};
-// Class for ranged tuple struct pattern patterns
-class TupleStructItemsRange : public TupleStructItems
+// Class for patterns within a tuple struct pattern, with a rest pattern
+// included
+class TupleStructItemsHasRest : public TupleStructItems
{
std::vector<std::unique_ptr<Pattern>> lower_patterns;
std::vector<std::unique_ptr<Pattern>> upper_patterns;
public:
- TupleStructItemsRange (std::vector<std::unique_ptr<Pattern>> lower_patterns,
- std::vector<std::unique_ptr<Pattern>> upper_patterns)
+ TupleStructItemsHasRest (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
- TupleStructItemsRange (TupleStructItemsRange const &other)
+ TupleStructItemsHasRest (TupleStructItemsHasRest const &other)
{
lower_patterns.reserve (other.lower_patterns.size ());
for (const auto &e : other.lower_patterns)
@@ -903,7 +927,7 @@ public:
}
// Overloaded assignment operator to clone
- TupleStructItemsRange &operator= (TupleStructItemsRange const &other)
+ TupleStructItemsHasRest &operator= (TupleStructItemsHasRest const &other)
{
lower_patterns.clear ();
lower_patterns.reserve (other.lower_patterns.size ());
@@ -919,8 +943,9 @@ public:
}
// move constructors
- TupleStructItemsRange (TupleStructItemsRange &&other) = default;
- TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default;
+ TupleStructItemsHasRest (TupleStructItemsHasRest &&other) = default;
+ TupleStructItemsHasRest &operator= (TupleStructItemsHasRest &&other)
+ = default;
std::string as_string () const override;
@@ -945,14 +970,14 @@ public:
return upper_patterns;
}
- ItemType get_item_type () const override final { return ItemType::RANGED; }
+ ItemType get_item_type () const override final { return ItemType::HAS_REST; }
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- TupleStructItemsRange *clone_tuple_items_impl () const override
+ TupleStructItemsHasRest *clone_pattern_items_impl () const override
{
- return new TupleStructItemsRange (*this);
+ return new TupleStructItemsHasRest (*this);
}
};
@@ -1025,32 +1050,32 @@ protected:
};
// Base abstract class representing TuplePattern patterns
-class TuplePatternItems : public TupleItems
+class TuplePatternItems : public PatternItems
{
public:
// Unique pointer custom clone function
std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const
{
- return std::unique_ptr<TuplePatternItems> (clone_tuple_items_impl ());
+ return std::unique_ptr<TuplePatternItems> (clone_pattern_items_impl ());
}
protected:
// pure virtual clone implementation
- virtual TuplePatternItems *clone_tuple_items_impl () const override = 0;
+ virtual TuplePatternItems *clone_pattern_items_impl () const override = 0;
};
-// Class representing TuplePattern patterns where there are multiple patterns
-class TuplePatternItemsMultiple : public TuplePatternItems
+// Class representing patterns within a TuplePattern, without a rest pattern
+class TuplePatternItemsNoRest : public TuplePatternItems
{
std::vector<std::unique_ptr<Pattern>> patterns;
public:
- TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern>> patterns)
+ TuplePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
: patterns (std::move (patterns))
{}
// Copy constructor with vector clone
- TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other)
+ TuplePatternItemsNoRest (TuplePatternItemsNoRest const &other)
{
patterns.reserve (other.patterns.size ());
for (const auto &e : other.patterns)
@@ -1058,7 +1083,7 @@ public:
}
// Overloaded assignment operator to vector clone
- TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other)
+ TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest const &other)
{
patterns.clear ();
patterns.reserve (other.patterns.size ());
@@ -1069,15 +1094,15 @@ public:
}
// move constructors
- TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default;
- TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other)
+ TuplePatternItemsNoRest (TuplePatternItemsNoRest &&other) = default;
+ TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest &&other)
= default;
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
- ItemType get_item_type () const override { return ItemType::MULTIPLE; }
+ ItemType get_item_type () const override { return ItemType::NO_REST; }
std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
@@ -1088,27 +1113,29 @@ public:
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- TuplePatternItemsMultiple *clone_tuple_items_impl () const override
+ TuplePatternItemsNoRest *clone_pattern_items_impl () const override
{
- return new TuplePatternItemsMultiple (*this);
+ return new TuplePatternItemsNoRest (*this);
}
};
-// Class representing TuplePattern patterns where there are a range of patterns
-class TuplePatternItemsRanged : public TuplePatternItems
+// Class representing patterns within a TuplePattern, with a rest pattern
+// included
+class TuplePatternItemsHasRest : public TuplePatternItems
{
std::vector<std::unique_ptr<Pattern>> lower_patterns;
std::vector<std::unique_ptr<Pattern>> upper_patterns;
public:
- TuplePatternItemsRanged (std::vector<std::unique_ptr<Pattern>> lower_patterns,
- std::vector<std::unique_ptr<Pattern>> upper_patterns)
+ TuplePatternItemsHasRest (
+ 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
- TuplePatternItemsRanged (TuplePatternItemsRanged const &other)
+ TuplePatternItemsHasRest (TuplePatternItemsHasRest const &other)
{
lower_patterns.reserve (other.lower_patterns.size ());
for (const auto &e : other.lower_patterns)
@@ -1120,7 +1147,7 @@ public:
}
// Overloaded assignment operator to clone
- TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other)
+ TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest const &other)
{
lower_patterns.clear ();
lower_patterns.reserve (other.lower_patterns.size ());
@@ -1136,15 +1163,15 @@ public:
}
// move constructors
- TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default;
- TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other)
+ TuplePatternItemsHasRest (TuplePatternItemsHasRest &&other) = default;
+ TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest &&other)
= default;
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
- ItemType get_item_type () const override { return ItemType::RANGED; }
+ ItemType get_item_type () const override { return ItemType::HAS_REST; }
std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
{
@@ -1167,9 +1194,9 @@ public:
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- TuplePatternItemsRanged *clone_tuple_items_impl () const override
+ TuplePatternItemsHasRest *clone_pattern_items_impl () const override
{
- return new TuplePatternItemsRanged (*this);
+ return new TuplePatternItemsHasRest (*this);
}
};
@@ -1234,10 +1261,161 @@ protected:
}
};
+// Base abstract class representing SlicePattern patterns
+class SlicePatternItems : public PatternItems
+{
+public:
+ // Unique pointer custom clone function
+ std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const
+ {
+ return std::unique_ptr<SlicePatternItems> (clone_pattern_items_impl ());
+ }
+
+protected:
+ // pure virtual clone implementation
+ virtual SlicePatternItems *clone_pattern_items_impl () const override = 0;
+};
+
+// Class representing patterns within a SlicePattern, without a rest pattern
+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 (HIRFullVisitor &vis) override;
+
+ ItemType get_item_type () const override { return ItemType::NO_REST; }
+
+ std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
+ {
+ return patterns;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ SlicePatternItemsNoRest *clone_pattern_items_impl () const override
+ {
+ return new SlicePatternItemsNoRest (*this);
+ }
+};
+
+// Class representing patterns within a SlicePattern, with a rest pattern
+// included
+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 ());
+
+ lower_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 (HIRFullVisitor &vis) override;
+
+ ItemType get_item_type () const override { return ItemType::HAS_REST; }
+
+ std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
+ {
+ return lower_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
+ {
+ return lower_patterns;
+ }
+
+ std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
+ {
+ return upper_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
+ {
+ return upper_patterns;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ SlicePatternItemsHasRest *clone_pattern_items_impl () const override
+ {
+ return new SlicePatternItemsHasRest (*this);
+ }
+};
+
// HIR 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;
Analysis::NodeMapping mappings;
@@ -1245,30 +1423,23 @@ public:
std::string as_string () const override;
SlicePattern (Analysis::NodeMapping mappings,
- std::vector<std::unique_ptr<Pattern>> items, location_t locus)
+ std::unique_ptr<SlicePatternItems> items, location_t locus)
: items (std::move (items)), locus (locus), mappings (mappings)
{}
- // Copy constructor with vector clone
+ // Copy constructor requires clone
SlicePattern (SlicePattern const &other)
- : locus (other.locus), mappings (other.mappings)
- {
- items.reserve (other.items.size ());
- for (const auto &e : other.items)
- items.push_back (e->clone_pattern ());
- }
+ : items (other.items->clone_slice_pattern_items ()), locus (other.locus),
+ mappings (other.mappings)
+ {}
// Overloaded assignment operator to vector clone
SlicePattern &operator= (SlicePattern const &other)
{
+ items = other.items->clone_slice_pattern_items ();
locus = other.locus;
mappings = other.mappings;
- items.clear ();
- items.reserve (other.items.size ());
- for (const auto &e : other.items)
- items.push_back (e->clone_pattern ());
-
return *this;
}
@@ -1276,11 +1447,8 @@ public:
SlicePattern (SlicePattern &&other) = default;
SlicePattern &operator= (SlicePattern &&other) = default;
- std::vector<std::unique_ptr<Pattern>> &get_items () { return items; }
- const std::vector<std::unique_ptr<Pattern>> &get_items () const
- {
- return items;
- }
+ SlicePatternItems &get_items () { return *items; }
+ const SlicePatternItems &get_items () const { return *items; }
location_t get_locus () const override { return locus; }
diff --git a/gcc/rust/hir/tree/rust-hir-type.cc b/gcc/rust/hir/tree/rust-hir-type.cc
index 6a6c319..ec48425 100644
--- a/gcc/rust/hir/tree/rust-hir-type.cc
+++ b/gcc/rust/hir/tree/rust-hir-type.cc
@@ -162,7 +162,7 @@ RawPointerType::operator= (RawPointerType const &other)
ReferenceType::ReferenceType (Analysis::NodeMapping mappings, Mutability mut,
std::unique_ptr<Type> type_no_bounds,
- location_t locus, Lifetime lifetime)
+ location_t locus, tl::optional<Lifetime> lifetime)
: TypeNoBounds (mappings, locus), lifetime (std::move (lifetime)), mut (mut),
type (std::move (type_no_bounds))
{}
diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h
index bd0f2b6..cbc20ff 100644
--- a/gcc/rust/hir/tree/rust-hir-type.h
+++ b/gcc/rust/hir/tree/rust-hir-type.h
@@ -291,7 +291,7 @@ protected:
class ReferenceType : public TypeNoBounds
{
// bool has_lifetime; // TODO: handle in lifetime or something?
- Lifetime lifetime;
+ tl::optional<Lifetime> lifetime;
Mutability mut;
std::unique_ptr<Type> type;
@@ -301,12 +301,12 @@ public:
bool is_mut () const { return mut == Mutability::Mut; }
// Returns whether the reference has a lifetime.
- bool has_lifetime () const { return !lifetime.is_error (); }
+ bool has_lifetime () const { return lifetime.has_value (); }
// Constructor
ReferenceType (Analysis::NodeMapping mappings, Mutability mut,
std::unique_ptr<Type> type_no_bounds, location_t locus,
- Lifetime lifetime);
+ tl::optional<Lifetime> lifetime);
// Copy constructor with custom clone method
ReferenceType (ReferenceType const &other);
@@ -323,7 +323,8 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
- Lifetime &get_lifetime () { return lifetime; }
+ Lifetime &get_lifetime () { return lifetime.value (); }
+ const Lifetime &get_lifetime () const { return lifetime.value (); }
Mutability get_mut () const { return mut; }
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..1e201a5
--- /dev/null
+++ b/gcc/rust/hir/tree/rust-hir-visitor.cc
@@ -0,0 +1,1202 @@
+// 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 (TupleStructItemsNoRest &tuple_items)
+{
+ for (auto &item : tuple_items.get_patterns ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleStructItemsHasRest &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 (TuplePatternItemsNoRest &tuple_items)
+{
+ for (auto &pattern : tuple_items.get_patterns ())
+ pattern->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TuplePatternItemsHasRest &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 (SlicePatternItemsNoRest &items)
+{
+ for (auto &pattern : items.get_patterns ())
+ pattern->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (SlicePatternItemsHasRest &items)
+{
+ for (auto &lower : items.get_lower_patterns ())
+ lower->accept_vis (*this);
+ for (auto &upper : items.get_upper_patterns ())
+ upper->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (SlicePattern &pattern)
+{
+ pattern.get_items ().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 800e647..77760b0 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;
@@ -84,6 +87,8 @@ public:
virtual void visit (AwaitExpr &expr) = 0;
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;
@@ -127,12 +132,14 @@ public:
virtual void visit (StructPatternFieldIdentPat &field) = 0;
virtual void visit (StructPatternFieldIdent &field) = 0;
virtual void visit (StructPattern &pattern) = 0;
- virtual void visit (TupleStructItemsNoRange &tuple_items) = 0;
- virtual void visit (TupleStructItemsRange &tuple_items) = 0;
+ virtual void visit (TupleStructItemsNoRest &tuple_items) = 0;
+ virtual void visit (TupleStructItemsHasRest &tuple_items) = 0;
virtual void visit (TupleStructPattern &pattern) = 0;
- virtual void visit (TuplePatternItemsMultiple &tuple_items) = 0;
- virtual void visit (TuplePatternItemsRanged &tuple_items) = 0;
+ virtual void visit (TuplePatternItemsNoRest &tuple_items) = 0;
+ virtual void visit (TuplePatternItemsHasRest &tuple_items) = 0;
virtual void visit (TuplePattern &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;
virtual void visit (EmptyStmt &stmt) = 0;
@@ -152,6 +159,316 @@ 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 (TupleStructItemsNoRest &node) override { walk (node); }
+ virtual void visit (TupleStructItemsHasRest &node) override { walk (node); }
+ virtual void visit (TupleStructPattern &node) override { walk (node); }
+ virtual void visit (TuplePatternItemsNoRest &node) override { walk (node); }
+ virtual void visit (TuplePatternItemsHasRest &node) override { walk (node); }
+ virtual void visit (TuplePattern &node) override { walk (node); }
+ virtual void visit (SlicePatternItemsNoRest &node) override { walk (node); }
+ virtual void visit (SlicePatternItemsHasRest &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 (TupleStructItemsNoRest &) final;
+ virtual void walk (TupleStructItemsHasRest &) final;
+ virtual void walk (TupleStructPattern &) final;
+ virtual void walk (TuplePatternItemsNoRest &) final;
+ virtual void walk (TuplePatternItemsHasRest &) final;
+ virtual void walk (TuplePattern &) final;
+ virtual void walk (SlicePatternItemsNoRest &) final;
+ virtual void walk (SlicePatternItemsHasRest &) 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:
@@ -200,6 +517,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 {}
@@ -220,6 +539,8 @@ public:
virtual void visit (AwaitExpr &) override {}
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 {}
@@ -271,13 +592,16 @@ public:
virtual void visit (StructPatternFieldIdent &) override {}
virtual void visit (StructPattern &) override {}
- virtual void visit (TupleStructItemsNoRange &) override {}
- virtual void visit (TupleStructItemsRange &) override {}
+ virtual void visit (TupleStructItemsNoRest &) override {}
+ virtual void visit (TupleStructItemsHasRest &) override {}
virtual void visit (TupleStructPattern &) override {}
- virtual void visit (TuplePatternItemsMultiple &) override {}
- virtual void visit (TuplePatternItemsRanged &) override {}
+ virtual void visit (TuplePatternItemsNoRest &) override {}
+ virtual void visit (TuplePatternItemsHasRest &) override {}
virtual void visit (TuplePattern &) override {}
+
+ virtual void visit (SlicePatternItemsNoRest &) override {}
+ virtual void visit (SlicePatternItemsHasRest &) override {}
virtual void visit (SlicePattern &) override {}
virtual void visit (AltPattern &) override {}
@@ -425,6 +749,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;
@@ -441,6 +767,8 @@ 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;
virtual void visit (AsyncBlockExpr &expr) = 0;
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index 822eaff..614fec7 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 ();
@@ -1314,7 +1346,7 @@ ContinueExpr::as_string () const
if (has_label ())
{
- str += label.as_string ();
+ str += get_label ().as_string ();
}
return str;
@@ -1704,7 +1736,7 @@ WhileLoopExpr::as_string () const
}
else
{
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
}
str += "\n Conditional expr: " + condition->as_string ();
@@ -1726,7 +1758,7 @@ WhileLetLoopExpr::as_string () const
}
else
{
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
}
str += "\n Match arm patterns: ";
@@ -1761,7 +1793,7 @@ LoopExpr::as_string () const
}
else
{
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
}
str += "\n Loop block: " + loop_block->as_string ();
@@ -1816,7 +1848,7 @@ BreakExpr::as_string () const
if (has_label ())
{
- str += label.as_string () + " ";
+ str += get_label ().as_string () + " ";
}
if (has_break_expr ())
@@ -2101,11 +2133,6 @@ QualifiedPathInType::as_string () const
std::string
Lifetime::as_string () const
{
- if (is_error ())
- {
- return "error lifetime";
- }
-
switch (lifetime_type)
{
case AST::Lifetime::LifetimeType::NAMED:
@@ -2212,8 +2239,8 @@ PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const
// create segment and add to vector
std::string segment_str = segment.as_string ();
- simple_segments.push_back (
- AST::SimplePathSegment (std::move (segment_str), segment.get_locus ()));
+ simple_segments.emplace_back (std::move (segment_str),
+ segment.get_locus ());
}
// kind of a HACK to get locus depending on opening scope resolution
@@ -2254,9 +2281,8 @@ TypePath::as_simple_path () const
// create segment and add to vector
std::string segment_str = segment->as_string ();
- simple_segments.push_back (
- AST::SimplePathSegment (std::move (segment_str),
- segment->get_locus ()));
+ simple_segments.emplace_back (std::move (segment_str),
+ segment->get_locus ());
}
return AST::SimplePath (std::move (simple_segments),
@@ -2360,11 +2386,11 @@ RangePatternBoundLiteral::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 ();
}
@@ -2373,6 +2399,46 @@ SlicePattern::as_string () const
}
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: ");
@@ -2386,7 +2452,7 @@ AltPattern::as_string () const
}
std::string
-TuplePatternItemsMultiple::as_string () const
+TuplePatternItemsNoRest::as_string () const
{
std::string str;
@@ -2399,7 +2465,7 @@ TuplePatternItemsMultiple::as_string () const
}
std::string
-TuplePatternItemsRanged::as_string () const
+TuplePatternItemsHasRest::as_string () const
{
std::string str;
@@ -2453,10 +2519,29 @@ StructPatternField::as_string () const
* just the body */
for (const auto &attr : outer_attrs)
{
- str += "\n " + attr.as_string ();
+ str += "\n " + attr.as_string ();
}
}
+ str += "\n item type: ";
+ switch (get_item_type ())
+ {
+ case ItemType::TUPLE_PAT:
+ str += "TUPLE_PAT";
+ break;
+ case ItemType::IDENT_PAT:
+ str += "IDENT_PAT";
+ break;
+ case ItemType::IDENT:
+ str += "IDENT";
+ break;
+ default:
+ str += "UNKNOWN";
+ break;
+ }
+
+ str += "\n mapping: " + mappings.as_string ();
+
return str;
}
@@ -2549,7 +2634,7 @@ StructPattern::as_string () const
std::string
LiteralPattern::as_string () const
{
- return lit.as_string ();
+ return (has_minus ? "-" : "") + lit.as_string ();
}
std::string
@@ -2584,16 +2669,16 @@ 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;
}
std::string
-TupleStructItemsNoRange::as_string () const
+TupleStructItemsNoRest::as_string () const
{
std::string str;
@@ -2606,7 +2691,7 @@ TupleStructItemsNoRange::as_string () const
}
std::string
-TupleStructItemsRange::as_string () const
+TupleStructItemsHasRest::as_string () const
{
std::string str ("\n Lower patterns: ");
@@ -2760,7 +2845,7 @@ ReferenceType::as_string () const
if (has_lifetime ())
{
- str += lifetime.as_string () + " ";
+ str += get_lifetime ().as_string () + " ";
}
if (is_mut ())
@@ -3411,7 +3496,7 @@ TraitFunctionDecl::as_string () const
str += "\n Function params: ";
if (is_method ())
{
- str += self.as_string () + (has_params () ? ", " : "");
+ str += get_self_unchecked ().as_string () + (has_params () ? ", " : "");
}
if (has_params ())
@@ -3497,6 +3582,18 @@ TraitItemType::as_string () const
str += "\ntype " + name.as_string ();
+ if (has_generics ())
+ {
+ str += "<";
+ for (size_t i = 0; i < generic_params.size (); i++)
+ {
+ if (i > 0)
+ str += ", ";
+ str += generic_params[i]->as_string ();
+ }
+ str += ">";
+ }
+
str += "\n Type param bounds: ";
if (!has_type_param_bounds ())
{
@@ -3525,70 +3622,63 @@ TraitItemType::as_string () const
std::string
SelfParam::as_string () const
{
- if (is_error ())
- {
- return "error";
- }
- else
+ if (has_type ())
{
- if (has_type ())
+ // type (i.e. not ref, no lifetime)
+ std::string str;
+
+ if (is_mut ())
{
- // type (i.e. not ref, no lifetime)
- std::string str;
+ str += "mut ";
+ }
- if (is_mut ())
- {
- str += "mut ";
- }
+ str += "self : ";
- str += "self : ";
+ str += type->as_string ();
- str += type->as_string ();
+ return str;
+ }
+ else if (has_lifetime ())
+ {
+ // ref and lifetime
+ std::string str = "&" + get_lifetime ().as_string () + " ";
- return str;
- }
- else if (has_lifetime ())
+ if (is_mut ())
{
- // ref and lifetime
- std::string str = "&" + lifetime.as_string () + " ";
+ str += "mut ";
+ }
- if (is_mut ())
- {
- str += "mut ";
- }
+ str += "self";
- str += "self";
+ return str;
+ }
+ else if (is_ref ())
+ {
+ // ref with no lifetime
+ std::string str = "&";
- return str;
- }
- else if (is_ref ())
+ if (is_mut ())
{
- // ref with no lifetime
- std::string str = "&";
+ str += " mut ";
+ }
- if (is_mut ())
- {
- str += " mut ";
- }
+ str += "self";
- str += "self";
+ return str;
+ }
+ else
+ {
+ // no ref, no type
+ std::string str;
- return str;
- }
- else
+ if (is_mut ())
{
- // no ref, no type
- std::string str;
-
- if (is_mut ())
- {
- str += "mut ";
- }
+ str += "mut ";
+ }
- str += "self";
+ str += "self";
- return str;
- }
+ return str;
}
}
@@ -3834,6 +3924,17 @@ InlineAsm::accept_vis (HIRFullVisitor &vis)
}
void
+LlvmInlineAsm::accept_vis (HIRFullVisitor &vis)
+{
+ vis.visit (*this);
+}
+void
+LlvmInlineAsm::accept_vis (HIRExpressionVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
BorrowExpr::accept_vis (HIRExpressionVisitor &vis)
{
vis.visit (*this);
@@ -4056,6 +4157,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);
@@ -4428,13 +4541,13 @@ StructPattern::accept_vis (HIRFullVisitor &vis)
}
void
-TupleStructItemsNoRange::accept_vis (HIRFullVisitor &vis)
+TupleStructItemsNoRest::accept_vis (HIRFullVisitor &vis)
{
vis.visit (*this);
}
void
-TupleStructItemsRange::accept_vis (HIRFullVisitor &vis)
+TupleStructItemsHasRest::accept_vis (HIRFullVisitor &vis)
{
vis.visit (*this);
}
@@ -4446,13 +4559,13 @@ TupleStructPattern::accept_vis (HIRFullVisitor &vis)
}
void
-TuplePatternItemsMultiple::accept_vis (HIRFullVisitor &vis)
+TuplePatternItemsNoRest::accept_vis (HIRFullVisitor &vis)
{
vis.visit (*this);
}
void
-TuplePatternItemsRanged::accept_vis (HIRFullVisitor &vis)
+TuplePatternItemsHasRest::accept_vis (HIRFullVisitor &vis)
{
vis.visit (*this);
}
@@ -4464,6 +4577,18 @@ TuplePattern::accept_vis (HIRFullVisitor &vis)
}
void
+SlicePatternItemsNoRest::accept_vis (HIRFullVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+SlicePatternItemsHasRest::accept_vis (HIRFullVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
SlicePattern::accept_vis (HIRFullVisitor &vis)
{
vis.visit (*this);
@@ -5028,6 +5153,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/lang.opt.urls b/gcc/rust/lang.opt.urls
index 33a54b4..09cfede 100644
--- a/gcc/rust/lang.opt.urls
+++ b/gcc/rust/lang.opt.urls
@@ -1,7 +1,7 @@
; Autogenerated by regenerate-opt-urls.py from gcc/rust/lang.opt and generated HTML
I
-UrlSuffix(gcc/Directory-Options.html#index-I) LangUrlSuffix_D(gdc/Directory-Options.html#index-I)
+UrlSuffix(gcc/Directory-Options.html#index-I) LangUrlSuffix_D(gdc/Directory-Options.html#index-I) LangUrlSuffix_Algol68(ga68/Directory-options.html#index-I)
L
UrlSuffix(gcc/Directory-Options.html#index-L) LangUrlSuffix_D(gdc/Directory-Options.html#index-L)
diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index b143e70..a99b5ed 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -236,10 +236,11 @@ Lexer::dump_and_skip (int n)
out << "<id=";
out << tok->token_id_to_str ();
- out << (tok->has_str () ? (std::string (", text=") + tok->get_str ()
- + std::string (", typehint=")
- + std::string (tok->get_type_hint_str ()))
- : "")
+ out << (tok->should_have_str ()
+ ? (std::string (", text=") + tok->get_str ()
+ + std::string (", typehint=")
+ + std::string (tok->get_type_hint_str ()))
+ : "")
<< " ";
out << Linemap::location_to_string (loc) << '\n';
}
@@ -1317,7 +1318,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 +1402,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 +1441,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 +1898,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 +1910,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++;
@@ -2635,37 +2639,37 @@ void
rust_input_source_test ()
{
// ASCII
- std::string src = u8"_abcde\tXYZ\v\f";
- std::vector<uint32_t> expected
- = {'_', 'a', 'b', 'c', 'd', 'e', '\t', 'X', 'Y', 'Z', '\v', '\f'};
+ std::string src = (const char *) u8"_abcde\tXYZ\v\f";
+ std::vector<uint32_t> expected = {u'_', u'a', u'b', u'c', u'd', u'e',
+ u'\t', u'X', u'Y', u'Z', u'\v', u'\f'};
test_buffer_input_source (src, expected);
// BOM
- src = u8"\xef\xbb\xbfOK";
- expected = {'O', 'K'};
+ src = (const char *) u8"\xef\xbb\xbfOK";
+ expected = {u'O', u'K'};
test_buffer_input_source (src, expected);
// Russian
- src = u8"приве́т";
- expected = {L'п',
- L'р',
- L'и',
- L'в',
+ src = (const char *) u8"приве́т";
+ expected = {u'п',
+ u'р',
+ u'и',
+ u'в',
0x0435 /* CYRILLIC SMALL LETTER IE е */,
0x301 /* COMBINING ACUTE ACCENT ́ */,
- L'т'};
+ u'т'};
test_buffer_input_source (src, expected);
- src = u8"❤️🦀";
+ src = (const char *) u8"❤️🦀";
expected = {0x2764 /* HEAVY BLACK HEART */,
- 0xfe0f /* VARIATION SELECTOR-16 */, L'🦀'};
+ 0xfe0f /* VARIATION SELECTOR-16 */, U'🦀'};
test_buffer_input_source (src, expected);
- src = u8"こんにちは";
- expected = {L'こ', L'ん', L'に', L'ち', L'は'};
+ src = (const char *) u8"こんにちは";
+ expected = {u'こ', u'ん', u'に', u'ち', u'は'};
test_file_input_source (src, expected);
- src = u8"👮‍♂👩‍⚕";
+ src = (const char *) u8"👮‍♂👩‍⚕";
expected
= {0x1f46e /* POLICE OFFICER */, 0x200d /* ZERO WIDTH JOINER */,
0x2642 /* MALE SIGN */, 0x1f469 /* WOMAN */,
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..43682af 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; \
} \
@@ -176,29 +178,6 @@ nfc_normalize_token_string (location_t loc, TokenId id, const std::string &str)
return str;
}
-const std::string &
-Token::get_str () const
-{
- if (token_id_is_keyword (token_id))
- return token_id_keyword_string (token_id);
-
- // FIXME: attempt to return null again
- // gcc_assert(str != NULL);
-
- // HACK: allow referencing an empty string
- static const std::string empty = "";
-
- if (str == NULL)
- {
- rust_error_at (get_locus (),
- "attempted to get string for %qs, which has no string. "
- "returning empty string instead",
- get_token_description ());
- return empty;
- }
- return *str;
-}
-
namespace {
enum class Context
{
@@ -234,6 +213,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..71a7503 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -22,8 +22,13 @@
#include "rust-system.h"
#include "rust-linemap.h"
#include "rust-unicode.h"
+#include "rust-diagnostics.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 +226,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
@@ -250,7 +250,7 @@ private:
// Token location.
location_t locus;
// Associated text (if any) of token.
- std::unique_ptr<std::string> str;
+ std::string str;
// TODO: maybe remove issues and just store std::string as value?
/* Type hint for token based on lexer data (e.g. type suffix). Does not exist
* for most tokens. */
@@ -258,23 +258,21 @@ private:
// Token constructor from token id and location. Has a null string.
Token (TokenId token_id, location_t location)
- : token_id (token_id), locus (location), str (nullptr),
- type_hint (CORETYPE_UNKNOWN)
+ : token_id (token_id), locus (location), type_hint (CORETYPE_UNKNOWN)
{}
// Token constructor from token id, location, and a string.
- Token (TokenId token_id, location_t location, std::string &&paramStr)
+ Token (TokenId token_id, location_t location, std::string paramStr)
: token_id (token_id), locus (location), type_hint (CORETYPE_UNKNOWN)
{
// Normalize identifier tokens
- str = std::make_unique<std::string> (
- nfc_normalize_token_string (location, token_id, paramStr));
+ str = nfc_normalize_token_string (location, token_id, std::move (paramStr));
}
// Token constructor from token id, location, and a char.
Token (TokenId token_id, location_t location, char paramChar)
- : token_id (token_id), locus (location),
- str (new std::string (1, paramChar)), type_hint (CORETYPE_UNKNOWN)
+ : token_id (token_id), locus (location), str (1, paramChar),
+ type_hint (CORETYPE_UNKNOWN)
{
// Do not need to normalize 1byte char
}
@@ -284,19 +282,17 @@ private:
: token_id (token_id), locus (location), type_hint (CORETYPE_UNKNOWN)
{
// Normalize identifier tokens
- str = std::make_unique<std::string> (
- nfc_normalize_token_string (location, token_id,
- paramCodepoint.as_string ()));
+ str = nfc_normalize_token_string (location, token_id,
+ paramCodepoint.as_string ());
}
// Token constructor from token id, location, a string, and type hint.
- Token (TokenId token_id, location_t location, std::string &&paramStr,
+ Token (TokenId token_id, location_t location, std::string paramStr,
PrimitiveCoreType parType)
: token_id (token_id), locus (location), type_hint (parType)
{
// Normalize identifier tokens
- str = std::make_unique<std::string> (
- nfc_normalize_token_string (location, token_id, paramStr));
+ str = nfc_normalize_token_string (location, token_id, std::move (paramStr));
}
public:
@@ -323,14 +319,16 @@ public:
}
// Makes and returns a new TokenPtr of type IDENTIFIER.
- static TokenPtr make_identifier (location_t locus, std::string &&str)
+ static TokenPtr make_identifier (location_t locus, std::string str)
{
// return std::make_shared<Token> (IDENTIFIER, locus, str);
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,
+ static TokenPtr make_int (location_t locus, std::string str,
PrimitiveCoreType type_hint = CORETYPE_UNKNOWN)
{
// return std::make_shared<Token> (INT_LITERAL, locus, str, type_hint);
@@ -339,7 +337,7 @@ public:
}
// Makes and returns a new TokenPtr of type FLOAT_LITERAL.
- static TokenPtr make_float (location_t locus, std::string &&str,
+ static TokenPtr make_float (location_t locus, std::string str,
PrimitiveCoreType type_hint = CORETYPE_UNKNOWN)
{
// return std::make_shared<Token> (FLOAT_LITERAL, locus, str, type_hint);
@@ -348,7 +346,7 @@ public:
}
// Makes and returns a new TokenPtr of type STRING_LITERAL.
- static TokenPtr make_string (location_t locus, std::string &&str)
+ static TokenPtr make_string (location_t locus, std::string str)
{
// return std::make_shared<Token> (STRING_LITERAL, locus, str,
// CORETYPE_STR);
@@ -371,32 +369,32 @@ public:
}
// Makes and returns a new TokenPtr of type BYTE_STRING_LITERAL (fix).
- static TokenPtr make_byte_string (location_t locus, std::string &&str)
+ static TokenPtr make_byte_string (location_t locus, std::string str)
{
// return std::make_shared<Token> (BYTE_STRING_LITERAL, locus, str);
return TokenPtr (new Token (BYTE_STRING_LITERAL, locus, std::move (str)));
}
// Makes and returns a new TokenPtr of type RAW_STRING_LITERAL.
- static TokenPtr make_raw_string (location_t locus, std::string &&str)
+ static TokenPtr make_raw_string (location_t locus, std::string str)
{
return TokenPtr (new Token (RAW_STRING_LITERAL, locus, std::move (str)));
}
// Makes and returns a new TokenPtr of type INNER_DOC_COMMENT.
- static TokenPtr make_inner_doc_comment (location_t locus, std::string &&str)
+ static TokenPtr make_inner_doc_comment (location_t locus, std::string str)
{
return TokenPtr (new Token (INNER_DOC_COMMENT, locus, std::move (str)));
}
// Makes and returns a new TokenPtr of type OUTER_DOC_COMMENT.
- static TokenPtr make_outer_doc_comment (location_t locus, std::string &&str)
+ static TokenPtr make_outer_doc_comment (location_t locus, std::string str)
{
return TokenPtr (new Token (OUTER_DOC_COMMENT, locus, std::move (str)));
}
// Makes and returns a new TokenPtr of type LIFETIME.
- static TokenPtr make_lifetime (location_t locus, std::string &&str)
+ static TokenPtr make_lifetime (location_t locus, std::string str)
{
// return std::make_shared<Token> (LIFETIME, locus, str);
return TokenPtr (new Token (LIFETIME, locus, std::move (str)));
@@ -412,16 +410,18 @@ public:
void set_locus (location_t locus) { this->locus = locus; }
// Gets string description of the token.
- const std::string &
- get_str () const; /*{
-// FIXME: put in header again when fix null problem
-//gcc_assert(str != nullptr);
-if (str == nullptr) {
-error_at(get_locus(), "attempted to get string for '%s', which has no string.
-returning empty string instead.", get_token_description()); return "";
-}
-return *str;
-}*/
+ const std::string &get_str () const
+ {
+ if (token_id_is_keyword (token_id))
+ return token_id_keyword_string (token_id);
+
+ if (!should_have_str ())
+ rust_internal_error_at (
+ locus, "attempting to get string for %qs, which should have no string",
+ get_token_description ());
+
+ return str;
+ }
// Gets token's type hint info.
PrimitiveCoreType get_type_hint () const
@@ -463,14 +463,11 @@ return *str;
}
}
- /* Returns whether the token actually has a string (regardless of whether it
- * should or not). */
- bool has_str () const { return str != nullptr; }
-
// Returns whether the token should have a string.
bool should_have_str () const
{
- return is_literal () || token_id == IDENTIFIER || token_id == LIFETIME;
+ return is_literal () || token_id == IDENTIFIER || token_id == LIFETIME
+ || token_id == INNER_DOC_COMMENT || token_id == OUTER_DOC_COMMENT;
}
// Returns whether the token is a pure decimal int literal
diff --git a/gcc/rust/metadata/rust-export-metadata.cc b/gcc/rust/metadata/rust-export-metadata.cc
index 771bec6..a8d4af1 100644
--- a/gcc/rust/metadata/rust-export-metadata.cc
+++ b/gcc/rust/metadata/rust-export-metadata.cc
@@ -23,6 +23,7 @@
#include "rust-ast-dump.h"
#include "rust-abi.h"
#include "rust-item.h"
+#include "rust-macro.h"
#include "rust-object-export.h"
#include "md5.h"
@@ -91,8 +92,8 @@ ExportContext::emit_function (const HIR::Function &fn)
AST::Function &function = static_cast<AST::Function &> (vis_item);
std::vector<std::unique_ptr<AST::ExternalItem>> external_items;
- external_items.push_back (std::unique_ptr<AST::ExternalItem> (
- static_cast<AST::ExternalItem *> (&function)));
+ external_items.emplace_back (
+ static_cast<AST::ExternalItem *> (&function));
AST::ExternBlock extern_block (get_string_from_abi (Rust::ABI::RUST),
std::move (external_items),
@@ -111,14 +112,12 @@ ExportContext::emit_function (const HIR::Function &fn)
}
void
-ExportContext::emit_macro (NodeId macro)
+ExportContext::emit_macro (AST::MacroRulesDefinition &macro)
{
std::stringstream oss;
AST::Dump dumper (oss);
- AST::Item *item = mappings.lookup_ast_item (macro).value ();
-
- dumper.go (*item);
+ dumper.go (macro);
public_interface_buffer += oss.str ();
}
@@ -195,7 +194,7 @@ PublicInterface::gather_export_data ()
vis_item.accept_vis (visitor);
}
- for (const auto &macro : mappings.get_exported_macros ())
+ for (auto &macro : mappings.get_exported_macros ())
context.emit_macro (macro);
}
@@ -263,8 +262,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-export-metadata.h b/gcc/rust/metadata/rust-export-metadata.h
index ee006cd..7747d95 100644
--- a/gcc/rust/metadata/rust-export-metadata.h
+++ b/gcc/rust/metadata/rust-export-metadata.h
@@ -48,7 +48,7 @@ public:
* directly refer to them using their NodeId. There's no need to keep an HIR
* node for them.
*/
- void emit_macro (NodeId macro);
+ void emit_macro (AST::MacroRulesDefinition &macro);
const std::string &get_interface_buffer () const;
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 71d7250..6cb8f0e 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 ();
@@ -424,10 +431,6 @@ Parser<ManagedTokenSource>::parse_items ()
std::unique_ptr<AST::Item> item = parse_item (false);
if (item == nullptr)
{
- Error error (lexer.peek_token ()->get_locus (),
- "failed to parse item in crate");
- add_error (std::move (error));
-
// TODO: should all items be cleared?
items = std::vector<std::unique_ptr<AST::Item>> ();
break;
@@ -651,10 +654,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 +682,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 +791,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 +801,8 @@ Parser<ManagedTokenSource>::parse_attr_input ()
return input_tree;
}
- case EQUAL: {
+ case EQUAL:
+ {
// = LiteralExpr
lexer.skip_token ();
@@ -877,7 +880,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:
@@ -972,16 +978,7 @@ Parser<ManagedTokenSource>::parse_delim_token_tree ()
std::unique_ptr<AST::TokenTree> tok_tree = parse_token_tree ();
if (tok_tree == nullptr)
- {
- // TODO: is this error handling appropriate?
- Error error (
- t->get_locus (),
- "failed to parse token tree in delimited token tree - found %qs",
- t->get_token_description ());
- add_error (std::move (error));
-
- return AST::DelimTokenTree::create_empty ();
- }
+ return AST::DelimTokenTree::create_empty ();
token_trees_in_tree.push_back (std::move (tok_tree));
@@ -1043,6 +1040,7 @@ Parser<ManagedTokenSource>::parse_identifier_or_keyword_token ()
}
else
{
+ add_error (Error (t->get_locus (), "expected keyword or identifier"));
return nullptr;
}
}
@@ -1068,11 +1066,12 @@ Parser<ManagedTokenSource>::parse_token_tree ()
case RIGHT_SQUARE:
case RIGHT_CURLY:
// error - should not be called when this a token
- add_error (
- Error (t->get_locus (),
- "unexpected closing delimiter %qs - token tree requires "
- "either paired delimiters or non-delimiter tokens",
- t->get_token_description ()));
+ add_error (Error (t->get_locus (), "unexpected closing delimiter %qs",
+ t->get_token_description ()));
+
+ add_error (Error (Error::Kind::Hint, t->get_locus (),
+ "token tree requires either paired delimiters or "
+ "non-delimiter tokens"));
lexer.skip_token ();
return nullptr;
@@ -1706,10 +1705,9 @@ Parser<ManagedTokenSource>::parse_decl_macro_def (AST::Visibility vis,
return nullptr;
}
- AST::MacroRule macro_rule
- = AST::MacroRule (std::move (matcher), std::move (transcriber), locus);
std::vector<AST::MacroRule> macro_rules;
- macro_rules.push_back (macro_rule);
+ macro_rules.emplace_back (std::move (matcher), std::move (transcriber),
+ locus);
return std::unique_ptr<AST::MacroRulesDefinition> (
AST::MacroRulesDefinition::decl_macro (std::move (rule_name),
@@ -1851,20 +1849,13 @@ Parser<ManagedTokenSource>::parse_macro_invocation_semi (
t = lexer.peek_token ();
// parse token trees until the initial delimiter token is found again
- while (!token_id_matches_delims (t->get_id (), delim_type))
+ while (!token_id_matches_delims (t->get_id (), delim_type)
+ && t->get_id () != END_OF_FILE)
{
std::unique_ptr<AST::TokenTree> tree = parse_token_tree ();
if (tree == nullptr)
- {
- Error error (t->get_locus (),
- "failed to parse token tree for macro invocation semi "
- "- found %qs",
- t->get_token_description ());
- add_error (std::move (error));
-
- return nullptr;
- }
+ return nullptr;
token_trees.push_back (std::move (tree));
@@ -2117,7 +2108,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 +2123,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 +2395,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 +2460,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 +2725,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 +2790,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 +2834,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",
@@ -2985,8 +2991,9 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
else
{
std::unique_ptr<AST::BlockExpr> block_expr = parse_block_expr ();
- if (block_expr != nullptr)
- body = std::move (block_expr);
+ if (block_expr == nullptr)
+ return nullptr;
+ body = std::move (block_expr);
}
return std::unique_ptr<AST::Function> (
@@ -3100,9 +3107,10 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
switch (token->get_id ())
{
- case LIFETIME: {
+ case LIFETIME:
+ {
auto lifetime = parse_lifetime (false);
- if (lifetime.is_error ())
+ if (!lifetime)
{
rust_error_at (
token->get_locus (),
@@ -3122,11 +3130,12 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
}
param = std::unique_ptr<AST::LifetimeParam> (new AST::LifetimeParam (
- std::move (lifetime), std::move (lifetime_bounds),
+ std::move (lifetime.value ()), std::move (lifetime_bounds),
std::move (outer_attrs), token->get_locus ()));
break;
}
- case IDENTIFIER: {
+ case IDENTIFIER:
+ {
auto type_ident = token->get_str ();
lexer.skip_token ();
@@ -3161,7 +3170,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);
@@ -3174,24 +3184,28 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
return nullptr;
// optional default value
- auto default_expr = AST::GenericArg::create_error ();
+ tl::optional<AST::GenericArg> default_expr = tl::nullopt;
if (lexer.peek_token ()->get_id () == EQUAL)
{
lexer.skip_token ();
auto tok = lexer.peek_token ();
default_expr = parse_generic_arg ();
- if (default_expr.is_error ())
- rust_error_at (tok->get_locus (),
- "invalid token for start of default value for "
- "const generic parameter: expected %<block%>, "
- "%<identifier%> or %<literal%>, got %qs",
- token_id_to_str (tok->get_id ()));
+ if (!default_expr)
+ {
+ rust_error_at (tok->get_locus (),
+ "invalid token for start of default value for "
+ "const generic parameter: expected %<block%>, "
+ "%<identifier%> or %<literal%>, got %qs",
+ token_id_to_str (tok->get_id ()));
+ return nullptr;
+ }
// At this point, we *know* that we are parsing a const
// expression
- if (default_expr.get_kind () == AST::GenericArg::Kind::Either)
- default_expr = default_expr.disambiguate_to_const ();
+ if (default_expr.value ().get_kind ()
+ == AST::GenericArg::Kind::Either)
+ default_expr = default_expr.value ().disambiguate_to_const ();
}
param = std::unique_ptr<AST::ConstGenericParam> (
@@ -3230,8 +3244,12 @@ Parser<ManagedTokenSource>::parse_generic_params (EndTokenPred is_end_token)
// Did we parse a generic type param yet
auto type_seen = false;
+ // Did we parse a const param with a default value yet
+ auto const_with_default_seen = false;
// Did the user write a lifetime parameter after a type one
auto order_error = false;
+ // Did the user write a const param with a default value after a type one
+ auto const_with_default_order_error = false;
// parse lifetime params
while (!is_end_token (lexer.peek_token ()->get_id ()))
@@ -3239,12 +3257,29 @@ Parser<ManagedTokenSource>::parse_generic_params (EndTokenPred is_end_token)
auto param = parse_generic_param (is_end_token);
if (param)
{
- // TODO: Handle `Const` here as well if necessary
if (param->get_kind () == AST::GenericParam::Kind::Type)
- type_seen = true;
+ {
+ type_seen = true;
+ if (const_with_default_seen)
+ const_with_default_order_error = true;
+ }
else if (param->get_kind () == AST::GenericParam::Kind::Lifetime
&& type_seen)
- order_error = true;
+ {
+ order_error = true;
+ if (const_with_default_seen)
+ const_with_default_order_error = true;
+ }
+ else if (param->get_kind () == AST::GenericParam::Kind::Const)
+ {
+ type_seen = true;
+ AST::ConstGenericParam *const_param
+ = static_cast<AST::ConstGenericParam *> (param.get ());
+ if (const_param->has_default_value ())
+ const_with_default_seen = true;
+ else if (const_with_default_seen)
+ const_with_default_order_error = true;
+ }
generic_params.emplace_back (std::move (param));
maybe_skip_token (COMMA);
@@ -3261,6 +3296,13 @@ Parser<ManagedTokenSource>::parse_generic_params (EndTokenPred is_end_token)
"must be declared prior to type and const parameters");
add_error (std::move (error));
}
+ if (const_with_default_order_error)
+ {
+ Error error (generic_params.front ()->get_locus (),
+ "invalid order for generic parameters: generic parameters "
+ "with a default must be trailing");
+ add_error (std::move (error));
+ }
generic_params.shrink_to_fit ();
return generic_params;
@@ -3276,16 +3318,16 @@ Parser<ManagedTokenSource>::parse_lifetime_params ()
while (lexer.peek_token ()->get_id () != END_OF_FILE)
{
- AST::LifetimeParam lifetime_param = parse_lifetime_param ();
+ auto lifetime_param = parse_lifetime_param ();
- if (lifetime_param.is_error ())
+ if (!lifetime_param)
{
// can't treat as error as only way to get out with trailing comma
break;
}
- lifetime_params.push_back (std::unique_ptr<AST::LifetimeParam> (
- new AST::LifetimeParam (std::move (lifetime_param))));
+ lifetime_params.emplace_back (
+ new AST::LifetimeParam (std::move (lifetime_param.value ())));
if (lexer.peek_token ()->get_id () != COMMA)
break;
@@ -3311,9 +3353,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token)
// if end_token is not specified, it defaults to EOF, so should work fine
while (!is_end_token (lexer.peek_token ()->get_id ()))
{
- AST::LifetimeParam lifetime_param = parse_lifetime_param ();
+ auto lifetime_param = parse_lifetime_param ();
- if (lifetime_param.is_error ())
+ if (!lifetime_param)
{
/* TODO: is it worth throwing away all lifetime params just because
* one failed? */
@@ -3324,8 +3366,8 @@ Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token)
return {};
}
- lifetime_params.push_back (std::unique_ptr<AST::LifetimeParam> (
- new AST::LifetimeParam (std::move (lifetime_param))));
+ lifetime_params.emplace_back (
+ new AST::LifetimeParam (std::move (lifetime_param)));
if (lexer.peek_token ()->get_id () != COMMA)
break;
@@ -3341,7 +3383,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 ()
@@ -3351,15 +3394,15 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs ()
// bad control structure as end token cannot be guaranteed
while (true)
{
- AST::LifetimeParam lifetime_param = parse_lifetime_param ();
+ auto lifetime_param = parse_lifetime_param ();
- if (lifetime_param.is_error ())
+ if (!lifetime_param)
{
// not an error as only way to exit if trailing comma
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;
@@ -3386,9 +3429,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs (
while (!is_end_token (lexer.peek_token ()->get_id ()))
{
- AST::LifetimeParam lifetime_param = parse_lifetime_param ();
+ auto lifetime_param = parse_lifetime_param ();
- if (lifetime_param.is_error ())
+ if (!lifetime_param)
{
/* TODO: is it worth throwing away all lifetime params just because
* one failed? */
@@ -3399,7 +3442,7 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs (
return {};
}
- 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;
@@ -3458,7 +3501,7 @@ Parser<ManagedTokenSource>::parse_non_ptr_sequence (
/* Parses a single lifetime generic parameter (not including comma). */
template <typename ManagedTokenSource>
-AST::LifetimeParam
+tl::expected<AST::LifetimeParam, ParseLifetimeParamError>
Parser<ManagedTokenSource>::parse_lifetime_param ()
{
// parse outer attributes, which are optional and may not exist
@@ -3468,8 +3511,8 @@ Parser<ManagedTokenSource>::parse_lifetime_param ()
const_TokenPtr lifetime_tok = lexer.peek_token ();
if (lifetime_tok->get_id () != LIFETIME)
{
- // if lifetime is missing, must not be a lifetime param, so return null
- return AST::LifetimeParam::create_error ();
+ // if lifetime is missing, must not be a lifetime param, so return error
+ return tl::make_unexpected<ParseLifetimeParamError> ({});
}
lexer.skip_token ();
AST::Lifetime lifetime (AST::Lifetime::NAMED, lifetime_tok->get_str (),
@@ -3815,12 +3858,13 @@ template <typename ManagedTokenSource>
std::unique_ptr<AST::LifetimeWhereClauseItem>
Parser<ManagedTokenSource>::parse_lifetime_where_clause_item ()
{
- AST::Lifetime lifetime = parse_lifetime (false);
- if (lifetime.is_error ())
+ auto parsed_lifetime = parse_lifetime (false);
+ if (!parsed_lifetime)
{
// TODO: error here?
return nullptr;
}
+ auto lifetime = parsed_lifetime.value ();
if (!skip_token (COLON))
{
@@ -4013,7 +4057,7 @@ Parser<ManagedTokenSource>::parse_type_param_bound ()
{
case LIFETIME:
return std::unique_ptr<AST::Lifetime> (
- new AST::Lifetime (parse_lifetime (false)));
+ new AST::Lifetime (parse_lifetime (false).value ()));
case LEFT_PAREN:
case QUESTION_MARK:
case FOR:
@@ -4086,13 +4130,13 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds ()
while (true)
{
- AST::Lifetime lifetime = parse_lifetime (false);
+ auto lifetime = parse_lifetime (false);
// quick exit for parsing failure
- if (lifetime.is_error ())
+ if (!lifetime)
break;
- lifetime_bounds.push_back (std::move (lifetime));
+ lifetime_bounds.push_back (std::move (lifetime.value ()));
/* plus is maybe not allowed at end - spec defines it weirdly, so
* assuming allowed at end */
@@ -4116,9 +4160,9 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token)
while (!is_end_token (lexer.peek_token ()->get_id ()))
{
- AST::Lifetime lifetime = parse_lifetime (false);
+ auto lifetime = parse_lifetime (false);
- if (lifetime.is_error ())
+ if (!lifetime)
{
/* TODO: is it worth throwing away all lifetime bound info just
* because one failed? */
@@ -4129,7 +4173,7 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token)
return {};
}
- lifetime_bounds.push_back (std::move (lifetime));
+ lifetime_bounds.push_back (std::move (lifetime.value ()));
/* plus is maybe not allowed at end - spec defines it weirdly, so
* assuming allowed at end */
@@ -4146,14 +4190,20 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token)
/* Parses a lifetime token (named, 'static, or '_). Also handles lifetime not
* existing. */
template <typename ManagedTokenSource>
-AST::Lifetime
+tl::expected<AST::Lifetime, ParseLifetimeError>
Parser<ManagedTokenSource>::parse_lifetime (bool allow_elided)
{
const_TokenPtr lifetime_tok = lexer.peek_token ();
if (lifetime_tok->get_id () != LIFETIME)
{
- return (allow_elided) ? AST::Lifetime::elided ()
- : AST::Lifetime::error ();
+ if (allow_elided)
+ {
+ return AST::Lifetime::elided ();
+ }
+ else
+ {
+ return tl::make_unexpected<ParseLifetimeError> ({});
+ }
}
lexer.skip_token ();
@@ -4345,7 +4395,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
@@ -4748,7 +4799,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 ();
@@ -4769,7 +4821,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 ();
@@ -4786,7 +4839,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 ();
@@ -5149,6 +5203,13 @@ Parser<ManagedTokenSource>::parse_trait_type (AST::AttrVec outer_attrs,
Identifier ident{ident_tok};
+ // Parse optional generic parameters for GATs (Generic Associated Types)
+ std::vector<std::unique_ptr<AST::GenericParam>> generic_params;
+ if (lexer.peek_token ()->get_id () == LEFT_ANGLE)
+ {
+ generic_params = parse_generic_params_in_angles ();
+ }
+
std::vector<std::unique_ptr<AST::TypeParamBound>> bounds;
// parse optional colon
@@ -5169,13 +5230,14 @@ Parser<ManagedTokenSource>::parse_trait_type (AST::AttrVec outer_attrs,
}
return std::unique_ptr<AST::TraitItemType> (
- new AST::TraitItemType (std::move (ident), std::move (bounds),
- std::move (outer_attrs), vis, locus));
+ new AST::TraitItemType (std::move (ident), std::move (generic_params),
+ std::move (bounds), std::move (outer_attrs), vis,
+ locus));
}
// Parses a constant trait item.
template <typename ManagedTokenSource>
-std::unique_ptr<AST::TraitItemConst>
+std::unique_ptr<AST::ConstantItem>
Parser<ManagedTokenSource>::parse_trait_const (AST::AttrVec outer_attrs)
{
location_t locus = lexer.peek_token ()->get_locus ();
@@ -5213,10 +5275,9 @@ Parser<ManagedTokenSource>::parse_trait_const (AST::AttrVec outer_attrs)
return nullptr;
}
- return std::unique_ptr<AST::TraitItemConst> (
- new AST::TraitItemConst (std::move (ident), std::move (type),
- std::move (const_body), std::move (outer_attrs),
- locus));
+ return std::unique_ptr<AST::ConstantItem> (new AST::ConstantItem (
+ std::move (ident), AST::Visibility::create_private (), std::move (type),
+ std::move (const_body), std::move (outer_attrs), locus));
}
/* Parses a struct "impl" item (both inherent impl and trait impl can be
@@ -5439,7 +5500,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 ();
@@ -5570,7 +5632,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
@@ -5769,7 +5832,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
@@ -5953,7 +6017,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 ();
@@ -6154,10 +6219,6 @@ Parser<ManagedTokenSource>::parse_let_stmt (AST::AttrVec outer_attrs,
expr = parse_expr ();
if (expr == nullptr)
{
- Error error (lexer.peek_token ()->get_locus (),
- "failed to parse expression in let statement");
- add_error (std::move (error));
-
skip_after_semicolon ();
return nullptr;
}
@@ -6242,7 +6303,7 @@ Parser<ManagedTokenSource>::parse_type_path ()
}
template <typename ManagedTokenSource>
-AST::GenericArg
+tl::optional<AST::GenericArg>
Parser<ManagedTokenSource>::parse_generic_arg ()
{
auto tok = lexer.peek_token ();
@@ -6250,7 +6311,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
@@ -6263,7 +6325,7 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
if (type)
return AST::GenericArg::create_type (std::move (type));
else
- return AST::GenericArg::create_error ();
+ return tl::nullopt;
}
else if (next_tok->get_id () == COLON)
{
@@ -6280,7 +6342,7 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
if (type)
return AST::GenericArg::create_type (std::move (type));
else
- return AST::GenericArg::create_error ();
+ return tl::nullopt;
}
lexer.skip_token ();
return AST::GenericArg::create_ambiguous (tok->get_str (),
@@ -6298,20 +6360,21 @@ 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)
return AST::GenericArg::create_type (std::move (type));
else
- return AST::GenericArg::create_error ();
+ return tl::nullopt;
}
}
if (!expr)
- return AST::GenericArg::create_error ();
+ return tl::nullopt;
return AST::GenericArg::create_const (std::move (expr));
}
@@ -6340,14 +6403,14 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
location_t locus = t->get_locus ();
while (!is_right_angle_tok (t->get_id ()))
{
- AST::Lifetime lifetime = parse_lifetime (false);
- if (lifetime.is_error ())
+ auto lifetime = parse_lifetime (false);
+ if (!lifetime)
{
// not necessarily an error
break;
}
- lifetime_args.push_back (std::move (lifetime));
+ lifetime_args.push_back (std::move (lifetime.value ()));
// if next token isn't comma, then it must be end of list
if (lexer.peek_token ()->get_id () != COMMA)
@@ -6376,9 +6439,9 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
break;
auto arg = parse_generic_arg ();
- if (!arg.is_error ())
+ if (arg)
{
- generic_args.emplace_back (std::move (arg));
+ generic_args.emplace_back (std::move (arg.value ()));
}
// FIXME: Do we need to break if we encounter an error?
@@ -6499,7 +6562,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 ();
@@ -6508,7 +6572,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);
@@ -6961,10 +7026,12 @@ Parser<ManagedTokenSource>::parse_self_param ()
// now test whether it has a lifetime
if (lexer.peek_token ()->get_id () == LIFETIME)
{
- lifetime = parse_lifetime (true);
-
// something went wrong somehow
- if (lifetime.is_error ())
+ if (auto parsed_lifetime = parse_lifetime (true))
+ {
+ lifetime = parsed_lifetime.value ();
+ }
+ else
{
Error error (lexer.peek_token ()->get_locus (),
"failed to parse lifetime in self param");
@@ -7055,16 +7122,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));
@@ -7072,7 +7137,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 ();
@@ -7080,14 +7145,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);
@@ -7153,9 +7218,9 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs,
// Parses a block expression, including the curly braces at start and end.
template <typename ManagedTokenSource>
std::unique_ptr<AST::BlockExpr>
-Parser<ManagedTokenSource>::parse_block_expr (AST::AttrVec outer_attrs,
- AST::LoopLabel label,
- location_t pratt_parsed_loc)
+Parser<ManagedTokenSource>::parse_block_expr (
+ AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label,
+ location_t pratt_parsed_loc)
{
location_t locus = pratt_parsed_loc;
if (locus == UNKNOWN_LOCATION)
@@ -7180,11 +7245,7 @@ Parser<ManagedTokenSource>::parse_block_expr (AST::AttrVec outer_attrs,
ExprOrStmt expr_or_stmt = parse_stmt_or_expr ();
if (expr_or_stmt.is_error ())
{
- Error error (
- t->get_locus (),
- "failed to parse statement or expression in block expression");
- add_error (std::move (error));
-
+ skip_after_end_block ();
return nullptr;
}
@@ -7225,6 +7286,51 @@ Parser<ManagedTokenSource>::parse_block_expr (AST::AttrVec outer_attrs,
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>
@@ -7505,6 +7611,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>
@@ -7519,12 +7653,10 @@ Parser<ManagedTokenSource>::parse_break_expr (AST::AttrVec outer_attrs,
skip_token (BREAK);
}
- // parse label (lifetime) if it exists - create dummy first
- AST::Lifetime label = AST::Lifetime::error ();
- if (lexer.peek_token ()->get_id () == LIFETIME)
- {
- label = parse_lifetime (false);
- }
+ auto parsed_label = parse_lifetime (false);
+ auto label = (parsed_label)
+ ? tl::optional<AST::Lifetime> (parsed_label.value ())
+ : tl::nullopt;
// parse break return expression if it exists
ParseRestrictions restrictions;
@@ -7550,12 +7682,10 @@ Parser<ManagedTokenSource>::parse_continue_expr (AST::AttrVec outer_attrs,
skip_token (CONTINUE);
}
- // parse label (lifetime) if it exists - create dummy first
- AST::Lifetime label = AST::Lifetime::error ();
- if (lexer.peek_token ()->get_id () == LIFETIME)
- {
- label = parse_lifetime (false);
- }
+ auto parsed_label = parse_lifetime (false);
+ auto label = (parsed_label)
+ ? tl::optional<AST::Lifetime> (parsed_label.value ())
+ : tl::nullopt;
return std::unique_ptr<AST::ContinueExpr> (
new AST::ContinueExpr (std::move (label), std::move (outer_attrs), locus));
@@ -7563,14 +7693,15 @@ Parser<ManagedTokenSource>::parse_continue_expr (AST::AttrVec outer_attrs,
// Parses a loop label used in loop expressions.
template <typename ManagedTokenSource>
-AST::LoopLabel
+tl::expected<AST::LoopLabel, ParseLoopLabelError>
Parser<ManagedTokenSource>::parse_loop_label (const_TokenPtr tok)
{
// parse lifetime - if doesn't exist, assume no label
if (tok->get_id () != LIFETIME)
{
// not necessarily an error
- return AST::LoopLabel::error ();
+ return tl::unexpected<ParseLoopLabelError> (
+ ParseLoopLabelError::NOT_LOOP_LABEL);
}
/* FIXME: check for named lifetime requirement here? or check in semantic
* analysis phase? */
@@ -7579,10 +7710,12 @@ Parser<ManagedTokenSource>::parse_loop_label (const_TokenPtr tok)
if (!skip_token (COLON))
{
// skip somewhere?
- return AST::LoopLabel::error ();
+ return tl::unexpected<ParseLoopLabelError> (
+ ParseLoopLabelError::MISSING_COLON);
}
- return AST::LoopLabel (std::move (label), tok->get_locus ());
+ return tl::expected<AST::LoopLabel, ParseLoopLabelError> (
+ AST::LoopLabel (std::move (label), tok->get_locus ()));
}
/* Parses an if expression of any kind, including with else, else if, else if
@@ -7635,14 +7768,7 @@ Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs,
// parse required block expr
std::unique_ptr<AST::BlockExpr> if_body = parse_block_expr ();
if (if_body == nullptr)
- {
- Error error (lexer.peek_token ()->get_locus (),
- "failed to parse if body block expression in if expression");
- add_error (std::move (error));
-
- // skip somewhere?
- return nullptr;
- }
+ return nullptr;
// branch to parse end or else (and then else, else if, or else if let)
if (lexer.peek_token ()->get_id () != ELSE)
@@ -7663,7 +7789,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 ();
@@ -7684,7 +7811,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)
@@ -7845,7 +7973,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 ();
@@ -7867,7 +7996,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)
@@ -7935,16 +8065,16 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs,
template <typename ManagedTokenSource>
std::unique_ptr<AST::LoopExpr>
Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs,
- AST::LoopLabel label,
+ tl::optional<AST::LoopLabel> label,
location_t pratt_parsed_loc)
{
location_t locus = pratt_parsed_loc;
if (locus == UNKNOWN_LOCATION)
{
- if (label.is_error ())
- locus = lexer.peek_token ()->get_locus ();
+ if (label)
+ locus = label->get_locus ();
else
- locus = label.get_locus ();
+ locus = lexer.peek_token ()->get_locus ();
if (!skip_token (LOOP))
{
@@ -7954,20 +8084,14 @@ Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs,
}
else
{
- if (!label.is_error ())
- locus = label.get_locus ();
+ if (label)
+ locus = label->get_locus ();
}
// parse loop body, which is required
std::unique_ptr<AST::BlockExpr> loop_body = parse_block_expr ();
if (loop_body == nullptr)
- {
- Error error (lexer.peek_token ()->get_locus (),
- "could not parse loop body in (infinite) loop expression");
- add_error (std::move (error));
-
- return nullptr;
- }
+ return nullptr;
return std::unique_ptr<AST::LoopExpr> (
new AST::LoopExpr (std::move (loop_body), locus, std::move (label),
@@ -7978,17 +8102,17 @@ Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs,
* via parse_labelled_loop_expr, which would call this. */
template <typename ManagedTokenSource>
std::unique_ptr<AST::WhileLoopExpr>
-Parser<ManagedTokenSource>::parse_while_loop_expr (AST::AttrVec outer_attrs,
- AST::LoopLabel label,
- location_t pratt_parsed_loc)
+Parser<ManagedTokenSource>::parse_while_loop_expr (
+ AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label,
+ location_t pratt_parsed_loc)
{
location_t locus = pratt_parsed_loc;
if (locus == UNKNOWN_LOCATION)
{
- if (label.is_error ())
- locus = lexer.peek_token ()->get_locus ();
+ if (label)
+ locus = label->get_locus ();
else
- locus = label.get_locus ();
+ locus = lexer.peek_token ()->get_locus ();
if (!skip_token (WHILE))
{
@@ -7998,8 +8122,8 @@ Parser<ManagedTokenSource>::parse_while_loop_expr (AST::AttrVec outer_attrs,
}
else
{
- if (!label.is_error ())
- locus = label.get_locus ();
+ if (label)
+ locus = label->get_locus ();
}
// ensure it isn't a while let loop
@@ -8051,14 +8175,14 @@ Parser<ManagedTokenSource>::parse_while_loop_expr (AST::AttrVec outer_attrs,
* parsed via parse_labelled_loop_expr, which would call this. */
template <typename ManagedTokenSource>
std::unique_ptr<AST::WhileLetLoopExpr>
-Parser<ManagedTokenSource>::parse_while_let_loop_expr (AST::AttrVec outer_attrs,
- AST::LoopLabel label)
+Parser<ManagedTokenSource>::parse_while_let_loop_expr (
+ AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label)
{
location_t locus = UNKNOWN_LOCATION;
- if (label.is_error ())
- locus = lexer.peek_token ()->get_locus ();
+ if (label)
+ locus = label->get_locus ();
else
- locus = label.get_locus ();
+ locus = lexer.peek_token ()->get_locus ();
maybe_skip_token (WHILE);
/* check for possible accidental recognition of a while loop as a while let
@@ -8079,7 +8203,14 @@ Parser<ManagedTokenSource>::parse_while_let_loop_expr (AST::AttrVec outer_attrs,
// parse predicate patterns
std::vector<std::unique_ptr<AST::Pattern>> predicate_patterns
= parse_match_arm_patterns (EQUAL);
- // TODO: have to ensure that there is at least 1 pattern?
+ // ensure that there is at least 1 pattern
+ if (predicate_patterns.empty ())
+ {
+ Error error (lexer.peek_token ()->get_locus (),
+ "should be at least 1 pattern");
+ add_error (std::move (error));
+ return nullptr;
+ }
if (!skip_token (EQUAL))
{
@@ -8125,14 +8256,14 @@ Parser<ManagedTokenSource>::parse_while_let_loop_expr (AST::AttrVec outer_attrs,
* parse_labelled_loop_expr, which would call this. */
template <typename ManagedTokenSource>
std::unique_ptr<AST::ForLoopExpr>
-Parser<ManagedTokenSource>::parse_for_loop_expr (AST::AttrVec outer_attrs,
- AST::LoopLabel label)
+Parser<ManagedTokenSource>::parse_for_loop_expr (
+ AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label)
{
location_t locus = UNKNOWN_LOCATION;
- if (label.is_error ())
- locus = lexer.peek_token ()->get_locus ();
+ if (label)
+ locus = label->get_locus ();
else
- locus = label.get_locus ();
+ locus = lexer.peek_token ()->get_locus ();
maybe_skip_token (FOR);
// parse pattern, which is required
@@ -8210,8 +8341,9 @@ Parser<ManagedTokenSource>::parse_labelled_loop_expr (const_TokenPtr tok,
}
// parse loop label (required)
- AST::LoopLabel label = parse_loop_label (tok);
- if (label.is_error ())
+ // TODO: Convert this return type to tl::expected instead of tl::optional
+ auto parsed_label = parse_loop_label (tok);
+ if (!parsed_label)
{
Error error (lexer.peek_token ()->get_locus (),
"failed to parse loop label in labelled loop expr");
@@ -8221,6 +8353,10 @@ Parser<ManagedTokenSource>::parse_labelled_loop_expr (const_TokenPtr tok,
return nullptr;
}
+ auto label = parsed_label
+ ? tl::optional<AST::LoopLabel> (parsed_label.value ())
+ : tl::nullopt;
+
// branch on next token
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
@@ -8914,7 +9050,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 ())
@@ -8943,7 +9080,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
@@ -8959,7 +9097,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
@@ -8989,7 +9128,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 ();
@@ -9015,7 +9155,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;
@@ -9100,14 +9241,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));
}
@@ -9135,7 +9270,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)
@@ -9388,7 +9524,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
@@ -9598,8 +9735,12 @@ Parser<ManagedTokenSource>::parse_reference_type_inner (location_t locus)
AST::Lifetime lifetime = AST::Lifetime::elided ();
if (lexer.peek_token ()->get_id () == LIFETIME)
{
- lifetime = parse_lifetime (true);
- if (lifetime.is_error ())
+ auto parsed_lifetime = parse_lifetime (true);
+ if (parsed_lifetime)
+ {
+ lifetime = parsed_lifetime.value ();
+ }
+ else
{
Error error (lexer.peek_token ()->get_locus (),
"failed to parse lifetime in reference type");
@@ -9730,13 +9871,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");
@@ -9751,7 +9894,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
@@ -9781,7 +9925,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 ())
@@ -9822,7 +9967,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
@@ -9850,7 +9996,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 ();
@@ -9934,14 +10081,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)
@@ -10204,7 +10349,7 @@ Parser<ManagedTokenSource>::parse_literal_or_range_pattern ()
return std::unique_ptr<AST::LiteralPattern> (
new AST::LiteralPattern (range_lower->get_str (), type,
range_lower->get_locus (),
- range_lower->get_type_hint ()));
+ range_lower->get_type_hint (), has_minus));
}
}
@@ -10282,7 +10427,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 ())
@@ -10298,7 +10444,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 ();
@@ -10340,16 +10487,22 @@ Parser<ManagedTokenSource>::parse_pattern ()
return first;
std::vector<std::unique_ptr<AST::Pattern>> alts;
- alts.push_back (std::move (first));
+ if (first != nullptr)
+ alts.push_back (std::move (first));
do
{
lexer.skip_token ();
- alts.push_back (parse_pattern_no_alt ());
+ auto follow = parse_pattern_no_alt ();
+ if (follow != nullptr)
+ alts.push_back (std::move (follow));
}
while (lexer.peek_token ()->get_id () == PIPE);
+ if (alts.empty ())
+ return nullptr;
+
/* alternates */
return std::unique_ptr<AST::Pattern> (
new AST::AltPattern (std::move (alts), start_locus));
@@ -10443,7 +10596,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 ();
@@ -10479,7 +10633,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 ();
@@ -10488,7 +10643,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 ();
@@ -10506,7 +10662,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 ();
@@ -10531,7 +10688,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 ();
@@ -10663,9 +10821,9 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern ()
return nullptr;
}
- // create ranged tuple pattern items with only upper items
- std::unique_ptr<AST::TuplePatternItemsRanged> items (
- new AST::TuplePatternItemsRanged (
+ // create tuple pattern items with only upper pattern items
+ std::unique_ptr<AST::TuplePatternItemsHasRest> items (
+ new AST::TuplePatternItemsHasRest (
std::vector<std::unique_ptr<AST::Pattern>> (), std::move (patterns)));
return std::unique_ptr<AST::TuplePattern> (
new AST::TuplePattern (std::move (items), paren_locus));
@@ -10673,8 +10831,8 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern ()
else if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
{
skip_token (RIGHT_PAREN);
- auto items = std::unique_ptr<AST::TuplePatternItemsMultiple> (
- new AST::TuplePatternItemsMultiple (
+ auto items = std::unique_ptr<AST::TuplePatternItemsNoRest> (
+ new AST::TuplePatternItemsNoRest (
std::vector<std::unique_ptr<AST::Pattern>> ()));
return std::unique_ptr<AST::TuplePattern> (
new AST::TuplePattern (std::move (items), paren_locus));
@@ -10701,7 +10859,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 ();
@@ -10737,8 +10896,8 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern ()
// non-ranged tuple pattern
lexer.skip_token ();
- std::unique_ptr<AST::TuplePatternItemsMultiple> items (
- new AST::TuplePatternItemsMultiple (std::move (patterns)));
+ std::unique_ptr<AST::TuplePatternItemsNoRest> items (
+ new AST::TuplePatternItemsNoRest (std::move (patterns)));
return std::unique_ptr<AST::TuplePattern> (
new AST::TuplePattern (std::move (items), paren_locus));
}
@@ -10778,9 +10937,9 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern ()
return nullptr;
}
- std::unique_ptr<AST::TuplePatternItemsRanged> items (
- new AST::TuplePatternItemsRanged (std::move (patterns),
- std::move (upper_patterns)));
+ std::unique_ptr<AST::TuplePatternItemsHasRest> items (
+ new AST::TuplePatternItemsHasRest (std::move (patterns),
+ std::move (upper_patterns)));
return std::unique_ptr<AST::TuplePattern> (
new AST::TuplePattern (std::move (items), paren_locus));
}
@@ -10814,27 +10973,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)
@@ -10845,6 +11024,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)
@@ -10855,7 +11051,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 ();
}
@@ -10865,8 +11061,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
@@ -10913,7 +11122,7 @@ Parser<ManagedTokenSource>::parse_identifier_pattern ()
lexer.skip_token ();
// parse required pattern to bind
- bind_pattern = parse_pattern ();
+ bind_pattern = parse_pattern_no_alt ();
if (bind_pattern == nullptr)
{
Error error (lexer.peek_token ()->get_locus (),
@@ -10958,7 +11167,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 ();
@@ -10991,7 +11201,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 ();
@@ -11012,7 +11223,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 ());
@@ -11029,14 +11241,16 @@ 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 ())
{
// identifier with pattern bind
lexer.skip_token ();
- std::unique_ptr<AST::Pattern> bind_pattern = parse_pattern ();
+ std::unique_ptr<AST::Pattern> bind_pattern
+ = parse_pattern_no_alt ();
if (bind_pattern == nullptr)
{
Error error (
@@ -11121,9 +11335,9 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items ()
rust_debug (
"finished parsing tuple struct items ranged (upper/none only)");
- return std::unique_ptr<AST::TupleStructItemsRange> (
- new AST::TupleStructItemsRange (std::move (lower_patterns),
- std::move (upper_patterns)));
+ return std::unique_ptr<AST::TupleStructItemsHasRest> (
+ new AST::TupleStructItemsHasRest (std::move (lower_patterns),
+ std::move (upper_patterns)));
}
// has at least some lower patterns
@@ -11165,9 +11379,10 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items ()
switch (t->get_id ())
{
case RIGHT_PAREN:
- return std::unique_ptr<AST::TupleStructItemsNoRange> (
- new AST::TupleStructItemsNoRange (std::move (lower_patterns)));
- case DOT_DOT: {
+ return std::unique_ptr<AST::TupleStructItemsNoRest> (
+ new AST::TupleStructItemsNoRest (std::move (lower_patterns)));
+ case DOT_DOT:
+ {
// has an upper range that must be parsed separately
lexer.skip_token ();
@@ -11197,9 +11412,9 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items ()
t = lexer.peek_token ();
}
- return std::unique_ptr<AST::TupleStructItemsRange> (
- new AST::TupleStructItemsRange (std::move (lower_patterns),
- std::move (upper_patterns)));
+ return std::unique_ptr<AST::TupleStructItemsHasRest> (
+ new AST::TupleStructItemsHasRest (std::move (lower_patterns),
+ std::move (upper_patterns)));
}
default:
// error
@@ -11219,7 +11434,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems ()
std::vector<std::unique_ptr<AST::StructPatternField>> fields;
AST::AttrVec etc_attrs;
- bool has_etc = false;
+ bool has_rest = false;
// try parsing struct pattern fields
const_TokenPtr t = lexer.peek_token ();
@@ -11232,7 +11447,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems ()
{
lexer.skip_token ();
etc_attrs = std::move (outer_attrs);
- has_etc = true;
+ has_rest = true;
break;
}
@@ -11257,7 +11472,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems ()
t = lexer.peek_token ();
}
- if (has_etc)
+ if (has_rest)
return AST::StructPatternElements (std::move (fields),
std::move (etc_attrs));
else
@@ -11287,7 +11502,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 ());
@@ -11321,7 +11537,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 ();
@@ -11346,7 +11563,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 ();
@@ -11365,7 +11583,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)
@@ -11437,7 +11656,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)));
@@ -11455,42 +11675,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)));
@@ -11535,7 +11761,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;
@@ -11544,6 +11771,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
std::unique_ptr<AST::MacroInvocation> invoc
= parse_macro_invocation_partial (std::move (path),
std::move (outer_attrs));
+ if (invoc == nullptr)
+ return ExprOrStmt::create_error ();
if (restrictions.consume_semi && maybe_skip_token (SEMICOLON))
{
@@ -11555,9 +11784,12 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
TokenId after_macro = lexer.peek_token ()->get_id ();
- if (invoc->get_invoc_data ().get_delim_tok_tree ().get_delim_type ()
- == AST::CURLY
- && after_macro != DOT && after_macro != QUESTION_MARK)
+ AST::DelimType delim_type = invoc->get_invoc_data ()
+ .get_delim_tok_tree ()
+ .get_delim_type ();
+
+ if (delim_type == AST::CURLY && after_macro != DOT
+ && after_macro != QUESTION_MARK)
{
rust_debug ("braced macro statement");
return ExprOrStmt (
@@ -11659,7 +11891,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 ();
@@ -11704,11 +11937,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));
}
@@ -11899,7 +12133,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 ();
@@ -11930,20 +12164,14 @@ Parser<ManagedTokenSource>::parse_expr (int right_binding_power,
return nullptr;
}
- if (current_token->get_id () == LEFT_SHIFT)
- {
- lexer.split_current_token (LEFT_ANGLE, LEFT_ANGLE);
- current_token = lexer.peek_token ();
- }
-
- lexer.skip_token ();
-
ParseRestrictions null_denotation_restrictions = restrictions;
null_denotation_restrictions.expr_can_be_stmt = false;
// parse null denotation (unary part of expression)
std::unique_ptr<AST::Expr> expr
- = null_denotation (current_token, {}, null_denotation_restrictions);
+ = null_denotation ({}, null_denotation_restrictions);
+ if (expr == nullptr)
+ return nullptr;
return left_denotations (std::move (expr), right_binding_power,
std::move (outer_attrs), restrictions);
@@ -12011,8 +12239,7 @@ Parser<ManagedTokenSource>::parse_expr (AST::AttrVec outer_attrs,
/* Determines action to take when finding token at beginning of expression. */
template <typename ManagedTokenSource>
std::unique_ptr<AST::Expr>
-Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
- AST::AttrVec outer_attrs,
+Parser<ManagedTokenSource>::null_denotation (AST::AttrVec outer_attrs,
ParseRestrictions restrictions)
{
/* note: tok is previous character in input stream, not current one, as
@@ -12022,6 +12249,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
* denotation and then a left denotation), null denotations handle primaries
* and unary operands (but only prefix unary operands) */
+ auto tok = lexer.peek_token ();
+
switch (tok->get_id ())
{
case IDENTIFIER:
@@ -12029,27 +12258,27 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
case SELF_ALIAS:
case DOLLAR_SIGN:
case CRATE:
- case SUPER: {
+ case SUPER:
+ case SCOPE_RESOLUTION:
+ {
// DEBUG
rust_debug ("beginning null denotation identifier handling");
/* best option: parse as path, then extract identifier, macro,
* struct/enum, or just path info from it */
- AST::PathInExpression path = parse_path_in_expression_pratt (tok);
+ AST::PathInExpression path = parse_path_in_expression ();
return null_denotation_path (std::move (path), std::move (outer_attrs),
restrictions);
}
- 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 "
- "have not written handling for it");
- add_error (std::move (error));
-
- return nullptr;
- }
default:
+ if (tok->get_id () == LEFT_SHIFT)
+ {
+ lexer.split_current_token (LEFT_ANGLE, LEFT_ANGLE);
+ tok = lexer.peek_token ();
+ }
+
+ lexer.skip_token ();
return null_denotation_not_path (std::move (tok), std::move (outer_attrs),
restrictions);
}
@@ -12082,7 +12311,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
@@ -12158,7 +12388,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
@@ -12216,23 +12447,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)
@@ -12259,7 +12491,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)
@@ -12284,7 +12517,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;
@@ -12297,7 +12531,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;
@@ -12354,7 +12589,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;
@@ -12393,6 +12629,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 ());
@@ -12400,8 +12639,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
return parse_continue_expr (std::move (outer_attrs), tok->get_locus ());
case LEFT_CURLY:
// ok - this is an expression with block for once.
- return parse_block_expr (std::move (outer_attrs),
- AST::LoopLabel::error (), tok->get_locus ());
+ return parse_block_expr (std::move (outer_attrs), tl::nullopt,
+ tok->get_locus ());
case IF:
// if or if let, so more lookahead to find out
if (lexer.peek_token ()->get_id () == LET)
@@ -12417,7 +12656,7 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
case LIFETIME:
return parse_labelled_loop_expr (tok, std::move (outer_attrs));
case LOOP:
- return parse_loop_expr (std::move (outer_attrs), AST::LoopLabel::error (),
+ return parse_loop_expr (std::move (outer_attrs), tl::nullopt,
tok->get_locus ());
case WHILE:
if (lexer.peek_token ()->get_id () == LET)
@@ -12426,13 +12665,11 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
}
else
{
- return parse_while_loop_expr (std::move (outer_attrs),
- AST::LoopLabel::error (),
+ return parse_while_loop_expr (std::move (outer_attrs), tl::nullopt,
tok->get_locus ());
}
case FOR:
- return parse_for_loop_expr (std::move (outer_attrs),
- AST::LoopLabel::error ());
+ return parse_for_loop_expr (std::move (outer_attrs), tl::nullopt);
case MATCH_KW:
// also an expression with block
return parse_match_expr (std::move (outer_attrs), tok->get_locus ());
@@ -12450,6 +12687,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 (),
@@ -12472,8 +12712,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> (
@@ -12727,7 +12968,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 */
@@ -12801,12 +13043,6 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok,
// array or slice index expression (pseudo binary infix)
return parse_index_expr (tok, std::move (left), std::move (outer_attrs),
restrictions);
- case FLOAT_LITERAL:
- /* HACK: get around lexer mis-identifying '.0' or '.1' or whatever as a
- * float literal - TODO does this happen anymore? It shouldn't. */
- return parse_tuple_index_expr_float (tok, std::move (left),
- std::move (outer_attrs),
- restrictions);
default:
add_error (Error (tok->get_locus (),
"found unexpected token %qs in left denotation",
@@ -14043,7 +14279,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
@@ -14201,119 +14438,6 @@ Parser<ManagedTokenSource>::parse_struct_expr_tuple_partial (
std::move (outer_attrs), path_locus));
}
-/* Parses a path in expression with the first token passed as a parameter (as
- * it is skipped in token stream). Note that this only parses segment-first
- * paths, not global ones. */
-template <typename ManagedTokenSource>
-AST::PathInExpression
-Parser<ManagedTokenSource>::parse_path_in_expression_pratt (const_TokenPtr tok)
-{
- // HACK-y way of making up for pratt-parsing consuming first token
-
- // DEBUG
- rust_debug ("current peek token when starting path pratt parse: '%s'",
- lexer.peek_token ()->get_token_description ());
-
- // create segment vector
- std::vector<AST::PathExprSegment> segments;
-
- std::string initial_str;
-
- switch (tok->get_id ())
- {
- case IDENTIFIER:
- initial_str = tok->get_str ();
- break;
- case SUPER:
- initial_str = Values::Keywords::SUPER;
- break;
- case SELF:
- initial_str = Values::Keywords::SELF;
- break;
- case SELF_ALIAS:
- initial_str = Values::Keywords::SELF_ALIAS;
- break;
- case CRATE:
- initial_str = Values::Keywords::CRATE;
- break;
- case DOLLAR_SIGN:
- if (lexer.peek_token ()->get_id () == CRATE)
- {
- initial_str = "$crate";
- break;
- }
- gcc_fallthrough ();
- default:
- add_error (Error (tok->get_locus (),
- "unrecognised token %qs in path in expression",
- tok->get_token_description ()));
-
- return AST::PathInExpression::create_error ();
- }
-
- // parse required initial segment
- AST::PathExprSegment initial_segment (initial_str, tok->get_locus ());
- // parse generic args (and turbofish), if they exist
- /* use lookahead to determine if they actually exist (don't want to
- * accidently parse over next ident segment) */
- if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION
- && lexer.peek_token (1)->get_id () == LEFT_ANGLE)
- {
- // skip scope resolution
- lexer.skip_token ();
-
- AST::GenericArgs generic_args = parse_path_generic_args ();
-
- initial_segment
- = AST::PathExprSegment (AST::PathIdentSegment (initial_str,
- tok->get_locus ()),
- tok->get_locus (), std::move (generic_args));
- }
- if (initial_segment.is_error ())
- {
- // skip after somewhere?
- // don't necessarily throw error but yeah
-
- // DEBUG
- rust_debug ("initial segment is error - returning null");
-
- return AST::PathInExpression::create_error ();
- }
- segments.push_back (std::move (initial_segment));
-
- // parse optional segments (as long as scope resolution operator exists)
- const_TokenPtr t = lexer.peek_token ();
- while (t->get_id () == SCOPE_RESOLUTION)
- {
- // skip scope resolution operator
- lexer.skip_token ();
-
- // parse the actual segment - it is an error if it doesn't exist now
- AST::PathExprSegment segment = parse_path_expr_segment ();
- if (segment.is_error ())
- {
- // skip after somewhere?
- Error error (t->get_locus (),
- "could not parse path expression segment");
- add_error (std::move (error));
-
- return AST::PathInExpression::create_error ();
- }
-
- segments.push_back (std::move (segment));
-
- t = lexer.peek_token ();
- }
-
- // DEBUG:
- rust_debug (
- "current token (just about to return path to null denotation): '%s'",
- lexer.peek_token ()->get_token_description ());
-
- return AST::PathInExpression (std::move (segments), {}, tok->get_locus (),
- false);
-}
-
// Parses a closure expression with pratt parsing (from null denotation).
template <typename ManagedTokenSource>
std::unique_ptr<AST::ClosureExpr>
@@ -14340,7 +14464,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 ();
@@ -14450,35 +14575,6 @@ Parser<ManagedTokenSource>::parse_closure_expr_pratt (const_TokenPtr tok,
}
}
-/* Parses a tuple index expression (pratt-parsed) from a 'float' token as a
- * result of lexer misidentification. */
-template <typename ManagedTokenSource>
-std::unique_ptr<AST::TupleIndexExpr>
-Parser<ManagedTokenSource>::parse_tuple_index_expr_float (
- const_TokenPtr tok, std::unique_ptr<AST::Expr> tuple_expr,
- AST::AttrVec outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED)
-{
- // only works on float literals
- if (tok->get_id () != FLOAT_LITERAL)
- return nullptr;
-
- // DEBUG:
- rust_debug ("exact string form of float: '%s'", tok->get_str ().c_str ());
-
- // get float string and remove dot and initial 0
- std::string index_str = tok->get_str ();
- index_str.erase (index_str.begin ());
-
- // get int from string
- int index = atoi (index_str.c_str ());
-
- location_t locus = tuple_expr->get_locus ();
-
- return std::unique_ptr<AST::TupleIndexExpr> (
- new AST::TupleIndexExpr (std::move (tuple_expr), index,
- std::move (outer_attrs), locus));
-}
-
// Returns true if the next token is END, ELSE, or EOF;
template <typename ManagedTokenSource>
bool
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 6c50ba9..7b40463 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"
@@ -25,6 +26,33 @@ along with GCC; see the file COPYING3. If not see
#include "expected.h"
namespace Rust {
+
+class ParseLifetimeParamError
+{
+};
+
+class ParseLifetimeError
+{
+};
+
+enum class AnonConstError
+{
+ InvalidSizeExpr,
+};
+
+enum class ParseLoopLabelError
+{
+ NOT_LOOP_LABEL,
+ MISSING_COLON,
+};
+
+enum class ParseSelfError
+{
+ SELF_PTR,
+ PARSING,
+ NOT_SELF,
+};
+
/* HACK: used to resolve the expression-or-statement problem at the end of a
* block by allowing either to be returned (technically). Tagged union would
* probably take up the same amount of space. */
@@ -95,12 +123,6 @@ struct ParseRestrictions
bool allow_close_after_expr_stmt = false;
};
-enum ParseSelfError
-{
- SELF_PTR,
- PARSING,
- NOT_SELF,
-};
// Parser implementation for gccrs.
// TODO: if updated to C++20, ManagedTokenSource would be useful as a concept
template <typename ManagedTokenSource> class Parser
@@ -148,9 +170,15 @@ public:
std::unique_ptr<AST::BlockExpr>
parse_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
- AST::LoopLabel label = AST::LoopLabel::error (),
+ 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 ();
@@ -184,6 +212,11 @@ public:
std::unique_ptr<AST::MacroInvocation>
parse_macro_invocation (AST::AttrVec outer_attrs);
+ /*
+ * This has to be public for parsing expressions with outer attributes
+ */
+ AST::AttrVec parse_outer_attributes ();
+
private:
void skip_after_semicolon ();
void skip_after_end ();
@@ -200,7 +233,6 @@ private:
// AST-related stuff - maybe move or something?
AST::Attribute parse_inner_attribute ();
- AST::AttrVec parse_outer_attributes ();
AST::Attribute parse_outer_attribute ();
std::unique_ptr<AST::AttrInput> parse_attr_input ();
std::tuple<AST::SimplePath, std::unique_ptr<AST::AttrInput>, location_t>
@@ -208,11 +240,11 @@ 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 ();
- AST::GenericArg parse_generic_arg ();
+ tl::optional<AST::GenericArg> parse_generic_arg ();
AST::GenericArgs parse_path_generic_args ();
AST::GenericArgsBinding parse_generic_args_binding ();
AST::TypePathFunction parse_type_path_function (location_t locus);
@@ -277,7 +309,8 @@ private:
ParseFunction parsing_function, EndTokenPred is_end_token,
std::string error_msg = "failed to parse generic param in generic params")
-> std::vector<decltype (parsing_function ())>;
- AST::LifetimeParam parse_lifetime_param ();
+ tl::expected<AST::LifetimeParam, ParseLifetimeParamError>
+ parse_lifetime_param ();
std::vector<std::unique_ptr<AST::TypeParam>> parse_type_params ();
template <typename EndTokenPred>
std::vector<std::unique_ptr<AST::TypeParam>>
@@ -306,7 +339,8 @@ private:
std::vector<AST::Lifetime> parse_lifetime_bounds ();
template <typename EndTokenPred>
std::vector<AST::Lifetime> parse_lifetime_bounds (EndTokenPred is_end_token);
- AST::Lifetime parse_lifetime (bool allow_elided);
+ tl::expected<AST::Lifetime, ParseLifetimeError>
+ parse_lifetime (bool allow_elided);
AST::Lifetime lifetime_from_token (const_TokenPtr tok);
std::unique_ptr<AST::ExternalTypeItem>
parse_external_type_item (AST::Visibility vis, AST::AttrVec outer_attrs);
@@ -338,7 +372,7 @@ private:
AST::AttrVec outer_attrs);
std::unique_ptr<AST::TraitItemType>
parse_trait_type (AST::AttrVec outer_attrs, AST::Visibility);
- std::unique_ptr<AST::TraitItemConst>
+ std::unique_ptr<AST::ConstantItem>
parse_trait_const (AST::AttrVec outer_attrs);
tl::expected<std::unique_ptr<AST::Param>, ParseSelfError> parse_self_param ();
@@ -363,7 +397,7 @@ private:
AST::AttrVec outer_attrs = AST::AttrVec (),
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::Expr>
- null_denotation (const_TokenPtr t, AST::AttrVec outer_attrs = AST::AttrVec (),
+ null_denotation (AST::AttrVec outer_attrs = AST::AttrVec (),
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::Expr>
null_denotation_path (AST::PathInExpression path, AST::AttrVec outer_attrs,
@@ -568,7 +602,6 @@ private:
std::unique_ptr<AST::CallExpr>
parse_struct_expr_tuple_partial (AST::PathInExpression path,
AST::AttrVec outer_attrs);
- AST::PathInExpression parse_path_in_expression_pratt (const_TokenPtr tok);
std::unique_ptr<AST::ClosureExpr>
parse_closure_expr_pratt (const_TokenPtr tok,
AST::AttrVec outer_attrs = AST::AttrVec ());
@@ -588,18 +621,18 @@ private:
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
std::unique_ptr<AST::LoopExpr>
parse_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
- AST::LoopLabel label = AST::LoopLabel::error (),
+ tl::optional<AST::LoopLabel> label = tl::nullopt,
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
std::unique_ptr<AST::WhileLoopExpr>
parse_while_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
- AST::LoopLabel label = AST::LoopLabel::error (),
+ tl::optional<AST::LoopLabel> label = tl::nullopt,
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
std::unique_ptr<AST::WhileLetLoopExpr>
parse_while_let_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
- AST::LoopLabel label = AST::LoopLabel::error ());
+ tl::optional<AST::LoopLabel> label = tl::nullopt);
std::unique_ptr<AST::ForLoopExpr>
parse_for_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
- AST::LoopLabel label = AST::LoopLabel::error ());
+ tl::optional<AST::LoopLabel> label = tl::nullopt);
std::unique_ptr<AST::MatchExpr>
parse_match_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
@@ -609,7 +642,8 @@ private:
std::unique_ptr<AST::Expr> parse_labelled_loop_expr (const_TokenPtr tok,
AST::AttrVec outer_attrs
= AST::AttrVec ());
- AST::LoopLabel parse_loop_label (const_TokenPtr tok);
+ tl::expected<AST::LoopLabel, ParseLoopLabelError>
+ parse_loop_label (const_TokenPtr tok);
std::unique_ptr<AST::AsyncBlockExpr>
parse_async_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
std::unique_ptr<AST::GroupedExpr> parse_grouped_expr (AST::AttrVec outer_attrs
@@ -627,6 +661,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);
@@ -745,11 +782,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 struct ::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.
@@ -759,12 +800,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
deleted file mode 100644
index 6c35a22..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-base.cc
+++ /dev/null
@@ -1,663 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-ast-resolve-base.h"
-#include "rust-ast-resolve-expr.h"
-#include "rust-ast-resolve-path.h"
-#include "rust-item.h"
-#include "rust-path.h"
-
-namespace Rust {
-namespace Resolver {
-
-bool
-ResolverBase::resolve_visibility (const AST::Visibility &vis)
-{
- if (vis.has_path ())
- {
- auto path = vis.get_path ();
- ResolvePath::go (path);
-
- // Do we need to lookup something here?
- // Is it just about resolving the names correctly so we can look them up
- // later?
- }
-
- return true;
-}
-
-// Default visitors implementations
-
-void
-ResolverBase::visit (AST::Token &)
-{}
-
-void
-ResolverBase::visit (AST::DelimTokenTree &)
-{}
-
-void
-ResolverBase::visit (AST::AttrInputMetaItemContainer &)
-{}
-
-void
-ResolverBase::visit (AST::IdentifierExpr &)
-{}
-
-void
-ResolverBase::visit (AST::Lifetime &)
-{}
-
-void
-ResolverBase::visit (AST::LifetimeParam &)
-{}
-
-void
-ResolverBase::visit (AST::ConstGenericParam &)
-{}
-
-void
-ResolverBase::visit (AST::PathInExpression &)
-{}
-
-void
-ResolverBase::visit (AST::TypePathSegment &)
-{}
-
-void
-ResolverBase::visit (AST::TypePathSegmentGeneric &)
-{}
-
-void
-ResolverBase::visit (AST::TypePathSegmentFunction &)
-{}
-
-void
-ResolverBase::visit (AST::TypePath &)
-{}
-
-void
-ResolverBase::visit (AST::QualifiedPathInExpression &)
-{}
-
-void
-ResolverBase::visit (AST::QualifiedPathInType &)
-{}
-
-void
-ResolverBase::visit (AST::LiteralExpr &)
-{}
-
-void
-ResolverBase::visit (AST::AttrInputLiteral &)
-{}
-
-void
-ResolverBase::visit (AST::AttrInputMacro &)
-{}
-
-void
-ResolverBase::visit (AST::MetaItemLitExpr &)
-{}
-
-void
-ResolverBase::visit (AST::MetaItemPathLit &)
-{}
-
-void
-ResolverBase::visit (AST::BorrowExpr &)
-{}
-
-void
-ResolverBase::visit (AST::DereferenceExpr &)
-{}
-
-void
-ResolverBase::visit (AST::ErrorPropagationExpr &)
-{}
-
-void
-ResolverBase::visit (AST::NegationExpr &)
-{}
-
-void
-ResolverBase::visit (AST::ArithmeticOrLogicalExpr &)
-{}
-
-void
-ResolverBase::visit (AST::ComparisonExpr &)
-{}
-
-void
-ResolverBase::visit (AST::LazyBooleanExpr &)
-{}
-
-void
-ResolverBase::visit (AST::TypeCastExpr &)
-{}
-
-void
-ResolverBase::visit (AST::AssignmentExpr &)
-{}
-
-void
-ResolverBase::visit (AST::CompoundAssignmentExpr &)
-{}
-
-void
-ResolverBase::visit (AST::GroupedExpr &)
-{}
-
-void
-ResolverBase::visit (AST::ArrayElemsValues &)
-{}
-
-void
-ResolverBase::visit (AST::ArrayElemsCopied &)
-{}
-
-void
-ResolverBase::visit (AST::ArrayExpr &)
-{}
-
-void
-ResolverBase::visit (AST::ArrayIndexExpr &)
-{}
-
-void
-ResolverBase::visit (AST::TupleExpr &)
-{}
-
-void
-ResolverBase::visit (AST::TupleIndexExpr &)
-{}
-
-void
-ResolverBase::visit (AST::StructExprStruct &)
-{}
-
-void
-ResolverBase::visit (AST::StructExprFieldIdentifier &)
-{}
-
-void
-ResolverBase::visit (AST::StructExprFieldIdentifierValue &)
-{}
-
-void
-ResolverBase::visit (AST::StructExprFieldIndexValue &)
-{}
-
-void
-ResolverBase::visit (AST::StructExprStructFields &)
-{}
-
-void
-ResolverBase::visit (AST::StructExprStructBase &)
-{}
-
-void
-ResolverBase::visit (AST::CallExpr &)
-{}
-
-void
-ResolverBase::visit (AST::MethodCallExpr &)
-{}
-
-void
-ResolverBase::visit (AST::FieldAccessExpr &)
-{}
-
-void
-ResolverBase::visit (AST::ClosureExprInner &)
-{}
-
-void
-ResolverBase::visit (AST::BlockExpr &)
-{}
-
-void
-ResolverBase::visit (AST::ClosureExprInnerTyped &)
-{}
-
-void
-ResolverBase::visit (AST::ContinueExpr &)
-{}
-
-void
-ResolverBase::visit (AST::BreakExpr &)
-{}
-
-void
-ResolverBase::visit (AST::RangeFromToExpr &)
-{}
-
-void
-ResolverBase::visit (AST::RangeFromExpr &)
-{}
-
-void
-ResolverBase::visit (AST::RangeToExpr &)
-{}
-
-void
-ResolverBase::visit (AST::RangeFullExpr &)
-{}
-
-void
-ResolverBase::visit (AST::RangeFromToInclExpr &)
-{}
-
-void
-ResolverBase::visit (AST::RangeToInclExpr &)
-{}
-
-void
-ResolverBase::visit (AST::BoxExpr &)
-{}
-
-void
-ResolverBase::visit (AST::ReturnExpr &)
-{}
-
-void
-ResolverBase::visit (AST::UnsafeBlockExpr &)
-{}
-
-void
-ResolverBase::visit (AST::LoopExpr &)
-{}
-
-void
-ResolverBase::visit (AST::WhileLoopExpr &)
-{}
-
-void
-ResolverBase::visit (AST::WhileLetLoopExpr &)
-{}
-
-void
-ResolverBase::visit (AST::ForLoopExpr &)
-{}
-
-void
-ResolverBase::visit (AST::IfExpr &)
-{}
-
-void
-ResolverBase::visit (AST::IfExprConseqElse &)
-{}
-
-void
-ResolverBase::visit (AST::IfLetExpr &)
-{}
-
-void
-ResolverBase::visit (AST::IfLetExprConseqElse &)
-{}
-
-void
-ResolverBase::visit (AST::MatchExpr &)
-{}
-
-void
-ResolverBase::visit (AST::AwaitExpr &)
-{}
-
-void
-ResolverBase::visit (AST::AsyncBlockExpr &)
-{}
-
-void
-ResolverBase::visit (AST::InlineAsm &)
-{}
-
-void
-ResolverBase::visit (AST::TypeParam &)
-{}
-
-void
-ResolverBase::visit (AST::LifetimeWhereClauseItem &)
-{}
-
-void
-ResolverBase::visit (AST::TypeBoundWhereClauseItem &)
-{}
-
-void
-ResolverBase::visit (AST::Module &)
-{}
-
-void
-ResolverBase::visit (AST::ExternCrate &)
-{}
-
-void
-ResolverBase::visit (AST::UseTreeGlob &)
-{}
-
-void
-ResolverBase::visit (AST::UseTreeList &)
-{}
-
-void
-ResolverBase::visit (AST::UseTreeRebind &)
-{}
-
-void
-ResolverBase::visit (AST::UseDeclaration &)
-{}
-
-void
-ResolverBase::visit (AST::Function &)
-{}
-
-void
-ResolverBase::visit (AST::TypeAlias &)
-{}
-
-void
-ResolverBase::visit (AST::StructStruct &)
-{}
-
-void
-ResolverBase::visit (AST::TupleStruct &)
-{}
-
-void
-ResolverBase::visit (AST::EnumItem &)
-{}
-
-void
-ResolverBase::visit (AST::EnumItemTuple &)
-{}
-
-void
-ResolverBase::visit (AST::EnumItemStruct &)
-{}
-
-void
-ResolverBase::visit (AST::EnumItemDiscriminant &)
-{}
-
-void
-ResolverBase::visit (AST::Enum &)
-{}
-
-void
-ResolverBase::visit (AST::Union &)
-{}
-
-void
-ResolverBase::visit (AST::ConstantItem &)
-{}
-
-void
-ResolverBase::visit (AST::StaticItem &)
-{}
-
-void
-ResolverBase::visit (AST::TraitItemConst &)
-{}
-
-void
-ResolverBase::visit (AST::TraitItemType &)
-{}
-
-void
-ResolverBase::visit (AST::Trait &)
-{}
-
-void
-ResolverBase::visit (AST::InherentImpl &)
-{}
-
-void
-ResolverBase::visit (AST::TraitImpl &)
-{}
-
-void
-ResolverBase::visit (AST::ExternalTypeItem &)
-{}
-
-void
-ResolverBase::visit (AST::ExternalStaticItem &)
-{}
-
-void
-ResolverBase::visit (AST::ExternBlock &)
-{}
-
-void
-ResolverBase::visit (AST::MacroMatchFragment &)
-{}
-
-void
-ResolverBase::visit (AST::MacroMatchRepetition &)
-{}
-
-void
-ResolverBase::visit (AST::MacroMatcher &)
-{}
-
-void
-ResolverBase::visit (AST::MacroRulesDefinition &)
-{}
-
-void
-ResolverBase::visit (AST::MacroInvocation &)
-{}
-
-void
-ResolverBase::visit (AST::MetaItemPath &)
-{}
-
-void
-ResolverBase::visit (AST::MetaItemSeq &)
-{}
-
-void
-ResolverBase::visit (AST::MetaWord &)
-{}
-
-void
-ResolverBase::visit (AST::MetaNameValueStr &)
-{}
-
-void
-ResolverBase::visit (AST::MetaListPaths &)
-{}
-
-void
-ResolverBase::visit (AST::MetaListNameValueStr &)
-{}
-
-void
-ResolverBase::visit (AST::LiteralPattern &)
-{}
-
-void
-ResolverBase::visit (AST::IdentifierPattern &)
-{}
-
-void
-ResolverBase::visit (AST::WildcardPattern &)
-{}
-
-void
-ResolverBase::visit (AST::RestPattern &)
-{}
-
-void
-ResolverBase::visit (AST::RangePatternBoundLiteral &)
-{}
-
-void
-ResolverBase::visit (AST::RangePatternBoundPath &)
-{}
-
-void
-ResolverBase::visit (AST::RangePatternBoundQualPath &)
-{}
-
-void
-ResolverBase::visit (AST::RangePattern &)
-{}
-
-void
-ResolverBase::visit (AST::ReferencePattern &)
-{}
-
-void
-ResolverBase::visit (AST::StructPatternFieldTuplePat &)
-{}
-
-void
-ResolverBase::visit (AST::StructPatternFieldIdentPat &)
-{}
-
-void
-ResolverBase::visit (AST::StructPatternFieldIdent &)
-{}
-
-void
-ResolverBase::visit (AST::StructPattern &)
-{}
-
-void
-ResolverBase::visit (AST::TupleStructItemsNoRange &)
-{}
-
-void
-ResolverBase::visit (AST::TupleStructItemsRange &)
-{}
-
-void
-ResolverBase::visit (AST::TupleStructPattern &)
-{}
-
-void
-ResolverBase::visit (AST::TuplePatternItemsMultiple &)
-{}
-
-void
-ResolverBase::visit (AST::TuplePatternItemsRanged &)
-{}
-
-void
-ResolverBase::visit (AST::TuplePattern &)
-{}
-
-void
-ResolverBase::visit (AST::GroupedPattern &)
-{}
-
-void
-ResolverBase::visit (AST::SlicePattern &)
-{}
-
-void
-ResolverBase::visit (AST::AltPattern &)
-{}
-
-void
-ResolverBase::visit (AST::EmptyStmt &)
-{}
-
-void
-ResolverBase::visit (AST::LetStmt &)
-{}
-
-void
-ResolverBase::visit (AST::ExprStmt &)
-{}
-
-void
-ResolverBase::visit (AST::TraitBound &)
-{}
-
-void
-ResolverBase::visit (AST::ImplTraitType &)
-{}
-
-void
-ResolverBase::visit (AST::TraitObjectType &)
-{}
-
-void
-ResolverBase::visit (AST::ParenthesisedType &)
-{}
-
-void
-ResolverBase::visit (AST::ImplTraitTypeOneBound &)
-{}
-
-void
-ResolverBase::visit (AST::TraitObjectTypeOneBound &)
-{}
-
-void
-ResolverBase::visit (AST::TupleType &)
-{}
-
-void
-ResolverBase::visit (AST::NeverType &)
-{}
-
-void
-ResolverBase::visit (AST::RawPointerType &)
-{}
-
-void
-ResolverBase::visit (AST::ReferenceType &)
-{}
-
-void
-ResolverBase::visit (AST::ArrayType &)
-{}
-
-void
-ResolverBase::visit (AST::SliceType &)
-{}
-
-void
-ResolverBase::visit (AST::InferredType &)
-{}
-
-void
-ResolverBase::visit (AST::BareFunctionType &)
-{}
-
-void
-ResolverBase::visit (AST::SelfParam &)
-{}
-
-void
-ResolverBase::visit (AST::VariadicParam &)
-{}
-
-void
-ResolverBase::visit (AST::FunctionParam &)
-{}
-
-void
-ResolverBase::visit (AST::FormatArgs &fmt)
-{}
-
-} // namespace Resolver
-} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h
deleted file mode 100644
index 0d497f8..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-base.h
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_RESOLVE_BASE_H
-#define RUST_AST_RESOLVE_BASE_H
-
-#include "rust-ast-visitor.h"
-#include "rust-ast.h"
-#include "rust-name-resolver.h"
-#include "rust-diagnostics.h"
-#include "rust-location.h"
-
-namespace Rust {
-namespace Resolver {
-
-class ResolverBase : public AST::ASTVisitor
-{
-public:
- virtual ~ResolverBase () {}
-
- void visit (AST::Token &);
- void visit (AST::DelimTokenTree &);
- void visit (AST::AttrInputMetaItemContainer &);
- void visit (AST::IdentifierExpr &);
- void visit (AST::Lifetime &);
- void visit (AST::LifetimeParam &);
- void visit (AST::ConstGenericParam &);
- void visit (AST::PathInExpression &);
- void visit (AST::TypePathSegment &);
- void visit (AST::TypePathSegmentGeneric &);
- void visit (AST::TypePathSegmentFunction &);
- void visit (AST::TypePath &);
- void visit (AST::QualifiedPathInExpression &);
- void visit (AST::QualifiedPathInType &);
- void visit (AST::LiteralExpr &);
- void visit (AST::AttrInputLiteral &);
- void visit (AST::AttrInputMacro &);
- void visit (AST::MetaItemLitExpr &);
- void visit (AST::MetaItemPathLit &);
- void visit (AST::BorrowExpr &);
- void visit (AST::DereferenceExpr &);
- void visit (AST::ErrorPropagationExpr &);
- void visit (AST::NegationExpr &);
- void visit (AST::ArithmeticOrLogicalExpr &);
- void visit (AST::ComparisonExpr &);
- void visit (AST::LazyBooleanExpr &);
- void visit (AST::TypeCastExpr &);
- void visit (AST::AssignmentExpr &);
- void visit (AST::CompoundAssignmentExpr &);
- void visit (AST::GroupedExpr &);
- void visit (AST::ArrayElemsValues &);
- void visit (AST::ArrayElemsCopied &);
- void visit (AST::ArrayExpr &);
- void visit (AST::ArrayIndexExpr &);
- void visit (AST::TupleExpr &);
- void visit (AST::TupleIndexExpr &);
- void visit (AST::StructExprStruct &);
- void visit (AST::StructExprFieldIdentifier &);
- void visit (AST::StructExprFieldIdentifierValue &);
- void visit (AST::StructExprFieldIndexValue &);
- void visit (AST::StructExprStructFields &);
- void visit (AST::StructExprStructBase &);
- void visit (AST::CallExpr &);
- void visit (AST::MethodCallExpr &);
- void visit (AST::FieldAccessExpr &);
- void visit (AST::ClosureExprInner &);
- void visit (AST::BlockExpr &);
- void visit (AST::ClosureExprInnerTyped &);
- void visit (AST::ContinueExpr &);
- void visit (AST::BreakExpr &);
- void visit (AST::RangeFromToExpr &);
- void visit (AST::RangeFromExpr &);
- void visit (AST::RangeToExpr &);
- void visit (AST::RangeFullExpr &);
- void visit (AST::RangeFromToInclExpr &);
- void visit (AST::RangeToInclExpr &);
- void visit (AST::BoxExpr &);
- void visit (AST::ReturnExpr &);
- void visit (AST::UnsafeBlockExpr &);
- void visit (AST::LoopExpr &);
- void visit (AST::WhileLoopExpr &);
- void visit (AST::WhileLetLoopExpr &);
- void visit (AST::ForLoopExpr &);
- void visit (AST::IfExpr &);
- void visit (AST::IfExprConseqElse &);
- void visit (AST::IfLetExpr &);
- void visit (AST::IfLetExprConseqElse &);
-
- void visit (AST::MatchExpr &);
- void visit (AST::AwaitExpr &);
- void visit (AST::AsyncBlockExpr &);
- void visit (AST::InlineAsm &);
-
- void visit (AST::TypeParam &);
-
- void visit (AST::LifetimeWhereClauseItem &);
- void visit (AST::TypeBoundWhereClauseItem &);
- void visit (AST::Module &);
- void visit (AST::ExternCrate &);
-
- void visit (AST::UseTreeGlob &);
- void visit (AST::UseTreeList &);
- void visit (AST::UseTreeRebind &);
- void visit (AST::UseDeclaration &);
- void visit (AST::Function &);
- void visit (AST::TypeAlias &);
- void visit (AST::StructStruct &);
- void visit (AST::TupleStruct &);
- void visit (AST::EnumItem &);
- void visit (AST::EnumItemTuple &);
- void visit (AST::EnumItemStruct &);
- void visit (AST::EnumItemDiscriminant &);
- void visit (AST::Enum &);
- void visit (AST::Union &);
- void visit (AST::ConstantItem &);
- void visit (AST::StaticItem &);
- void visit (AST::TraitItemConst &);
- void visit (AST::TraitItemType &);
- void visit (AST::Trait &);
- void visit (AST::InherentImpl &);
- void visit (AST::TraitImpl &);
-
- void visit (AST::ExternalTypeItem &);
- void visit (AST::ExternalStaticItem &);
- void visit (AST::ExternBlock &);
-
- void visit (AST::MacroMatchFragment &);
- void visit (AST::MacroMatchRepetition &);
- void visit (AST::MacroMatcher &);
- void visit (AST::MacroRulesDefinition &);
- void visit (AST::MacroInvocation &);
- void visit (AST::MetaItemPath &);
- void visit (AST::MetaItemSeq &);
- void visit (AST::MetaWord &);
- void visit (AST::MetaNameValueStr &);
- void visit (AST::MetaListPaths &);
- void visit (AST::MetaListNameValueStr &);
-
- void visit (AST::LiteralPattern &);
- void visit (AST::IdentifierPattern &);
- void visit (AST::WildcardPattern &);
- void visit (AST::RestPattern &);
-
- void visit (AST::RangePatternBoundLiteral &);
- void visit (AST::RangePatternBoundPath &);
- void visit (AST::RangePatternBoundQualPath &);
- void visit (AST::RangePattern &);
- void visit (AST::ReferencePattern &);
-
- void visit (AST::StructPatternFieldTuplePat &);
- void visit (AST::StructPatternFieldIdentPat &);
- void visit (AST::StructPatternFieldIdent &);
- void visit (AST::StructPattern &);
-
- void visit (AST::TupleStructItemsNoRange &);
- void visit (AST::TupleStructItemsRange &);
- void visit (AST::TupleStructPattern &);
-
- void visit (AST::TuplePatternItemsMultiple &);
- void visit (AST::TuplePatternItemsRanged &);
- void visit (AST::TuplePattern &);
- void visit (AST::GroupedPattern &);
- void visit (AST::SlicePattern &);
- void visit (AST::AltPattern &);
-
- void visit (AST::EmptyStmt &);
- void visit (AST::LetStmt &);
- void visit (AST::ExprStmt &);
-
- void visit (AST::TraitBound &);
- void visit (AST::ImplTraitType &);
- void visit (AST::TraitObjectType &);
- void visit (AST::ParenthesisedType &);
- void visit (AST::ImplTraitTypeOneBound &);
- void visit (AST::TraitObjectTypeOneBound &);
- void visit (AST::TupleType &);
- void visit (AST::NeverType &);
- void visit (AST::RawPointerType &);
- void visit (AST::ReferenceType &);
- void visit (AST::ArrayType &);
- void visit (AST::SliceType &);
- void visit (AST::InferredType &);
- void visit (AST::BareFunctionType &);
- void visit (AST::FunctionParam &param);
- void visit (AST::VariadicParam &param);
- void visit (AST::SelfParam &param);
-
- void visit (AST::FormatArgs &fmt);
-
-protected:
- ResolverBase ()
- : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()),
- resolved_node (UNKNOWN_NODEID)
- {}
-
- /**
- * Resolve a visibility's path through the name resolver
- */
- bool resolve_visibility (const AST::Visibility &vis);
-
- Resolver *resolver;
- Analysis::Mappings &mappings;
- NodeId resolved_node;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_AST_RESOLVE_BASE_H
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc
deleted file mode 100644
index dc7f76d..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-expr.cc
+++ /dev/null
@@ -1,785 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-ast-resolve-expr.h"
-#include "rust-ast-resolve-stmt.h"
-#include "rust-ast-resolve-struct-expr-field.h"
-#include "rust-ast-resolve-type.h"
-#include "rust-ast-resolve-pattern.h"
-#include "rust-ast-resolve-path.h"
-#include "rust-expr.h"
-#include "rust-ice-finalizer.h"
-
-namespace Rust {
-namespace Resolver {
-
-void
-ResolveExpr::go (AST::Expr &expr, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix, bool funny_error)
-{
- ResolveExpr resolver (prefix, canonical_prefix, funny_error);
- expr.accept_vis (resolver);
-}
-
-void
-ResolveExpr::visit (AST::TupleIndexExpr &expr)
-{
- ResolveExpr::go (expr.get_tuple_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::TupleExpr &expr)
-{
- if (expr.is_unit ())
- return;
-
- for (auto &elem : expr.get_tuple_elems ())
- ResolveExpr::go (*elem, prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::PathInExpression &expr)
-{
- ResolvePath::go (expr);
-}
-
-void
-ResolveExpr::visit (AST::QualifiedPathInExpression &expr)
-{
- ResolvePath::go (expr);
-}
-
-void
-ResolveExpr::visit (AST::ReturnExpr &expr)
-{
- if (expr.has_returned_expr ())
- ResolveExpr::go (expr.get_returned_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::CallExpr &expr)
-{
- ResolveExpr::go (expr.get_function_expr (), prefix, canonical_prefix);
- for (auto &param : expr.get_params ())
- ResolveExpr::go (*param, prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::MethodCallExpr &expr)
-{
- ResolveExpr::go (expr.get_receiver_expr (), prefix, canonical_prefix);
-
- if (expr.get_method_name ().has_generic_args ())
- {
- AST::GenericArgs &args = expr.get_method_name ().get_generic_args ();
- ResolveGenericArgs::go (args, prefix, canonical_prefix);
- }
-
- auto const &in_params = expr.get_params ();
- for (auto &param : in_params)
- ResolveExpr::go (*param, prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::ErrorPropagationExpr &expr)
-{
- ResolveExpr::go (expr.get_propagating_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::AssignmentExpr &expr)
-{
- ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::IdentifierExpr &expr)
-{
- if (resolver->get_name_scope ().lookup (
- CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()),
- &resolved_node))
- {
- resolver->insert_resolved_name (expr.get_node_id (), resolved_node);
- }
- else if (resolver->get_type_scope ().lookup (
- CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()),
- &resolved_node))
- {
- resolver->insert_resolved_type (expr.get_node_id (), resolved_node);
- }
- else if (funny_error)
- {
- /* This was a "break rust" or "break gcc", and the identifier failed to
- resolve. Emit a funny ICE. We set the finalizer to our custom one,
- and use the lower-level emit_diagnostic () instead of the more common
- internal_error_no_backtrace () in order to pass our locus. */
- diagnostic_text_finalizer (global_dc) = funny_ice_text_finalizer;
- emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1,
- "are you trying to break %s? how dare you?",
- expr.as_string ().c_str ());
- }
- else
- {
- rust_error_at (expr.get_locus (), ErrorCode::E0425,
- "cannot find value %qs in this scope",
- expr.as_string ().c_str ());
- }
-}
-
-void
-ResolveExpr::visit (AST::ArithmeticOrLogicalExpr &expr)
-{
- ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::CompoundAssignmentExpr &expr)
-{
- ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::ComparisonExpr &expr)
-{
- ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::LazyBooleanExpr &expr)
-{
- ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::NegationExpr &expr)
-{
- ResolveExpr::go (expr.get_negated_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::TypeCastExpr &expr)
-{
- ResolveType::go (expr.get_type_to_cast_to ());
- ResolveExpr::go (expr.get_casted_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::IfExpr &expr)
-{
- ResolveExpr::go (expr.get_condition_expr (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::IfExprConseqElse &expr)
-{
- ResolveExpr::go (expr.get_condition_expr (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_else_block (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::IfLetExpr &expr)
-{
- ResolveExpr::go (expr.get_value_expr (), prefix, canonical_prefix);
-
- NodeId scope_node_id = expr.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- // We know expr.get_patterns () has one pattern at most
- // so there's no reason to handle it like an AltPattern.
- std::vector<PatternBinding> bindings
- = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
-
- for (auto &pattern : expr.get_patterns ())
- {
- PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings);
- }
-
- ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix);
-
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
-}
-
-void
-ResolveExpr::visit (AST::IfLetExprConseqElse &expr)
-{
- ResolveExpr::go (expr.get_value_expr (), prefix, canonical_prefix);
-
- NodeId scope_node_id = expr.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- // We know expr.get_patterns () has one pattern at most
- // so there's no reason to handle it like an AltPattern.
- std::vector<PatternBinding> bindings
- = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
-
- for (auto &pattern : expr.get_patterns ())
- {
- PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings);
- }
-
- ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_else_block (), prefix, canonical_prefix);
-
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
-}
-
-void
-ResolveExpr::visit (AST::BlockExpr &expr)
-{
- NodeId scope_node_id = expr.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- if (expr.has_label ())
- {
- auto label = expr.get_label ();
- if (label.get_lifetime ().get_lifetime_type ()
- != AST::Lifetime::LifetimeType::NAMED)
- {
- rust_error_at (label.get_locus (),
- "Labels must be a named lifetime value");
- return;
- }
-
- auto label_name = label.get_lifetime ().get_lifetime_name ();
- auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
- resolver->get_label_scope ().insert (
- CanonicalPath::new_seg (label.get_node_id (), label_name),
- label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rust_error_at (label.get_locus (), "label defined multiple times");
- rust_error_at (locus, "was defined here");
- });
- }
-
- for (auto &s : expr.get_statements ())
- {
- if (s->is_item ())
- ResolveStmt::go (*s, prefix, canonical_prefix,
- CanonicalPath::create_empty ());
- }
-
- for (auto &s : expr.get_statements ())
- {
- if (!s->is_item ())
- ResolveStmt::go (*s, prefix, canonical_prefix,
- CanonicalPath::create_empty ());
- }
-
- if (expr.has_tail_expr ())
- ResolveExpr::go (expr.get_tail_expr (), prefix, canonical_prefix);
-
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
-}
-
-void
-translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
-{
- const auto &operands = expr.get_operands ();
- using RegisterType = AST::InlineAsmOperand::RegisterType;
- for (auto &operand : operands)
- {
- switch (operand.get_register_type ())
- {
- case RegisterType::In: {
- auto in = operand.get_in ();
- ResolveExpr::go (*in.expr, prefix, canonical_prefix);
- break;
- }
- case RegisterType::Out: {
- auto out = operand.get_out ();
- ResolveExpr::go (*out.expr, prefix, canonical_prefix);
- break;
- }
- case RegisterType::InOut: {
- auto in_out = operand.get_in_out ();
- ResolveExpr::go (*in_out.expr, prefix, canonical_prefix);
- break;
- }
- 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: {
- auto anon_const = operand.get_const ().anon_const;
- ResolveExpr::go (*anon_const.expr, prefix, canonical_prefix);
- break;
- }
- case RegisterType::Sym: {
- auto sym = operand.get_sym ();
- ResolveExpr::go (*sym.expr, prefix, canonical_prefix);
- break;
- }
- case RegisterType::Label: {
- auto label = operand.get_label ();
- ResolveExpr::go (*label.expr, prefix, canonical_prefix);
- break;
- }
- }
- }
-}
-void
-ResolveExpr::visit (AST::InlineAsm &expr)
-{
- translate_operand (expr, prefix, canonical_prefix);
-}
-void
-ResolveExpr::visit (AST::UnsafeBlockExpr &expr)
-{
- expr.get_block_expr ().accept_vis (*this);
-}
-
-void
-ResolveExpr::visit (AST::ArrayElemsValues &elems)
-{
- for (auto &elem : elems.get_values ())
- ResolveExpr::go (*elem, prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::ArrayExpr &expr)
-{
- expr.get_array_elems ()->accept_vis (*this);
-}
-
-void
-ResolveExpr::visit (AST::ArrayIndexExpr &expr)
-{
- ResolveExpr::go (expr.get_array_expr (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_index_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::ArrayElemsCopied &expr)
-{
- ResolveExpr::go (expr.get_num_copies (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_elem_to_copy (), prefix, canonical_prefix);
-}
-
-// this this an empty struct constructor like 'S {}'
-void
-ResolveExpr::visit (AST::StructExprStruct &struct_expr)
-{
- ResolveExpr::go (struct_expr.get_struct_name (), prefix, canonical_prefix);
-}
-
-// this this a struct constructor with fields
-void
-ResolveExpr::visit (AST::StructExprStructFields &struct_expr)
-{
- ResolveExpr::go (struct_expr.get_struct_name (), prefix, canonical_prefix);
-
- if (struct_expr.has_struct_base ())
- {
- AST::StructBase &base = struct_expr.get_struct_base ();
- ResolveExpr::go (base.get_base_struct (), prefix, canonical_prefix);
- }
-
- auto const &struct_fields = struct_expr.get_fields ();
- for (auto &struct_field : struct_fields)
- {
- ResolveStructExprField::go (*struct_field, prefix, canonical_prefix);
- }
-}
-
-void
-ResolveExpr::visit (AST::GroupedExpr &expr)
-{
- ResolveExpr::go (expr.get_expr_in_parens (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::FieldAccessExpr &expr)
-{
- ResolveExpr::go (expr.get_receiver_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::LoopExpr &expr)
-{
- if (expr.has_loop_label ())
- {
- auto label = expr.get_loop_label ();
- if (label.get_lifetime ().get_lifetime_type ()
- != AST::Lifetime::LifetimeType::NAMED)
- {
- rust_error_at (label.get_locus (),
- "Labels must be a named lifetime value");
- return;
- }
-
- auto label_name = label.get_lifetime ().get_lifetime_name ();
- auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
- resolver->get_label_scope ().insert (
- CanonicalPath::new_seg (expr.get_node_id (), label_name),
- label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rust_error_at (label.get_locus (), "label defined multiple times");
- rust_error_at (locus, "was defined here");
- });
- }
- ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::BreakExpr &expr)
-{
- if (expr.has_label ())
- {
- auto label = expr.get_label ().get_lifetime ();
- if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED)
- {
- rust_error_at (label.get_locus (),
- "Labels must be a named lifetime value");
- return;
- }
-
- NodeId resolved_node = UNKNOWN_NODEID;
- if (!resolver->get_label_scope ().lookup (
- CanonicalPath::new_seg (label.get_node_id (),
- label.get_lifetime_name ()),
- &resolved_node))
- {
- rust_error_at (label.get_locus (), ErrorCode::E0426,
- "use of undeclared label %qs in %<break%>",
- label.get_lifetime_name ().c_str ());
- return;
- }
- resolver->insert_resolved_label (label.get_node_id (), resolved_node);
- }
-
- if (expr.has_break_expr ())
- {
- bool funny_error = false;
- auto &break_expr = expr.get_break_expr ();
- if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier)
- {
- /* This is a break with an expression, and the expression is
- just a single identifier. See if the identifier is either
- "rust" or "gcc", in which case we have "break rust" or "break
- gcc", and so may need to emit our funny error. We cannot yet
- emit the error here though, because the identifier may still
- be in scope, and ICE'ing on valid programs would not be very
- funny. */
- std::string ident
- = static_cast<AST::IdentifierExpr &> (break_expr).as_string ();
- if (ident == "rust" || ident == "gcc")
- funny_error = true;
- }
- ResolveExpr::go (break_expr, prefix, canonical_prefix, funny_error);
- }
-}
-
-void
-ResolveExpr::visit (AST::WhileLoopExpr &expr)
-{
- if (expr.has_loop_label ())
- {
- auto label = expr.get_loop_label ();
- if (label.get_lifetime ().get_lifetime_type ()
- != AST::Lifetime::LifetimeType::NAMED)
- {
- rust_error_at (label.get_locus (),
- "Labels must be a named lifetime value");
- return;
- }
-
- auto label_name = label.get_lifetime ().get_lifetime_name ();
- auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
- resolver->get_label_scope ().insert (
- CanonicalPath::new_seg (label.get_node_id (), label_name),
- label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rust_error_at (label.get_locus (), "label defined multiple times");
- rust_error_at (locus, "was defined here");
- });
- }
-
- ResolveExpr::go (expr.get_predicate_expr (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::ForLoopExpr &expr)
-{
- if (expr.has_loop_label ())
- {
- auto label = expr.get_loop_label ();
- if (label.get_lifetime ().get_lifetime_type ()
- != AST::Lifetime::LifetimeType::NAMED)
- {
- rust_error_at (label.get_locus (),
- "Labels must be a named lifetime value");
- return;
- }
-
- auto label_name = label.get_lifetime ().get_lifetime_name ();
- auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
- resolver->get_label_scope ().insert (
- CanonicalPath::new_seg (label.get_node_id (), label_name),
- label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rust_error_at (label.get_locus (), "label defined multiple times");
- rust_error_at (locus, "was defined here");
- });
- }
-
- // this needs a new rib to contain the pattern
- NodeId scope_node_id = expr.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- // resolve the expression
- PatternDeclaration::go (expr.get_pattern (), Rib::ItemType::Var);
- ResolveExpr::go (expr.get_iterator_expr (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix);
-
- // done
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
-}
-
-void
-ResolveExpr::visit (AST::ContinueExpr &expr)
-{
- if (expr.has_label ())
- {
- auto label = expr.get_label ();
- if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED)
- {
- rust_error_at (label.get_locus (),
- "Labels must be a named lifetime value");
- return;
- }
-
- NodeId resolved_node = UNKNOWN_NODEID;
- if (!resolver->get_label_scope ().lookup (
- CanonicalPath::new_seg (label.get_node_id (),
- label.get_lifetime_name ()),
- &resolved_node))
- {
- rust_error_at (expr.get_label ().get_locus (), ErrorCode::E0426,
- "use of undeclared label %qs in %<continue%>",
- label.get_lifetime_name ().c_str ());
- return;
- }
- resolver->insert_resolved_label (label.get_node_id (), resolved_node);
- }
-}
-
-void
-ResolveExpr::visit (AST::BorrowExpr &expr)
-{
- ResolveExpr::go (expr.get_borrowed_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::DereferenceExpr &expr)
-{
- ResolveExpr::go (expr.get_dereferenced_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::MatchExpr &expr)
-{
- ResolveExpr::go (expr.get_scrutinee_expr (), prefix, canonical_prefix);
- for (auto &match_case : expr.get_match_cases ())
- {
- // each arm is in its own scope
- NodeId scope_node_id = match_case.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- // resolve
- AST::MatchArm &arm = match_case.get_arm ();
- if (arm.has_match_arm_guard ())
- ResolveExpr::go (arm.get_guard_expr (), prefix, canonical_prefix);
-
- // We know expr.get_patterns () has one pattern at most
- // so there's no reason to handle it like an AltPattern.
- std::vector<PatternBinding> bindings
- = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
-
- // insert any possible new patterns
- for (auto &pattern : arm.get_patterns ())
- {
- PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings);
- }
-
- // resolve the body
- ResolveExpr::go (match_case.get_expr (), prefix, canonical_prefix);
-
- // done
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
- }
-}
-
-void
-ResolveExpr::visit (AST::RangeFromToExpr &expr)
-{
- ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::RangeFromExpr &expr)
-{
- ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::RangeToExpr &expr)
-{
- ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::RangeFullExpr &)
-{
- // nothing to do
-}
-
-void
-ResolveExpr::visit (AST::RangeFromToInclExpr &expr)
-{
- ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix);
- ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix);
-}
-
-void
-ResolveExpr::visit (AST::ClosureExprInner &expr)
-{
- NodeId scope_node_id = expr.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- std::vector<PatternBinding> bindings
- = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
-
- for (auto &p : expr.get_params ())
- {
- resolve_closure_param (p, bindings);
- }
-
- resolver->push_closure_context (expr.get_node_id ());
-
- ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix);
-
- resolver->pop_closure_context ();
-
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
-}
-
-void
-ResolveExpr::visit (AST::ClosureExprInnerTyped &expr)
-{
- NodeId scope_node_id = expr.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- std::vector<PatternBinding> bindings
- = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
-
- for (auto &p : expr.get_params ())
- {
- resolve_closure_param (p, bindings);
- }
-
- ResolveType::go (expr.get_return_type ());
-
- resolver->push_closure_context (expr.get_node_id ());
-
- ResolveExpr::go (expr.get_definition_block (), prefix, canonical_prefix);
-
- resolver->pop_closure_context ();
-
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
-}
-
-void
-ResolveExpr::resolve_closure_param (AST::ClosureParam &param,
- std::vector<PatternBinding> &bindings)
-{
- PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, bindings);
-
- if (param.has_type_given ())
- ResolveType::go (param.get_type ());
-}
-
-ResolveExpr::ResolveExpr (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix,
- bool funny_error)
- : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix),
- funny_error (funny_error)
-{}
-
-} // namespace Resolver
-} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
deleted file mode 100644
index 562a3bd..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_RESOLVE_EXPR_H
-#define RUST_AST_RESOLVE_EXPR_H
-
-#include "rust-ast-resolve-base.h"
-#include "rust-ast.h"
-#include "rust-ast-resolve-pattern.h"
-#include "rust-expr.h"
-
-namespace Rust {
-namespace Resolver {
-
-class ResolveExpr : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void go (AST::Expr &expr, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix,
- bool funny_error = false);
-
- void visit (AST::TupleIndexExpr &expr) override;
- void visit (AST::TupleExpr &expr) override;
- void visit (AST::PathInExpression &expr) override;
- void visit (AST::QualifiedPathInExpression &expr) override;
- void visit (AST::ReturnExpr &expr) override;
- void visit (AST::CallExpr &expr) override;
- void visit (AST::MethodCallExpr &expr) override;
- void visit (AST::AssignmentExpr &expr) override;
- void visit (AST::IdentifierExpr &expr) override;
- void visit (AST::ArithmeticOrLogicalExpr &expr) override;
- void visit (AST::CompoundAssignmentExpr &expr) override;
- void visit (AST::ComparisonExpr &expr) override;
- void visit (AST::LazyBooleanExpr &expr) override;
- void visit (AST::NegationExpr &expr) override;
- void visit (AST::TypeCastExpr &expr) override;
- void visit (AST::IfExpr &expr) override;
- void visit (AST::IfExprConseqElse &expr) override;
- void visit (AST::IfLetExpr &expr) override;
- void visit (AST::IfLetExprConseqElse &expr) override;
- void visit (AST::BlockExpr &expr) override;
- void visit (AST::InlineAsm &expr) override;
- void visit (AST::UnsafeBlockExpr &expr) override;
- void visit (AST::ArrayElemsValues &elems) override;
- void visit (AST::ArrayExpr &expr) override;
- void visit (AST::ArrayIndexExpr &expr) override;
- void visit (AST::ArrayElemsCopied &elems) override;
- void visit (AST::StructExprStruct &struct_expr) override;
- void visit (AST::StructExprStructFields &struct_expr) override;
- void visit (AST::GroupedExpr &expr) override;
- void visit (AST::FieldAccessExpr &expr) override;
- void visit (AST::LoopExpr &expr) override;
- void visit (AST::BreakExpr &expr) override;
- void visit (AST::WhileLoopExpr &expr) override;
- void visit (AST::ForLoopExpr &expr) override;
- void visit (AST::ContinueExpr &expr) override;
- void visit (AST::BorrowExpr &expr) override;
- void visit (AST::DereferenceExpr &expr) override;
- void visit (AST::MatchExpr &expr) override;
- void visit (AST::RangeFromToExpr &expr) override;
- void visit (AST::RangeFromExpr &expr) override;
- void visit (AST::RangeToExpr &expr) override;
- void visit (AST::RangeFullExpr &expr) override;
- void visit (AST::RangeFromToInclExpr &expr) override;
- void visit (AST::ClosureExprInner &expr) override;
- void visit (AST::ClosureExprInnerTyped &expr) override;
- void visit (AST::ErrorPropagationExpr &expr) override;
-
-protected:
- void resolve_closure_param (AST::ClosureParam &param,
- std::vector<PatternBinding> &bindings);
-
-private:
- ResolveExpr (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix, bool funny_error);
-
- const CanonicalPath &prefix;
- const CanonicalPath &canonical_prefix;
- bool funny_error;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_AST_RESOLVE_EXPR_H
diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h
deleted file mode 100644
index 971bf8f..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-implitem.h
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_RESOLVE_IMPLITEM_H
-#define RUST_AST_RESOLVE_IMPLITEM_H
-
-#include "rust-ast-resolve-base.h"
-#include "rust-ast-resolve-type.h"
-#include "rust-ast-full.h"
-
-namespace Rust {
-namespace Resolver {
-
-class ResolveToplevelImplItem : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void go (AST::AssociatedItem &item, const CanonicalPath &prefix)
- {
- if (item.is_marked_for_strip ())
- return;
-
- ResolveToplevelImplItem resolver (prefix);
- item.accept_vis (resolver);
- }
-
- void visit (AST::TypeAlias &type) override
- {
- auto decl = CanonicalPath::new_seg (type.get_node_id (),
- type.get_new_type_name ().as_string ());
- auto path = prefix.append (decl);
-
- resolver->get_type_scope ().insert (
- path, type.get_node_id (), type.get_locus (), false, Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, type.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
- }
-
- void visit (AST::ConstantItem &constant) override
- {
- auto decl = CanonicalPath::new_seg (constant.get_node_id (),
- constant.get_identifier ());
- auto path = prefix.append (decl);
-
- resolver->get_name_scope ().insert (
- path, constant.get_node_id (), constant.get_locus (), false,
- Rib::ItemType::Const,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, constant.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
- }
-
- void visit (AST::Function &function) override
- {
- auto decl
- = CanonicalPath::new_seg (function.get_node_id (),
- function.get_function_name ().as_string ());
- auto path = prefix.append (decl);
-
- resolver->get_name_scope ().insert (
- path, function.get_node_id (), function.get_locus (), false,
- Rib::ItemType::Function,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, function.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
- }
-
-private:
- ResolveToplevelImplItem (const CanonicalPath &prefix)
- : ResolverBase (), prefix (prefix)
- {
- rust_assert (!prefix.is_empty ());
- }
-
- const CanonicalPath &prefix;
-};
-
-class ResolveTopLevelTraitItems : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void go (AST::AssociatedItem *item, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
- {
- ResolveTopLevelTraitItems resolver (prefix, canonical_prefix);
- item->accept_vis (resolver);
- };
-
- void visit (AST::Function &function) override
- {
- auto decl
- = CanonicalPath::new_seg (function.get_node_id (),
- function.get_function_name ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_name_scope ().insert (
- path, function.get_node_id (), function.get_locus (), false,
- Rib::ItemType::Function,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, function.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- mappings.insert_canonical_path (function.get_node_id (), cpath);
- }
-
- void visit (AST::TraitItemConst &constant) override
- {
- auto decl
- = CanonicalPath::new_seg (constant.get_node_id (),
- constant.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_name_scope ().insert (
- path, constant.get_node_id (), constant.get_locus (), false,
- Rib::ItemType::Const,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, constant.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- mappings.insert_canonical_path (constant.get_node_id (), cpath);
- }
-
- void visit (AST::TraitItemType &type) override
- {
- auto decl = CanonicalPath::new_seg (type.get_node_id (),
- type.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_type_scope ().insert (
- path, type.get_node_id (), type.get_locus (), false, Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, type.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- mappings.insert_canonical_path (type.get_node_id (), cpath);
- }
-
-private:
- ResolveTopLevelTraitItems (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
- : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
- {}
-
- const CanonicalPath &prefix;
- const CanonicalPath &canonical_prefix;
-};
-
-class ResolveToplevelExternItem : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void go (AST::ExternalItem &item, const CanonicalPath &prefix)
- {
- ResolveToplevelExternItem resolver (prefix);
- item.accept_vis (resolver);
- };
-
- void visit (AST::Function &function) override
- {
- auto decl
- = CanonicalPath::new_seg (function.get_node_id (),
- function.get_function_name ().as_string ());
- auto path = prefix.append (decl);
-
- resolver->get_name_scope ().insert (
- path, function.get_node_id (), function.get_locus (), false,
- Rib::ItemType::Function,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, function.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- }
-
- void visit (AST::ExternalStaticItem &item) override
- {
- auto decl = CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ());
- auto path = prefix.append (decl);
-
- resolver->get_name_scope ().insert (
- path, item.get_node_id (), item.get_locus (), false,
- Rib::ItemType::Static,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, item.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- }
-
- void visit (AST::ExternalTypeItem &type) override
- {
- auto decl = CanonicalPath::new_seg (type.get_node_id (),
- type.get_identifier ().as_string ());
- auto path = prefix.append (decl);
-
- resolver->get_type_scope ().insert (
- path, type.get_node_id (), type.get_locus (), false, Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, type.get_locus ());
- r.add_range (locus);
-
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- }
-
-private:
- ResolveToplevelExternItem (const CanonicalPath &prefix)
- : ResolverBase (), prefix (prefix)
- {}
-
- const CanonicalPath &prefix;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_AST_RESOLVE_IMPLITEM_H
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc
deleted file mode 100644
index d584961..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ /dev/null
@@ -1,1250 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-ast-resolve-item.h"
-#include "rust-ast-full-decls.h"
-#include "rust-ast-resolve-toplevel.h"
-#include "rust-ast-resolve-type.h"
-#include "rust-ast-resolve-pattern.h"
-#include "rust-ast-resolve-path.h"
-
-#include "rust-item.h"
-#include "selftest.h"
-
-namespace Rust {
-namespace Resolver {
-
-ResolveTraitItems::ResolveTraitItems (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
- : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
-{}
-
-void
-ResolveTraitItems::go (AST::AssociatedItem *item, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
-{
- if (item->is_marked_for_strip ())
- return;
-
- ResolveTraitItems resolver (prefix, canonical_prefix);
- item->accept_vis (resolver);
-}
-
-void
-ResolveTraitItems::visit (AST::Function &function)
-{
- auto decl
- = CanonicalPath::new_seg (function.get_node_id (),
- function.get_function_name ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (function.get_node_id (), cpath);
-
- NodeId scope_node_id = function.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- if (function.has_generics ())
- ResolveGenericParams::go (function.get_generic_params (), prefix,
- canonical_prefix);
-
- if (function.has_return_type ())
- ResolveType::go (function.get_return_type ());
-
- // self turns into (self: Self) as a function param
- std::vector<PatternBinding> bindings
- = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
-
- // we make a new scope so the names of parameters are resolved and shadowed
- // correctly
- for (auto &p : function.get_function_params ())
- {
- if (p->is_variadic ())
- {
- auto param = static_cast<AST::VariadicParam &> (*p);
- PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param,
- bindings);
- }
- else if (p->is_self ())
- {
- auto &param = static_cast<AST::SelfParam &> (*p);
- // FIXME: which location should be used for Rust::Identifier `self`?
- AST::IdentifierPattern self_pattern (
- param.get_node_id (), {"self"}, param.get_locus (),
- param.get_has_ref (), param.get_is_mut (),
- std::unique_ptr<AST::Pattern> (nullptr));
-
- PatternDeclaration::go (self_pattern, Rib::ItemType::Param);
-
- if (param.has_type ())
- {
- // This shouldn't happen the parser should already error for this
- rust_assert (!param.get_has_ref ());
- ResolveType::go (param.get_type ());
- }
- else
- {
- // here we implicitly make self have a type path of Self
- std::vector<std::unique_ptr<AST::TypePathSegment>> segments;
- segments.push_back (std::unique_ptr<AST::TypePathSegment> (
- new AST::TypePathSegment ("Self", false, param.get_locus ())));
-
- AST::TypePath self_type_path (std::move (segments),
- param.get_locus ());
- ResolveType::go (self_type_path);
- }
- }
- else
- {
- auto &param = static_cast<AST::FunctionParam &> (*p);
- ResolveType::go (param.get_type ());
- PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param,
- bindings);
- }
- }
-
- if (function.has_where_clause ())
- ResolveWhereClause::Resolve (function.get_where_clause ());
-
- // trait items have an optional body
- if (function.has_body ())
- ResolveExpr::go (*function.get_definition ().value (), path, cpath);
-
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
-}
-void
-ResolveTraitItems::visit (AST::TraitItemType &type)
-{
- auto decl = CanonicalPath::new_seg (type.get_node_id (),
- type.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (type.get_node_id (), cpath);
-
- for (auto &bound : type.get_type_param_bounds ())
- ResolveTypeBound::go (*bound);
-}
-
-void
-ResolveTraitItems::visit (AST::TraitItemConst &constant)
-{
- auto decl = CanonicalPath::new_seg (constant.get_node_id (),
- constant.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (constant.get_node_id (), cpath);
-
- ResolveType::go (constant.get_type ());
-
- if (constant.has_expr ())
- ResolveExpr::go (constant.get_expr (), path, cpath);
-}
-
-ResolveItem::ResolveItem (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
- : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
-{}
-
-void
-ResolveItem::go (AST::Item &item, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
-{
- ResolveItem resolver (prefix, canonical_prefix);
- item.accept_vis (resolver);
-}
-
-void
-ResolveItem::visit (AST::TypeAlias &alias)
-{
- auto talias
- = CanonicalPath::new_seg (alias.get_node_id (),
- alias.get_new_type_name ().as_string ());
- auto path = prefix.append (talias);
- auto cpath = canonical_prefix.append (talias);
- mappings.insert_canonical_path (alias.get_node_id (), cpath);
-
- NodeId scope_node_id = alias.get_node_id ();
- resolver->get_type_scope ().push (scope_node_id);
-
- if (alias.has_generics ())
- ResolveGenericParams::go (alias.get_generic_params (), prefix,
- canonical_prefix);
-
- if (alias.has_where_clause ())
- ResolveWhereClause::Resolve (alias.get_where_clause ());
-
- ResolveType::go (alias.get_type_aliased ());
-
- resolver->get_type_scope ().pop ();
-}
-
-void
-ResolveItem::visit (AST::Module &module)
-{
- auto mod = CanonicalPath::new_seg (module.get_node_id (),
- module.get_name ().as_string ());
- auto path = prefix.append (mod);
- auto cpath = canonical_prefix.append (mod);
- mappings.insert_canonical_path (module.get_node_id (), cpath);
-
- resolve_visibility (module.get_visibility ());
-
- NodeId scope_node_id = module.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- // FIXME: Should we reinsert a child here? Any reason we ResolveTopLevel::go
- // in ResolveTopLevel::visit (AST::Module) as well as here?
- for (auto &item : module.get_items ())
- ResolveTopLevel::go (*item, CanonicalPath::create_empty (), cpath);
-
- resolver->push_new_module_scope (module.get_node_id ());
- for (auto &item : module.get_items ())
- ResolveItem::go (*item, path, cpath);
-
- resolver->pop_module_scope ();
-
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
-}
-
-void
-ResolveItem::visit (AST::TupleStruct &struct_decl)
-{
- auto decl
- = CanonicalPath::new_seg (struct_decl.get_node_id (),
- struct_decl.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (struct_decl.get_node_id (), cpath);
-
- resolve_visibility (struct_decl.get_visibility ());
-
- NodeId scope_node_id = struct_decl.get_node_id ();
- resolver->get_type_scope ().push (scope_node_id);
-
- if (struct_decl.has_generics ())
- ResolveGenericParams::go (struct_decl.get_generic_params (), prefix,
- canonical_prefix);
-
- if (struct_decl.has_where_clause ())
- ResolveWhereClause::Resolve (struct_decl.get_where_clause ());
-
- for (AST::TupleField &field : struct_decl.get_fields ())
- {
- if (field.get_field_type ().is_marked_for_strip ())
- continue;
-
- resolve_visibility (field.get_visibility ());
-
- ResolveType::go (field.get_field_type ());
- }
-
- resolver->get_type_scope ().pop ();
-}
-
-void
-ResolveItem::visit (AST::Enum &enum_decl)
-{
- auto decl = CanonicalPath::new_seg (enum_decl.get_node_id (),
- enum_decl.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (enum_decl.get_node_id (), cpath);
-
- resolve_visibility (enum_decl.get_visibility ());
-
- NodeId scope_node_id = enum_decl.get_node_id ();
- resolver->get_type_scope ().push (scope_node_id);
-
- if (enum_decl.has_generics ())
- ResolveGenericParams::go (enum_decl.get_generic_params (), prefix,
- canonical_prefix);
-
- if (enum_decl.has_where_clause ())
- ResolveWhereClause::Resolve (enum_decl.get_where_clause ());
-
- /* The actual fields are inside the variants. */
- for (auto &variant : enum_decl.get_variants ())
- ResolveItem::go (*variant, path, cpath);
-
- resolver->get_type_scope ().pop ();
-}
-
-/* EnumItem doesn't need to be handled, no fields. */
-void
-ResolveItem::visit (AST::EnumItem &item)
-{
- // Since at this point we cannot have visibilities on enum items anymore, we
- // can skip handling them
-
- auto decl = CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (item.get_node_id (), cpath);
-}
-
-void
-ResolveItem::visit (AST::EnumItemTuple &item)
-{
- auto decl = CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (item.get_node_id (), cpath);
-
- for (auto &field : item.get_tuple_fields ())
- {
- if (field.get_field_type ().is_marked_for_strip ())
- continue;
-
- ResolveType::go (field.get_field_type ());
- }
-}
-
-void
-ResolveItem::visit (AST::EnumItemStruct &item)
-{
- auto decl = CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (item.get_node_id (), cpath);
-
- for (auto &field : item.get_struct_fields ())
- {
- if (field.get_field_type ().is_marked_for_strip ())
- continue;
-
- ResolveType::go (field.get_field_type ());
- }
-}
-
-void
-ResolveItem::visit (AST::EnumItemDiscriminant &item)
-{
- auto decl = CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- mappings.insert_canonical_path (item.get_node_id (), cpath);
-}
-
-void
-ResolveItem::visit (AST::StructStruct &struct_decl)
-{
- auto decl
- = CanonicalPath::new_seg (struct_decl.get_node_id (),
- struct_decl.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (struct_decl.get_node_id (), cpath);
-
- resolve_visibility (struct_decl.get_visibility ());
-
- NodeId scope_node_id = struct_decl.get_node_id ();
- resolver->get_type_scope ().push (scope_node_id);
-
- if (struct_decl.has_generics ())
- ResolveGenericParams::go (struct_decl.get_generic_params (), prefix,
- canonical_prefix);
-
- if (struct_decl.has_where_clause ())
- ResolveWhereClause::Resolve (struct_decl.get_where_clause ());
-
- for (AST::StructField &field : struct_decl.get_fields ())
- {
- if (field.get_field_type ().is_marked_for_strip ())
- continue;
-
- resolve_visibility (field.get_visibility ());
-
- ResolveType::go (field.get_field_type ());
- }
-
- resolver->get_type_scope ().pop ();
-}
-
-void
-ResolveItem::visit (AST::Union &union_decl)
-{
- auto decl
- = CanonicalPath::new_seg (union_decl.get_node_id (),
- union_decl.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (union_decl.get_node_id (), cpath);
-
- resolve_visibility (union_decl.get_visibility ());
-
- NodeId scope_node_id = union_decl.get_node_id ();
- resolver->get_type_scope ().push (scope_node_id);
-
- if (union_decl.has_generics ())
- ResolveGenericParams::go (union_decl.get_generic_params (), prefix,
- canonical_prefix);
-
- if (union_decl.has_where_clause ())
- ResolveWhereClause::Resolve (union_decl.get_where_clause ());
-
- for (AST::StructField &field : union_decl.get_variants ())
- {
- if (field.get_field_type ().is_marked_for_strip ())
- continue;
-
- ResolveType::go (field.get_field_type ());
- }
-
- resolver->get_type_scope ().pop ();
-}
-
-void
-ResolveItem::visit (AST::StaticItem &var)
-{
- auto decl = CanonicalPath::new_seg (var.get_node_id (),
- var.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (var.get_node_id (), cpath);
-
- ResolveType::go (var.get_type ());
- ResolveExpr::go (var.get_expr (), path, cpath);
-}
-
-void
-ResolveItem::visit (AST::ConstantItem &constant)
-{
- auto decl = CanonicalPath::new_seg (constant.get_node_id (),
- constant.get_identifier ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (constant.get_node_id (), cpath);
-
- resolve_visibility (constant.get_visibility ());
-
- ResolveType::go (constant.get_type ());
- ResolveExpr::go (constant.get_expr (), path, cpath);
-}
-
-void
-ResolveItem::visit (AST::Function &function)
-{
- auto decl
- = CanonicalPath::new_seg (function.get_node_id (),
- function.get_function_name ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- mappings.insert_canonical_path (function.get_node_id (), cpath);
-
- resolve_visibility (function.get_visibility ());
-
- NodeId scope_node_id = function.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- if (function.has_generics ())
- ResolveGenericParams::go (function.get_generic_params (), prefix,
- canonical_prefix);
-
- // resolve any where clause items
- if (function.has_where_clause ())
- ResolveWhereClause::Resolve (function.get_where_clause ());
-
- if (function.has_return_type ())
- ResolveType::go (function.get_return_type ());
-
- if (function.has_self_param ())
- {
- // self turns into (self: Self) as a function param
- AST::Param &s_param = function.get_self_param ();
- auto &self_param = static_cast<AST::SelfParam &> (s_param);
-
- // FIXME: which location should be used for Rust::Identifier `self`?
- AST::IdentifierPattern self_pattern (
- self_param.get_node_id (), {"self"}, self_param.get_locus (),
- self_param.get_has_ref (), self_param.get_is_mut (),
- std::unique_ptr<AST::Pattern> (nullptr));
- PatternDeclaration::go (self_pattern, Rib::ItemType::Param);
-
- if (self_param.has_type ())
- {
- // This shouldn't happen the parser should already error for this
- rust_assert (!self_param.get_has_ref ());
- ResolveType::go (self_param.get_type ());
- }
- else
- {
- // here we implicitly make self have a type path of Self
- std::vector<std::unique_ptr<AST::TypePathSegment>> segments;
- segments.push_back (std::unique_ptr<AST::TypePathSegment> (
- new AST::TypePathSegment ("Self", false, self_param.get_locus ())));
-
- AST::TypePath self_type_path (std::move (segments),
- self_param.get_locus ());
- ResolveType::go (self_type_path);
- }
- }
-
- std::vector<PatternBinding> bindings
- = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
-
- // we make a new scope so the names of parameters are resolved and shadowed
- // correctly
- for (auto &p : function.get_function_params ())
- {
- if (p->is_variadic ())
- {
- auto &param = static_cast<AST::VariadicParam &> (*p);
- if (param.has_pattern ())
- PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param,
- bindings);
- }
- else if (p->is_self ())
- {
- auto &param = static_cast<AST::SelfParam &> (*p);
- if (param.has_type ())
- ResolveType::go (param.get_type ());
- }
- else
- {
- auto &param = static_cast<AST::FunctionParam &> (*p);
- ResolveType::go (param.get_type ());
- PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param,
- bindings);
- }
- }
-
- // resolve the function body
- ResolveExpr::go (*function.get_definition ().value (), path, cpath);
-
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
-}
-
-void
-ResolveItem::visit (AST::InherentImpl &impl_block)
-{
- NodeId scope_node_id = impl_block.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
-
- resolve_visibility (impl_block.get_visibility ());
-
- if (impl_block.has_generics ())
- ResolveGenericParams::go (impl_block.get_generic_params (), prefix,
- canonical_prefix);
-
- // resolve any where clause items
- if (impl_block.has_where_clause ())
- ResolveWhereClause::Resolve (impl_block.get_where_clause ());
-
- // FIXME this needs to be protected behind nominal type-checks see:
- // rustc --explain E0118
- // issue #2634
- ResolveType::go (impl_block.get_type ());
-
- // Setup paths
- CanonicalPath self_cpath = CanonicalPath::create_empty ();
- bool ok = ResolveTypeToCanonicalPath::go (impl_block.get_type (), self_cpath);
- if (!ok)
- {
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
- return;
- }
-
- rust_debug ("AST::InherentImpl resolve Self: {%s}",
- self_cpath.get ().c_str ());
-
- CanonicalPath impl_type = self_cpath;
- CanonicalPath impl_type_seg
- = CanonicalPath::inherent_impl_seg (impl_block.get_node_id (), impl_type);
- CanonicalPath impl_prefix = prefix.append (impl_type_seg);
-
- // see https://godbolt.org/z/a3vMbsT6W
- CanonicalPath cpath = CanonicalPath::create_empty ();
- if (canonical_prefix.size () <= 1)
- {
- cpath = impl_prefix;
- }
- 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);
- }
-
- // done setup paths
-
- auto Self
- = CanonicalPath::get_big_self (impl_block.get_type ().get_node_id ());
-
- resolver->get_type_scope ().insert (Self,
- impl_block.get_type ().get_node_id (),
- impl_block.get_type ().get_locus ());
-
- for (auto &impl_item : impl_block.get_impl_items ())
- {
- rust_debug (
- "AST::InherentImpl resolve_impl_item: impl_prefix={%s} cpath={%s}",
- impl_prefix.get ().c_str (), cpath.get ().c_str ());
- resolve_impl_item (*impl_item, impl_prefix, cpath);
- }
-
- resolver->get_type_scope ().peek ()->clear_name (
- Self, impl_block.get_type ().get_node_id ());
-
- resolver->get_type_scope ().pop ();
- resolver->get_name_scope ().pop ();
-}
-
-void
-ResolveItem::visit (AST::TraitImpl &impl_block)
-{
- NodeId scope_node_id = impl_block.get_node_id ();
-
- resolve_visibility (impl_block.get_visibility ());
-
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- if (impl_block.has_generics ())
- ResolveGenericParams::go (impl_block.get_generic_params (), prefix,
- canonical_prefix);
-
- // resolve any where clause items
- if (impl_block.has_where_clause ())
- ResolveWhereClause::Resolve (impl_block.get_where_clause ());
-
- // CanonicalPath canonical_trait_type = CanonicalPath::create_empty ();
- NodeId trait_resolved_node = ResolveType::go (impl_block.get_trait_path ());
- if (trait_resolved_node == UNKNOWN_NODEID)
- {
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
- return;
- }
-
- // CanonicalPath canonical_impl_type = CanonicalPath::create_empty ();
- NodeId type_resolved_node = ResolveType::go (impl_block.get_type ());
- if (type_resolved_node == UNKNOWN_NODEID)
- {
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
- return;
- }
-
- bool ok = true;
-
- // setup paths
- CanonicalPath canonical_trait_type = CanonicalPath::create_empty ();
-
- ok = ResolveTypeToCanonicalPath::go (impl_block.get_trait_path (),
- canonical_trait_type);
- if (!ok)
- {
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
- return;
- }
-
- rust_debug ("AST::TraitImpl resolve trait type: {%s}",
- canonical_trait_type.get ().c_str ());
-
- CanonicalPath canonical_impl_type = CanonicalPath::create_empty ();
- ok = ResolveTypeToCanonicalPath::go (impl_block.get_type (),
- canonical_impl_type);
- if (!ok)
- {
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
- return;
- }
-
- rust_debug ("AST::TraitImpl resolve self: {%s}",
- canonical_impl_type.get ().c_str ());
-
- // raw paths
- CanonicalPath impl_type_seg = canonical_impl_type;
- CanonicalPath trait_type_seg = canonical_trait_type;
- CanonicalPath projection
- = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (),
- trait_type_seg, impl_type_seg);
- CanonicalPath impl_prefix = prefix.append (projection);
-
- // setup canonical-path
- CanonicalPath canonical_projection
- = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (),
- canonical_trait_type,
- canonical_impl_type);
- CanonicalPath cpath = CanonicalPath::create_empty ();
- if (canonical_prefix.size () <= 1)
- {
- cpath = canonical_projection;
- }
- 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);
- }
-
- // DONE setup canonical-path
-
- auto Self
- = CanonicalPath::get_big_self (impl_block.get_type ().get_node_id ());
-
- resolver->get_type_scope ().insert (Self,
- impl_block.get_type ().get_node_id (),
- impl_block.get_type ().get_locus ());
-
- for (auto &impl_item : impl_block.get_impl_items ())
- {
- rust_debug (
- "AST::TraitImpl resolve_impl_item: impl_prefix={%s} cpath={%s}",
- impl_prefix.get ().c_str (), cpath.get ().c_str ());
- resolve_impl_item (*impl_item, impl_prefix, cpath);
- }
-
- Rib *r = resolver->get_type_scope ().peek ();
- r->clear_name (Self, impl_block.get_type ().get_node_id ());
-
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
-}
-
-void
-ResolveItem::visit (AST::Trait &trait)
-{
- NodeId scope_node_id = trait.get_node_id ();
-
- resolve_visibility (trait.get_visibility ());
-
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
-
- ResolveGenericParams::go_single (trait.get_implicit_self (), prefix,
- canonical_prefix);
- ResolveGenericParams::go (trait.get_generic_params (), prefix,
- canonical_prefix);
-
- // Self is an implicit TypeParam so lets mark it as such
- resolver->get_type_scope ().append_reference_for_def (
- trait.get_node_id (), trait.get_implicit_self ().get_node_id ());
-
- if (trait.has_type_param_bounds ())
- {
- for (auto &bound : trait.get_type_param_bounds ())
- {
- ResolveTypeBound::go (*bound);
- }
- }
-
- // resolve any where clause items
- if (trait.has_where_clause ())
- ResolveWhereClause::Resolve (trait.get_where_clause ());
-
- // resolve the paths
- CanonicalPath path = CanonicalPath::create_empty ();
- CanonicalPath cpath = CanonicalPath::create_empty ();
- //
-
- for (auto &item : trait.get_trait_items ())
- {
- ResolveTraitItems::go (item.get (), path, cpath);
- }
-
- resolver->get_type_scope ().pop ();
- resolver->get_name_scope ().pop ();
-}
-
-void
-ResolveItem::visit (AST::ExternBlock &extern_block)
-{
- resolve_visibility (extern_block.get_visibility ());
-
- for (auto &item : extern_block.get_extern_items ())
- {
- resolve_extern_item (*item);
- }
-}
-
-void
-ResolveItem::resolve_impl_item (AST::AssociatedItem &item,
- const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
-{
- ResolveImplItems::go (item, prefix, canonical_prefix);
-}
-
-void
-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 (const AST::UseTree *tree, std::vector<Import> &imports)
-{
- switch (tree->get_kind ())
- {
- case AST::UseTree::Glob: {
- auto glob = static_cast<const AST::UseTreeGlob *> (tree);
- flatten_glob (*glob, imports);
- break;
- }
- case AST::UseTree::Rebind: {
- auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
- flatten_rebind (*rebind, imports);
- break;
- }
- case AST::UseTree::List: {
- auto list = static_cast<const AST::UseTreeList *> (tree);
- flatten_list (*list, imports);
- break;
- }
- break;
- }
-}
-
-static void
-flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports)
-{
- if (glob.has_path ())
- imports.emplace_back (glob.get_path (), true, std::string ());
-}
-
-static void
-flatten_rebind (const AST::UseTreeRebind &rebind, std::vector<Import> &imports)
-{
- auto path = rebind.get_path ();
-
- std::string label;
- if (rebind.has_identifier ())
- label = rebind.get_identifier ().as_string ();
- else
- label = path.get_final_segment ().as_string ();
-
- imports.emplace_back (path, false, label);
-}
-
-static void
-flatten_list (const AST::UseTreeList &list, std::vector<Import> &imports)
-{
- auto prefix = AST::SimplePath::create_empty ();
- if (list.has_path ())
- prefix = list.get_path ();
-
- for (const auto &tree : list.get_trees ())
- {
- // append imports to the main list, then modify them in-place
- auto start_idx = imports.size ();
- flatten (tree.get (), imports);
-
- for (auto import = imports.begin () + start_idx; import != imports.end ();
- import++)
- {
- // avoid duplicate node ids
- auto prefix_copy
- = AST::SimplePath ({}, prefix.has_opening_scope_resolution (),
- prefix.get_locus ());
- for (auto &seg : prefix.get_segments ())
- prefix_copy.get_segments ().push_back (
- AST::SimplePathSegment (seg.get_segment_name (),
- seg.get_locus ()));
-
- import->add_prefix (std::move (prefix_copy));
- }
- }
-}
-
-void
-Import::add_prefix (AST::SimplePath prefix)
-{
- AST::SimplePath old_path (std::move (path));
- path = std::move (prefix);
- std::move (old_path.get_segments ().begin (), old_path.get_segments ().end (),
- std::back_inserter (path.get_segments ()));
-}
-
-/**
- * Flatten a UseDeclaration's UseTree into multiple simple paths to resolve.
- *
- * Given the following use declarations:
- * ```
- * use some::path::to_resolve; #1
- * use some::path::to_glob::*; #2
- * use some::path::{one, two}; #2
- * ```
- *
- * In the first case, we simply want to return a vector with a single
- * SimplePath:
- * [some::path::to_resolve]
- *
- * In the second case, we want to resolve the glob's "origin path":
- * [some::path::to_glob]
- *
- * Finally in the third case, we want to create two SimplePaths to resolve:
- * [some::path::one, some::path::two]
- */
-static std::vector<Import>
-flatten_use_dec_to_imports (const AST::UseDeclaration &use_item)
-{
- auto imports = std::vector<Import> ();
-
- const auto &tree = use_item.get_tree ();
- flatten (tree.get (), imports);
-
- return imports;
-}
-
-void
-ResolveItem::visit (AST::UseDeclaration &use_item)
-{
- std::vector<Import> to_resolve = flatten_use_dec_to_imports (use_item);
-
- // FIXME: I think this does not actually resolve glob use-decls and is going
- // the wrong way about it. RFC #1560 specifies the following:
- //
- // > When we find a glob import, we have to record a 'back link', so that when
- // a public name is added for the supplying module, we can add it for the
- // importing module.
- //
- // Which is the opposite of what we're doing if I understand correctly?
-
- NodeId current_module = resolver->peek_current_module_scope ();
- for (auto &import : to_resolve)
- {
- auto &path = import.get_path ();
-
- rust_debug ("resolving use-decl path: [%s]", path.as_string ().c_str ());
- NodeId resolved_node_id = ResolvePath::go (path);
- bool ok = resolved_node_id != UNKNOWN_NODEID;
- if (!ok)
- continue;
-
- if (import.is_glob ())
- continue;
-
- auto decl = CanonicalPath::new_seg (resolved_node_id, import.get_name ());
- mappings.insert_module_child_item (current_module, decl);
-
- resolver->get_type_scope ().insert (decl, resolved_node_id,
- path.get_locus (),
- Rib::ItemType::Type);
- rust_debug ("use-decl rexporting: [%s]", decl.get ().c_str ());
- }
-}
-
-ResolveImplItems::ResolveImplItems (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
- : ResolveItem (prefix, canonical_prefix)
-{}
-
-void
-ResolveImplItems::go (AST::AssociatedItem &item, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
-{
- if (item.is_marked_for_strip ())
- return;
-
- ResolveImplItems resolver (prefix, canonical_prefix);
- item.accept_vis (resolver);
-}
-
-void
-ResolveImplItems::visit (AST::TypeAlias &alias)
-{
- ResolveItem::visit (alias);
-
- resolve_visibility (alias.get_visibility ());
-
- // FIXME this stops the erronious unused decls which will be fixed later on
- resolver->get_type_scope ().append_reference_for_def (alias.get_node_id (),
- alias.get_node_id ());
-}
-
-void
-ResolveExternItem::go (AST::ExternalItem &item, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
-{
- ResolveExternItem resolver (prefix, canonical_prefix);
- item.accept_vis (resolver);
-}
-
-void
-ResolveExternItem::visit (AST::Function &function)
-{
- NodeId scope_node_id = function.get_node_id ();
- auto decl
- = CanonicalPath::new_seg (function.get_node_id (),
- function.get_function_name ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- mappings.insert_canonical_path (function.get_node_id (), cpath);
-
- resolve_visibility (function.get_visibility ());
-
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- // resolve the generics
- if (function.has_generics ())
- ResolveGenericParams::go (function.get_generic_params (), prefix,
- canonical_prefix);
-
- if (function.has_return_type ())
- ResolveType::go (function.get_return_type ());
-
- // we make a new scope so the names of parameters are resolved and shadowed
- // correctly
- for (auto &param : function.get_function_params ())
- if (!param->is_variadic ())
- {
- auto &p = static_cast<AST::FunctionParam &> (*param);
- ResolveType::go (p.get_type ());
- }
-
- // done
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
-}
-
-void
-ResolveExternItem::visit (AST::ExternalStaticItem &item)
-{
- resolve_visibility (item.get_visibility ());
-
- ResolveType::go (item.get_type ());
-}
-
-} // namespace Resolver
-} // namespace Rust
-
-#if CHECKING_P
-
-namespace selftest {
-
-static void
-rust_flatten_nested_glob (void)
-{
- auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION);
- auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION);
- auto foobar = Rust::AST::SimplePath ({foo, bar});
-
- auto glob
- = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED,
- foobar, UNDEF_LOCATION);
-
- auto imports = std::vector<Rust::Resolver::Import> ();
- Rust::Resolver::flatten_glob (glob, imports);
-
- ASSERT_TRUE (!imports.empty ());
- ASSERT_EQ (imports.size (), 1);
- ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo");
- ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar");
-}
-
-static void
-rust_flatten_glob (void)
-{
- auto frob = Rust::AST::SimplePath::from_str ("frobulator", UNDEF_LOCATION);
-
- auto glob
- = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED,
- frob, UNDEF_LOCATION);
-
- auto imports = std::vector<Rust::Resolver::Import> ();
- Rust::Resolver::flatten_glob (glob, imports);
-
- ASSERT_TRUE (!imports.empty ());
- ASSERT_EQ (imports.size (), 1);
- ASSERT_EQ (imports[0].get_path (), "frobulator");
-}
-
-static void
-rust_flatten_rebind_none (void)
-{
- auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION);
- auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION);
- auto foobar = Rust::AST::SimplePath ({foo, bar});
-
- auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE,
- foobar, UNDEF_LOCATION);
-
- auto imports = std::vector<Rust::Resolver::Import> ();
- Rust::Resolver::flatten_rebind (rebind, imports);
-
- ASSERT_TRUE (!imports.empty ());
- ASSERT_EQ (imports.size (), 1);
- ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo");
- ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar");
-}
-
-static void
-rust_flatten_rebind (void)
-{
- auto frob = Rust::AST::SimplePath::from_str ("frobulator", UNDEF_LOCATION);
-
- auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER,
- frob, UNDEF_LOCATION, {"saindoux"});
-
- auto imports = std::vector<Rust::Resolver::Import> ();
- Rust::Resolver::flatten_rebind (rebind, imports);
-
- ASSERT_TRUE (!imports.empty ());
- ASSERT_EQ (imports.size (), 1);
- ASSERT_EQ (imports[0].get_path (), "frobulator");
- ASSERT_EQ (imports[0].get_name (), "saindoux");
-}
-
-static void
-rust_flatten_rebind_nested (void)
-{
- auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION);
- auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION);
- auto baz = Rust::AST::SimplePathSegment ("baz", UNDEF_LOCATION);
-
- auto foo_bar_baz = Rust::AST::SimplePath ({foo, bar, baz});
-
- auto rebind
- = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER,
- foo_bar_baz, UNDEF_LOCATION, {"saindoux"});
-
- auto imports = std::vector<Rust::Resolver::Import> ();
- Rust::Resolver::flatten_rebind (rebind, imports);
-
- ASSERT_TRUE (!imports.empty ());
- ASSERT_EQ (imports.size (), 1);
- ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo");
- ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar");
- ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz");
- ASSERT_EQ (imports[0].get_name (), "saindoux");
-}
-
-static void
-rust_flatten_list (void)
-{
- auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION);
- auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION);
- auto foo_bar = Rust::AST::SimplePath ({foo, bar});
-
- auto baz = Rust::AST::SimplePath::from_str ("baz", UNDEF_LOCATION);
- auto bul = Rust::AST::SimplePath::from_str ("bul", UNDEF_LOCATION);
-
- // use foo::bar::{baz, bul};
-
- auto use0 = std::unique_ptr<Rust::AST::UseTree> (
- new Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, baz,
- UNDEF_LOCATION));
- auto use1 = std::unique_ptr<Rust::AST::UseTree> (
- new Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, bul,
- UNDEF_LOCATION));
-
- auto uses = std::vector<std::unique_ptr<Rust::AST::UseTree>> ();
- uses.emplace_back (std::move (use0));
- uses.emplace_back (std::move (use1));
-
- auto list
- = Rust::AST::UseTreeList (Rust::AST::UseTreeList::PATH_PREFIXED, foo_bar,
- std::move (uses), UNDEF_LOCATION);
-
- auto imports = std::vector<Rust::Resolver::Import> ();
- Rust::Resolver::flatten_list (list, imports);
-
- ASSERT_TRUE (!imports.empty ());
- ASSERT_EQ (imports.size (), 2);
- ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo");
- ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar");
- ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz");
- ASSERT_EQ (imports[1].get_path ().get_segments ()[0].as_string (), "foo");
- ASSERT_EQ (imports[1].get_path ().get_segments ()[1].as_string (), "bar");
- ASSERT_EQ (imports[1].get_path ().get_segments ()[2].as_string (), "bul");
-}
-
-static void
-rust_use_dec_flattening (void)
-{
- rust_flatten_glob ();
- rust_flatten_nested_glob ();
- rust_flatten_rebind_none ();
- rust_flatten_rebind ();
- rust_flatten_rebind_nested ();
- rust_flatten_list ();
-}
-
-void
-rust_simple_path_resolve_test (void)
-{
- rust_use_dec_flattening ();
-}
-
-} // namespace selftest
-
-#endif // CHECKING_P
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
deleted file mode 100644
index 776dd53..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_RESOLVE_ITEM_H
-#define RUST_AST_RESOLVE_ITEM_H
-
-#include "rust-ast-full-decls.h"
-#include "rust-ast-resolve-base.h"
-
-#include "config.h"
-
-namespace Rust {
-namespace Resolver {
-
-class ResolveTraitItems : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void go (AST::AssociatedItem *item, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix);
-
- void visit (AST::Function &type) override;
- void visit (AST::TraitItemType &type) override;
- void visit (AST::TraitItemConst &constant) override;
-
-private:
- ResolveTraitItems (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix);
-
- const CanonicalPath &prefix;
- const CanonicalPath &canonical_prefix;
-};
-
-class ResolveItem : public ResolverBase
-{
-public:
- using Rust::Resolver::ResolverBase::visit;
-
- static void go (AST::Item &item, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix);
-
- void visit (AST::TypeAlias &alias) override;
- void visit (AST::Module &module) override;
- void visit (AST::TupleStruct &struct_decl) override;
- void visit (AST::Enum &enum_decl) override;
- /* EnumItem doesn't need to be handled, no fields. */
- void visit (AST::EnumItem &item) override;
- void visit (AST::EnumItemTuple &item) override;
- void visit (AST::EnumItemStruct &item) override;
- void visit (AST::EnumItemDiscriminant &item) override;
- void visit (AST::StructStruct &struct_decl) override;
- void visit (AST::Union &union_decl) override;
- void visit (AST::StaticItem &var) override;
- void visit (AST::ConstantItem &constant) override;
- void visit (AST::Function &function) override;
- void visit (AST::InherentImpl &impl_block) override;
- void visit (AST::TraitImpl &impl_block) override;
- void visit (AST::Trait &trait) override;
- void visit (AST::ExternBlock &extern_block) override;
- void visit (AST::UseDeclaration &) override;
-
-protected:
- void resolve_impl_item (AST::AssociatedItem &item,
- const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix);
- void resolve_extern_item (AST::ExternalItem &item);
-
- ResolveItem (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix);
-
- const CanonicalPath &prefix;
- const CanonicalPath &canonical_prefix;
-};
-
-class ResolveImplItems : public ResolveItem
-{
- using Rust::Resolver::ResolveItem::visit;
-
-public:
- static void go (AST::AssociatedItem &item, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix);
-
- void visit (AST::TypeAlias &alias) override;
-
-private:
- ResolveImplItems (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix);
-};
-
-class ResolveExternItem : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void go (AST::ExternalItem &item, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix);
-
- void visit (AST::Function &function) override;
- void visit (AST::ExternalStaticItem &item) override;
-
-private:
- ResolveExternItem (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
- : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
- {}
-
- const CanonicalPath &prefix;
- const CanonicalPath &canonical_prefix;
-};
-
-class Import
-{
-public:
- Import (AST::SimplePath path, bool is_glob, std::string name)
- : path (path), is_glob_f (is_glob), name (name)
- {}
-
- AST::SimplePath &get_path () { return path; }
-
- const AST::SimplePath &get_path () const { return path; }
-
- bool is_glob () const { return is_glob_f; }
-
- const std::string &get_name () const { return name; }
-
- void add_prefix (AST::SimplePath prefix);
-
-private:
- AST::SimplePath path;
- bool is_glob_f;
- std::string name;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#if CHECKING_P
-
-namespace selftest {
-extern void
-rust_simple_path_resolve_test (void);
-} // namespace selftest
-
-#endif // CHECKING_P
-
-#endif // RUST_AST_RESOLVE_ITEM_H
diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc
deleted file mode 100644
index 530926d..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-path.cc
+++ /dev/null
@@ -1,558 +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-resolve-path.h"
-#include "rust-ast-resolve-type.h"
-#include "rust-hir-map.h"
-#include "rust-path.h"
-
-namespace Rust {
-namespace Resolver {
-
-ResolvePath::ResolvePath () : ResolverBase () {}
-
-NodeId
-ResolvePath::go (AST::PathInExpression &expr)
-{
- ResolvePath resolver;
- return resolver.resolve_path (expr);
-}
-
-NodeId
-ResolvePath::go (AST::QualifiedPathInExpression &expr)
-{
- ResolvePath resolver;
- return resolver.resolve_path (expr);
-}
-
-NodeId
-ResolvePath::go (AST::SimplePath &expr)
-{
- ResolvePath resolver;
- return resolver.resolve_path (expr);
-}
-
-NodeId
-ResolvePath::resolve_path (AST::PathInExpression &expr)
-{
- if (expr.is_lang_item ())
- return Analysis::Mappings::get ().get_lang_item_node (
- expr.get_lang_item ());
-
- NodeId resolved_node_id = UNKNOWN_NODEID;
- NodeId module_scope_id = resolver->peek_current_module_scope ();
- NodeId previous_resolved_node_id = module_scope_id;
- for (size_t i = 0; i < expr.get_segments ().size (); i++)
- {
- auto &segment = expr.get_segments ().at (i);
- const AST::PathIdentSegment &ident_seg = segment.get_ident_segment ();
- bool is_first_segment = i == 0;
- resolved_node_id = UNKNOWN_NODEID;
-
- bool in_middle_of_path = i > 0;
- if (in_middle_of_path && segment.is_lower_self_seg ())
- {
- rust_error_at (segment.get_locus (), ErrorCode::E0433,
- "leading path segment %qs can only be used at the "
- "beginning of a path",
- segment.as_string ().c_str ());
- return UNKNOWN_NODEID;
- }
-
- NodeId crate_scope_id = resolver->peek_crate_module_scope ();
- if (segment.is_crate_path_seg ())
- {
- // what is the current crate scope node id?
- module_scope_id = crate_scope_id;
- previous_resolved_node_id = module_scope_id;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == module_scope_id);
- else
- resolver->insert_resolved_name (segment.get_node_id (),
- module_scope_id);
- continue;
- }
- else if (segment.is_super_path_seg ())
- {
- if (module_scope_id == crate_scope_id)
- {
- rust_error_at (segment.get_locus (),
- "cannot use %<super%> at the crate scope");
- return UNKNOWN_NODEID;
- }
-
- module_scope_id = resolver->peek_parent_module_scope ();
- previous_resolved_node_id = module_scope_id;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == module_scope_id);
- else
- resolver->insert_resolved_name (segment.get_node_id (),
- module_scope_id);
- continue;
- }
-
- // resolve any generic args
- if (segment.has_generic_args ())
- ResolveGenericArgs::go (segment.get_generic_args ());
-
- // logic is awkward here there are a few cases
- //
- // T::Default
- // mod::foo::impl_item
- // super::super::module::item
- // self
- // self::foo
- // self::foo::baz
- //
- // T::Default we can only resolve the T and cant do anything about Default
- // its dependant on associated types
- //
- // mod::foo::impl_item
- // we can resolve mod::foo but nothing about impl_item but we need to
- // _always resolve generic arguments
- //
- // self is a simple single lookup
- //
- // we have module_scope_id for the next module_scope to lookup
- // resolved_node_id is the thing we have resolve this segment to
- //
- // new algo?
- // we can only use module resolution when the previous segment is either
- // unknown or equal to this module_scope_id
- //
- // can only use old resolution when previous segment is unkown
-
- if (is_first_segment)
- {
- // name scope first
- NodeId resolved_node = UNKNOWN_NODEID;
- const CanonicalPath path
- = CanonicalPath::new_seg (segment.get_node_id (),
- ident_seg.as_string ());
- if (resolver->get_name_scope ().lookup (path, &resolved_node))
- {
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node);
- else
- resolver->insert_resolved_name (segment.get_node_id (),
- resolved_node);
- resolved_node_id = resolved_node;
- }
- // check the type scope
- else if (resolver->get_type_scope ().lookup (path, &resolved_node))
- {
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_type (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node);
- else
- resolver->insert_resolved_type (segment.get_node_id (),
- resolved_node);
- resolved_node_id = resolved_node;
- }
- else if (segment.is_lower_self_seg ())
- {
- module_scope_id = crate_scope_id;
- previous_resolved_node_id = module_scope_id;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == module_scope_id);
- else
- resolver->insert_resolved_name (segment.get_node_id (),
- module_scope_id);
- continue;
- }
- else
- {
- // no error handling here since we might be able to resolve via
- // the module hierarchy and handle errors at the end
- }
- }
-
- if (resolved_node_id == UNKNOWN_NODEID
- && previous_resolved_node_id == module_scope_id)
- {
- tl::optional<CanonicalPath &> resolved_child
- = mappings.lookup_module_child (module_scope_id,
- ident_seg.as_string ());
- if (resolved_child.has_value ())
- {
- NodeId resolved_node = resolved_child->get_node_id ();
- if (resolver->get_name_scope ().decl_was_declared_here (
- resolved_node))
- {
- resolved_node_id = resolved_node;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok
- = resolver->lookup_resolved_name (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node);
- else
- resolver->insert_resolved_name (segment.get_node_id (),
- resolved_node);
- }
- else if (resolver->get_type_scope ().decl_was_declared_here (
- resolved_node))
- {
- resolved_node_id = resolved_node;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok
- = resolver->lookup_resolved_type (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node);
- else
- resolver->insert_resolved_type (segment.get_node_id (),
- resolved_node);
- }
- else
- {
- rust_error_at (segment.get_locus (),
- "Cannot find path %<%s%> in this scope",
- segment.as_string ().c_str ());
- return UNKNOWN_NODEID;
- }
- }
- }
-
- bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID;
- if (did_resolve_segment)
- {
- if (mappings.node_is_module (resolved_node_id)
- || mappings.node_is_crate (resolved_node_id))
- {
- module_scope_id = resolved_node_id;
- }
- previous_resolved_node_id = resolved_node_id;
- }
- else if (is_first_segment)
- {
- rust_error_at (segment.get_locus (), ErrorCode::E0433,
- "Cannot find path %<%s%> in this scope",
- segment.as_string ().c_str ());
- return UNKNOWN_NODEID;
- }
- }
-
- resolved_node = resolved_node_id;
- if (resolved_node_id != UNKNOWN_NODEID)
- {
- // name scope first
- if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
- {
- NodeId existing = UNKNOWN_NODEID;
- bool ok
- = resolver->lookup_resolved_name (expr.get_node_id (), &existing);
-
- if (ok)
- rust_assert (existing == resolved_node_id);
- else
- resolver->insert_resolved_name (expr.get_node_id (),
- resolved_node_id);
- }
- // check the type scope
- else if (resolver->get_type_scope ().decl_was_declared_here (
- resolved_node_id))
- {
- NodeId existing = UNKNOWN_NODEID;
- bool ok
- = resolver->lookup_resolved_type (expr.get_node_id (), &existing);
-
- if (ok)
- rust_assert (existing == resolved_node_id);
- else
- resolver->insert_resolved_type (expr.get_node_id (),
- resolved_node_id);
- }
- else
- {
- rust_unreachable ();
- }
- }
- return resolved_node_id;
-}
-
-NodeId
-ResolvePath::resolve_path (AST::QualifiedPathInExpression &expr)
-{
- auto &root_segment = expr.get_qualified_path_type ();
- ResolveType::go (root_segment.get_type ());
- if (root_segment.has_as_clause ())
- ResolveType::go (root_segment.get_as_type_path ());
-
- for (auto &segment : expr.get_segments ())
- {
- // we cant actually do anything with the segment itself since this is all
- // the job of the type system to figure it out but we can resolve any
- // generic arguments used
- if (segment.has_generic_args ())
- ResolveGenericArgs::go (segment.get_generic_args ());
- }
-
- // cannot fully resolve a qualified path as it is dependant on associated
- // items
- return UNKNOWN_NODEID;
-}
-
-NodeId
-ResolvePath::resolve_path (AST::SimplePath &expr)
-{
- NodeId crate_scope_id = resolver->peek_crate_module_scope ();
- NodeId module_scope_id = resolver->peek_current_module_scope ();
-
- NodeId previous_resolved_node_id = UNKNOWN_NODEID;
- NodeId resolved_node_id = UNKNOWN_NODEID;
- for (size_t i = 0; i < expr.get_segments ().size (); i++)
- {
- AST::SimplePathSegment &segment = expr.get_segments ().at (i);
- bool is_first_segment = i == 0;
- bool is_final_segment = i >= (expr.get_segments ().size () - 1);
- resolved_node_id = UNKNOWN_NODEID;
-
- if (segment.is_crate_path_seg ())
- {
- // what is the current crate scope node id?
- module_scope_id = crate_scope_id;
- previous_resolved_node_id = module_scope_id;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == module_scope_id);
- else
- resolver->insert_resolved_name (segment.get_node_id (),
- module_scope_id);
- resolved_node_id = module_scope_id;
-
- continue;
- }
- else if (segment.is_super_path_seg ())
- {
- if (!is_first_segment)
- {
- rust_error_at (segment.get_locus (),
- "%<super%> can only be used in start position");
- return UNKNOWN_NODEID;
- }
- if (module_scope_id == crate_scope_id)
- {
- rust_error_at (segment.get_locus (),
- "cannot use %<super%> at the crate scope");
- return UNKNOWN_NODEID;
- }
-
- module_scope_id = resolver->peek_parent_module_scope ();
- previous_resolved_node_id = module_scope_id;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == module_scope_id);
- else
- resolver->insert_resolved_name (segment.get_node_id (),
- module_scope_id);
- resolved_node_id = module_scope_id;
-
- continue;
- }
-
- tl::optional<CanonicalPath &> resolved_child
- = mappings.lookup_module_child (module_scope_id,
- segment.get_segment_name ());
- if (resolved_child.has_value ())
- {
- NodeId resolved_node = resolved_child->get_node_id ();
- if (resolver->get_name_scope ().decl_was_declared_here (
- resolved_node))
- {
- resolved_node_id = resolved_node;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node);
- else
- resolver->insert_resolved_name (segment.get_node_id (),
- resolved_node);
- }
- else if (resolver->get_type_scope ().decl_was_declared_here (
- resolved_node))
- {
- resolved_node_id = resolved_node;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_type (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node);
- else
- resolver->insert_resolved_type (segment.get_node_id (),
- resolved_node);
- }
- else
- {
- rust_error_at (segment.get_locus (),
- "Cannot find path %<%s%> in this scope",
- segment.as_string ().c_str ());
- return UNKNOWN_NODEID;
- }
- }
-
- if (resolved_node_id == UNKNOWN_NODEID && is_first_segment)
- {
- // name scope first
- NodeId resolved_node = UNKNOWN_NODEID;
- const CanonicalPath path
- = CanonicalPath::new_seg (segment.get_node_id (),
- segment.get_segment_name ());
- if (resolver->get_name_scope ().lookup (path, &resolved_node))
- {
- resolved_node_id = resolved_node;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node);
- else
- resolver->insert_resolved_name (segment.get_node_id (),
- resolved_node);
- }
- // check the type scope
- else if (resolver->get_type_scope ().lookup (path, &resolved_node))
- {
- resolved_node_id = resolved_node;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_type (segment.get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node);
- else
- resolver->insert_resolved_type (segment.get_node_id (),
- resolved_node);
- }
- }
-
- // if we still have not resolved and this is the final segment and the
- // final segment is self its likely the case: pub use
- //
- // result::Result::{self, Err, Ok};
- //
- // Then the resolved_node_id is just the previous one so long as it is a
- // resolved node id
- // rust_debug_loc (segment.get_locus (),
- // "trying to resolve seg: [%s] first [%s] last [%s]",
- // segment.get_segment_name ().c_str (),
- // is_first_segment ? "true" : "false",
- // is_final_segment ? "true" : "false");
- if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment
- && is_final_segment && segment.is_lower_self_seg ())
- resolved_node_id = previous_resolved_node_id;
-
- // final check
- if (resolved_node_id == UNKNOWN_NODEID)
- {
- rust_error_at (segment.get_locus (),
- "cannot find simple path segment %<%s%> in this scope",
- segment.as_string ().c_str ());
- return UNKNOWN_NODEID;
- }
-
- if (mappings.node_is_module (resolved_node_id))
- {
- module_scope_id = resolved_node_id;
- }
-
- previous_resolved_node_id = resolved_node_id;
- }
-
- resolved_node = resolved_node_id;
- if (resolved_node_id != UNKNOWN_NODEID)
- {
- // name scope first
- if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
- {
- NodeId existing = UNKNOWN_NODEID;
- bool ok
- = resolver->lookup_resolved_name (expr.get_node_id (), &existing);
-
- if (ok)
- rust_assert (existing == resolved_node_id);
- else
- resolver->insert_resolved_name (expr.get_node_id (),
- resolved_node_id);
- }
- // check the type scope
- else if (resolver->get_type_scope ().decl_was_declared_here (
- resolved_node_id))
- {
- NodeId existing = UNKNOWN_NODEID;
- bool ok
- = resolver->lookup_resolved_type (expr.get_node_id (), &existing);
-
- if (ok)
- rust_assert (existing == resolved_node_id);
- else
- resolver->insert_resolved_type (expr.get_node_id (),
- resolved_node_id);
- }
- else
- {
- rust_unreachable ();
- }
- }
- return resolved_node_id;
-}
-
-} // namespace Resolver
-} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-path.h b/gcc/rust/resolve/rust-ast-resolve-path.h
deleted file mode 100644
index cddb54a..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-path.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_RESOLVE_PATH_H
-#define RUST_AST_RESOLVE_PATH_H
-
-#include "rust-ast-resolve-base.h"
-
-namespace Rust {
-namespace Resolver {
-
-class ResolvePath : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static NodeId go (AST::PathInExpression &expr);
- static NodeId go (AST::QualifiedPathInExpression &expr);
- static NodeId go (AST::SimplePath &expr);
-
-private:
- ResolvePath ();
-
- NodeId resolve_path (AST::PathInExpression &expr);
- NodeId resolve_path (AST::QualifiedPathInExpression &expr);
- NodeId resolve_path (AST::SimplePath &expr);
-
- void
- resolve_simple_path_segments (CanonicalPath prefix, size_t offs,
- const std::vector<AST::SimplePathSegment> &segs,
- NodeId expr_node_id, location_t expr_locus);
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // !RUST_AST_RESOLVE_PATH_H
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
deleted file mode 100644
index ee84be8..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc
+++ /dev/null
@@ -1,384 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-ast-resolve-pattern.h"
-#include "rust-ast-resolve-path.h"
-
-namespace Rust {
-namespace Resolver {
-
-void
-PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type)
-{
- std::vector<PatternBinding> bindings
- = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
- PatternDeclaration::go (pattern, type, bindings);
-}
-
-void
-PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type,
- std::vector<PatternBinding> &bindings)
-{
- PatternDeclaration resolver (bindings, type);
- pattern.accept_vis (resolver);
-
- for (auto &map_entry : resolver.missing_bindings)
- {
- auto ident = map_entry.first; // key
- auto info = map_entry.second; // value
-
- rust_error_at (info.get_locus (), ErrorCode::E0408,
- "variable '%s' is not bound in all patterns",
- ident.as_string ().c_str ());
- }
-
- for (auto &map_entry : resolver.inconsistent_bindings)
- {
- auto ident = map_entry.first; // key
- auto info = map_entry.second; // value
-
- rust_error_at (
- info.get_locus (), ErrorCode::E0409,
- "variable '%s' is bound inconsistently across pattern alternatives",
- ident.as_string ().c_str ());
- }
-}
-
-void
-PatternDeclaration::visit (AST::IdentifierPattern &pattern)
-{
- 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 (),
- pattern.get_locus ()));
-}
-
-void
-PatternDeclaration::visit (AST::GroupedPattern &pattern)
-{
- pattern.get_pattern_in_parens ().accept_vis (*this);
-}
-
-void
-PatternDeclaration::visit (AST::ReferencePattern &pattern)
-{
- pattern.get_referenced_pattern ().accept_vis (*this);
-}
-
-void
-PatternDeclaration::visit (AST::PathInExpression &pattern)
-{
- ResolvePath::go (pattern);
-}
-
-void
-PatternDeclaration::visit (AST::TupleStructPattern &pattern)
-{
- ResolvePath::go (pattern.get_path ());
-
- AST::TupleStructItems &items = pattern.get_items ();
- switch (items.get_item_type ())
- {
- case AST::TupleStructItems::RANGE: {
- // TODO
- rust_unreachable ();
- }
- break;
-
- case AST::TupleStructItems::NO_RANGE: {
- auto &items_no_range
- = static_cast<AST::TupleStructItemsNoRange &> (items);
-
- for (auto &inner_pattern : items_no_range.get_patterns ())
- {
- inner_pattern->accept_vis (*this);
- }
- }
- break;
- }
-}
-
-void
-PatternDeclaration::visit (AST::StructPattern &pattern)
-{
- ResolvePath::go (pattern.get_path ());
-
- auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
- for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
- {
- switch (field->get_item_type ())
- {
- case AST::StructPatternField::ItemType::TUPLE_PAT: {
- AST::StructPatternFieldTuplePat &tuple
- = static_cast<AST::StructPatternFieldTuplePat &> (*field);
-
- tuple.get_index_pattern ().accept_vis (*this);
- }
- break;
-
- case AST::StructPatternField::ItemType::IDENT_PAT: {
- AST::StructPatternFieldIdentPat &ident
- = static_cast<AST::StructPatternFieldIdentPat &> (*field);
-
- ident.get_ident_pattern ().accept_vis (*this);
- }
- break;
-
- case AST::StructPatternField::ItemType::IDENT: {
- auto &ident = static_cast<AST::StructPatternFieldIdent &> (*field);
-
- Mutability mut
- = ident.is_mut () ? Mutability::Mut : Mutability::Imm;
-
- add_new_binding (ident.get_identifier (), ident.get_node_id (),
- BindingTypeInfo (mut, ident.is_ref (),
- ident.get_locus ()));
- }
- break;
- }
- }
-}
-
-void
-PatternDeclaration::visit (AST::TuplePattern &pattern)
-{
- auto &items = pattern.get_items ();
- switch (items.get_pattern_type ())
- {
- case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
- auto &ref = static_cast<AST::TuplePatternItemsMultiple &> (
- pattern.get_items ());
-
- for (auto &p : ref.get_patterns ())
- p->accept_vis (*this);
- }
- break;
-
- case AST::TuplePatternItems::TuplePatternItemType::RANGED: {
- auto &ref
- = static_cast<AST::TuplePatternItemsRanged &> (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;
- }
-}
-
-void
-PatternDeclaration::visit (AST::AltPattern &pattern)
-{
- // push a new set of 'Or' bindings to the stack. Accounts for the
- // alternatives. e.g. in `p_0 | p_1`, bindings to the same identifier between
- // p_0 and p_1 shouldn't cause an error.
- bindings_with_ctx.push_back (
- PatternBinding (PatternBoundCtx::Or, std::set<Identifier> ()));
-
- // This is a hack to avoid creating a separate visitor class for the
- // consistency checks. We empty out the binding_info_map before each iteration
- // to separate between the alts' binding_maps. And right after the alt
- // visit...
- auto tmp_binding_map = binding_info_map;
- binding_info_map.clear ();
-
- std::vector<BindingMap> alts_binding_maps;
-
- for (auto &alt : pattern.get_alts ())
- {
- // before this visit, the binding_info_map is guaranteed to be empty
- rust_assert (binding_info_map.empty ());
-
- // push a new `Product` context to correctly reject multiple bindings
- // within this single alt.
- bindings_with_ctx.push_back (
- PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ()));
-
- alt->accept_vis (*this);
-
- // ...the binding_info_map is (potentially) populated. We copy it to the
- // vector, and empty it out to be ready for the next iteration. And after
- // all the iterations are finished...
- alts_binding_maps.push_back (binding_info_map);
- binding_info_map.clear ();
-
- // Remove the last (i.e. `Product`) context and add the bindings from the
- // visited alt to the one before last (i.e. `Or`). Now (after checking
- // with the alt internally), the bindings from this alt will reside in the
- // `Or` context.
- auto last_bound_idents = bindings_with_ctx.back ().idents;
- bindings_with_ctx.pop_back ();
-
- for (auto &ident : last_bound_idents)
- {
- bindings_with_ctx.back ().idents.insert (ident);
- }
- }
-
- // Now we can finally check for consistency.
- check_bindings_consistency (alts_binding_maps);
-
- // Now we remove the `Or` context we pushed earlier.
- // e.g. in `(a, (p_0 | p_1), c)`: after finishing up inside the alt pattern,
- // we return to the tuple (`Product`) context and push the new bindings.
- auto idents = bindings_with_ctx.back ().idents;
- bindings_with_ctx.pop_back ();
- for (auto &ident : idents)
- bindings_with_ctx.back ().idents.insert (ident.as_string ());
-
- // ...we repopulate the binding_info_map correctly (the initial bindings
- // stored in the tmp_binding_map + all the bindings from all the alts)
- binding_info_map = tmp_binding_map;
- for (auto &alt_map : alts_binding_maps)
- for (auto &map_entry : alt_map)
- binding_info_map.insert (map_entry);
-}
-
-void
-PatternDeclaration::add_new_binding (Identifier ident, NodeId node_id,
- BindingTypeInfo info)
-{
- bool has_binding_ctx = bindings_with_ctx.size () > 0;
- rust_assert (has_binding_ctx);
-
- bool identifier_or_bound = false, identifier_product_bound = false;
-
- for (auto binding : bindings_with_ctx)
- {
- bool identifier_bound_here
- = (binding.idents.find (ident) != binding.idents.end ());
- if (identifier_bound_here)
- {
- identifier_product_bound |= binding.ctx == PatternBoundCtx::Product;
- identifier_or_bound |= binding.ctx == PatternBoundCtx::Or;
- }
- }
-
- if (identifier_product_bound)
- {
- if (type == Rib::ItemType::Param)
- {
- rust_error_at (info.get_locus (), ErrorCode::E0415,
- "identifier '%s' is bound more than once in the "
- "same parameter list",
- ident.as_string ().c_str ());
- }
- else
- {
- rust_error_at (
- info.get_locus (), ErrorCode::E0416,
- "identifier '%s' is bound more than once in the same pattern",
- ident.as_string ().c_str ());
- }
-
- return;
- }
-
- if (!identifier_or_bound)
- {
- bindings_with_ctx.back ().idents.insert (ident);
- resolver->get_name_scope ().insert (
- CanonicalPath::new_seg (node_id, ident.as_string ()), node_id,
- info.get_locus (), type);
- }
-
- binding_info_map.insert ({ident, info});
-}
-
-// Verifies that all the alts in an AltPattern have the same set of bindings
-// with the same mutability and reference states.
-void
-PatternDeclaration::check_bindings_consistency (
- std::vector<BindingMap> &binding_maps)
-{
- for (size_t i = 0; i < binding_maps.size (); i++)
- {
- auto &outer_bindings_map = binding_maps[i];
-
- for (size_t j = 0; j < binding_maps.size (); j++)
- {
- // skip comparing the current outer map with itself.
- if (j == i)
- continue;
-
- auto &inner_bindings_map = binding_maps[j];
-
- // iterate over the inner map entries and check if they exist in outer
- // map
- for (auto map_entry : inner_bindings_map)
- {
- auto ident = map_entry.first; // key
- auto inner_info = map_entry.second; // value
- bool ident_is_outer_bound = outer_bindings_map.count (ident);
-
- if (!ident_is_outer_bound && !missing_bindings.count (ident))
- missing_bindings.insert ({ident, inner_info});
-
- else if (outer_bindings_map.count (ident)
- && outer_bindings_map[ident] != inner_info
- && !inconsistent_bindings.count (ident))
- inconsistent_bindings.insert ({ident, inner_info});
- }
- }
- }
-}
-
-static void
-resolve_range_pattern_bound (AST::RangePatternBound &bound)
-{
- switch (bound.get_bound_type ())
- {
- case AST::RangePatternBound::RangePatternBoundType::LITERAL:
- // Nothing to resolve for a literal.
- break;
-
- case AST::RangePatternBound::RangePatternBoundType::PATH: {
- auto &ref = static_cast<AST::RangePatternBoundPath &> (bound);
-
- ResolvePath::go (ref.get_path ());
- }
- break;
-
- case AST::RangePatternBound::RangePatternBoundType::QUALPATH: {
- auto &ref = static_cast<AST::RangePatternBoundQualPath &> (bound);
-
- ResolvePath::go (ref.get_qualified_path ());
- }
- break;
- }
-}
-
-void
-PatternDeclaration::visit (AST::RangePattern &pattern)
-{
- resolve_range_pattern_bound (pattern.get_upper_bound ());
- resolve_range_pattern_bound (pattern.get_lower_bound ());
-}
-
-void
-PatternDeclaration::visit (AST::SlicePattern &pattern)
-{
- for (auto &p : pattern.get_items ())
- {
- p->accept_vis (*this);
- }
-}
-
-} // namespace Resolver
-} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h
deleted file mode 100644
index 876de16..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_RESOLVE_PATTERN_H
-#define RUST_AST_RESOLVE_PATTERN_H
-
-#include "rust-ast-resolve-base.h"
-#include "rust-ast-full.h"
-
-namespace Rust {
-namespace Resolver {
-
-// Specifies whether the set of already bound patterns are related by 'Or' or
-// 'Product'. Used to check for multiple bindings to the same identifier.
-enum PatternBoundCtx
-{
- // A product pattern context (e.g. struct and tuple patterns)
- Product,
- // An or-pattern context (e.g. p_0 | p_1 | ...)
- Or,
-};
-
-struct PatternBinding
-{
- PatternBoundCtx ctx;
- std::set<Identifier> idents;
-
- PatternBinding (PatternBoundCtx ctx, std::set<Identifier> idents)
- : ctx (ctx), idents (idents)
- {}
-};
-
-// Info that gets stored in the map. Helps us detect if two bindings to the same
-// identifier have different mutability or ref states.
-class BindingTypeInfo
-{
- Mutability mut;
- bool is_ref;
- location_t locus;
-
-public:
- BindingTypeInfo (Mutability mut, bool is_ref, location_t locus)
- : mut (mut), is_ref (is_ref), locus (locus)
- {}
-
- BindingTypeInfo (BindingTypeInfo const &other)
- : mut (other.mut), is_ref (other.is_ref), locus (other.get_locus ())
- {}
-
- BindingTypeInfo (){};
-
- location_t get_locus () const { return locus; }
- Mutability get_mut () const { return mut; }
- bool get_is_ref () const { return is_ref; }
-
- BindingTypeInfo operator= (BindingTypeInfo const &other)
- {
- mut = other.mut;
- is_ref = other.is_ref;
- locus = other.get_locus ();
-
- return *this;
- }
-
- bool operator== (BindingTypeInfo const &other)
- {
- return mut == other.mut && is_ref == other.is_ref;
- }
-
- bool operator!= (BindingTypeInfo const &other)
- {
- return !BindingTypeInfo::operator== (other);
- }
-};
-
-typedef std::map<Identifier, BindingTypeInfo> BindingMap;
-
-class PatternDeclaration : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void go (AST::Pattern &pattern, Rib::ItemType type);
- static void go (AST::Pattern &pattern, Rib::ItemType type,
- std::vector<PatternBinding> &bindings);
-
- void visit (AST::IdentifierPattern &pattern) override;
- void visit (AST::GroupedPattern &pattern) override;
- void visit (AST::ReferencePattern &pattern) override;
- void visit (AST::PathInExpression &pattern) override;
- void visit (AST::StructPattern &pattern) override;
- void visit (AST::TupleStructPattern &pattern) override;
- void visit (AST::TuplePattern &pattern) override;
- void visit (AST::RangePattern &pattern) override;
- void visit (AST::AltPattern &pattern) override;
- void visit (AST::SlicePattern &pattern) override;
-
- void add_new_binding (Identifier ident, NodeId node_id, BindingTypeInfo info);
- void check_bindings_consistency (std::vector<BindingMap> &binding_maps);
-
-private:
- PatternDeclaration (std::vector<PatternBinding> &bindings_with_ctx,
- Rib::ItemType type)
- : ResolverBase (), bindings_with_ctx (bindings_with_ctx), type (type)
- {}
-
- // To avoid having a separate visitor for consistency checks, we store
- // bindings in two forms:
-
- // 1) Bindings as a vector of context-related sets.
- // Used for checking multiple bindings to the same identifier (i.e. E0415,
- // E0416).
- std::vector<PatternBinding> &bindings_with_ctx;
-
- // 2) Bindings as a map between identifiers and binding info.
- // Used for checking consistency between alt patterns (i.e. E0408, E0409).
- BindingMap binding_info_map;
-
- // we need to insert the missing and inconsistent bindings (found in
- // check_bindings_consistency) into maps to avoid duplication of error
- // messages.
- BindingMap inconsistent_bindings;
- BindingMap missing_bindings;
-
- Rib::ItemType type;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_AST_RESOLVE_PATTERN_H
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.cc b/gcc/rust/resolve/rust-ast-resolve-stmt.cc
deleted file mode 100644
index fefb522..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-ast-resolve-toplevel.h"
-#include "rust-ast-resolve-item.h"
-#include "rust-ast-resolve-stmt.h"
-#include "rust-ast-resolve-implitem.h"
-
-namespace Rust {
-namespace Resolver {
-
-void
-ResolveStmt::visit (AST::ExternBlock &extern_block)
-{
- resolve_visibility (extern_block.get_visibility ());
- for (auto &item : extern_block.get_extern_items ())
- {
- ResolveToplevelExternItem::go (*item, CanonicalPath::create_empty ());
- ResolveExternItem::go (*item, prefix, canonical_prefix);
- }
-}
-
-void
-ResolveStmt::visit (AST::Trait &trait)
-{
- ResolveTopLevel::go (trait, prefix, canonical_prefix);
- ResolveItem::go (trait, prefix, canonical_prefix);
-}
-
-void
-ResolveStmt::visit (AST::InherentImpl &impl_block)
-{
- ResolveTopLevel::go (impl_block, prefix, canonical_prefix);
- ResolveItem::go (impl_block, prefix, canonical_prefix);
-}
-
-void
-ResolveStmt::visit (AST::TraitImpl &impl_block)
-{
- ResolveTopLevel::go (impl_block, prefix, canonical_prefix);
- ResolveItem::go (impl_block, prefix, canonical_prefix);
-}
-
-void
-ResolveStmt::visit (AST::StaticItem &var)
-{
- auto decl = CanonicalPath::new_seg (var.get_node_id (),
- var.get_identifier ().as_string ());
- auto path = decl;
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (var.get_node_id (), cpath);
-
- resolver->get_name_scope ().insert (
- path, var.get_node_id (), var.get_locus (), false, Rib::ItemType::Static,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, var.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- ResolveType::go (var.get_type ());
- ResolveExpr::go (var.get_expr (), path, cpath);
-}
-
-} // namespace Resolver
-} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
deleted file mode 100644
index 6c99d6a..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ /dev/null
@@ -1,407 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_RESOLVE_STMT_H
-#define RUST_AST_RESOLVE_STMT_H
-
-#include "rust-ast-resolve-base.h"
-#include "rust-ast-resolve-type.h"
-#include "rust-ast-resolve-pattern.h"
-#include "rust-ast-resolve-expr.h"
-#include "rust-item.h"
-
-namespace Rust {
-namespace Resolver {
-
-class ResolveStmt : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void go (AST::Stmt &stmt, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix,
- const CanonicalPath &enum_prefix)
- {
- if (stmt.is_marked_for_strip ())
- return;
-
- ResolveStmt resolver (prefix, canonical_prefix, enum_prefix);
- stmt.accept_vis (resolver);
- }
-
- void visit (AST::ExprStmt &stmt) override
- {
- ResolveExpr::go (stmt.get_expr (), prefix, canonical_prefix);
- }
-
- void visit (AST::ConstantItem &constant) override
- {
- auto decl = CanonicalPath::new_seg (constant.get_node_id (),
- constant.get_identifier ());
- auto path = decl; // this ensures we have the correct relative resolution
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (constant.get_node_id (), cpath);
-
- resolver->get_name_scope ().insert (
- path, constant.get_node_id (), constant.get_locus (), false,
- Rib::ItemType::Const,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, constant.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- ResolveType::go (constant.get_type ());
- ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix);
- }
-
- void visit (AST::LetStmt &stmt) override
- {
- if (stmt.has_init_expr ())
- ResolveExpr::go (stmt.get_init_expr (), prefix, canonical_prefix);
-
- if (stmt.has_else_expr ())
- ResolveExpr::go (stmt.get_else_expr (), prefix, canonical_prefix);
-
- PatternDeclaration::go (stmt.get_pattern (), Rib::ItemType::Var);
- if (stmt.has_type ())
- ResolveType::go (stmt.get_type ());
- }
-
- void visit (AST::TupleStruct &struct_decl) override
- {
- auto decl
- = CanonicalPath::new_seg (struct_decl.get_node_id (),
- struct_decl.get_identifier ().as_string ());
- auto path = decl; // this ensures we have the correct relative resolution
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (struct_decl.get_node_id (), cpath);
-
- resolver->get_type_scope ().insert (
- path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
- Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, struct_decl.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId scope_node_id = struct_decl.get_node_id ();
- resolver->get_type_scope ().push (scope_node_id);
-
- if (struct_decl.has_generics ())
- ResolveGenericParams::go (struct_decl.get_generic_params (), prefix,
- canonical_prefix);
-
- for (AST::TupleField &field : struct_decl.get_fields ())
- ResolveType::go (field.get_field_type ());
-
- resolver->get_type_scope ().pop ();
- }
-
- void visit (AST::Enum &enum_decl) override
- {
- auto decl
- = CanonicalPath::new_seg (enum_decl.get_node_id (),
- enum_decl.get_identifier ().as_string ());
- auto path = decl; // this ensures we have the correct relative resolution
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (enum_decl.get_node_id (), cpath);
-
- resolver->get_type_scope ().insert (
- path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
- Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, enum_decl.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId scope_node_id = enum_decl.get_node_id ();
- resolver->get_type_scope ().push (scope_node_id);
-
- if (enum_decl.has_generics ())
- ResolveGenericParams::go (enum_decl.get_generic_params (), prefix,
- canonical_prefix);
-
- for (auto &variant : enum_decl.get_variants ())
- ResolveStmt::go (*variant, path, canonical_prefix, path);
-
- resolver->get_type_scope ().pop ();
- }
-
- void visit (AST::EnumItem &item) override
- {
- auto decl = enum_prefix.append (
- CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ()));
- auto path = decl; // this ensures we have the correct relative resolution
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (item.get_node_id (), cpath);
-
- resolver->get_type_scope ().insert (
- path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, item.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- // Done, no fields.
- }
-
- void visit (AST::EnumItemTuple &item) override
- {
- auto decl = enum_prefix.append (
- CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ()));
- auto path = decl; // this ensures we have the correct relative resolution
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (item.get_node_id (), cpath);
-
- resolver->get_type_scope ().insert (
- path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, item.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- for (auto &field : item.get_tuple_fields ())
- {
- if (field.get_field_type ().is_marked_for_strip ())
- continue;
-
- ResolveType::go (field.get_field_type ());
- }
- }
-
- void visit (AST::EnumItemStruct &item) override
- {
- auto decl = enum_prefix.append (
- CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ()));
- auto path = decl; // this ensures we have the correct relative resolution
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (item.get_node_id (), cpath);
-
- resolver->get_type_scope ().insert (
- path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, item.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- for (auto &field : item.get_struct_fields ())
- {
- if (field.get_field_type ().is_marked_for_strip ())
- continue;
-
- ResolveType::go (field.get_field_type ());
- }
- }
-
- void visit (AST::EnumItemDiscriminant &item) override
- {
- auto decl = enum_prefix.append (
- CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ()));
- auto path = decl; // this ensures we have the correct relative resolution
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (item.get_node_id (), cpath);
-
- resolver->get_type_scope ().insert (
- path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, item.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- // Done, no fields.
- }
-
- void visit (AST::StructStruct &struct_decl) override
- {
- auto decl
- = CanonicalPath::new_seg (struct_decl.get_node_id (),
- struct_decl.get_identifier ().as_string ());
- auto path = decl; // this ensures we have the correct relative resolution
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (struct_decl.get_node_id (), cpath);
-
- resolver->get_type_scope ().insert (
- path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
- Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, struct_decl.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId scope_node_id = struct_decl.get_node_id ();
- resolver->get_type_scope ().push (scope_node_id);
-
- if (struct_decl.has_generics ())
- ResolveGenericParams::go (struct_decl.get_generic_params (), prefix,
- canonical_prefix);
-
- for (AST::StructField &field : struct_decl.get_fields ())
- {
- if (field.get_field_type ().is_marked_for_strip ())
- continue;
-
- ResolveType::go (field.get_field_type ());
- }
-
- resolver->get_type_scope ().pop ();
- }
-
- void visit (AST::Union &union_decl) override
- {
- auto decl
- = CanonicalPath::new_seg (union_decl.get_node_id (),
- union_decl.get_identifier ().as_string ());
- auto path = decl; // this ensures we have the correct relative resolution
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (union_decl.get_node_id (), cpath);
-
- resolver->get_type_scope ().insert (
- path, union_decl.get_node_id (), union_decl.get_locus (), false,
- Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, union_decl.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId scope_node_id = union_decl.get_node_id ();
- resolver->get_type_scope ().push (scope_node_id);
-
- if (union_decl.has_generics ())
- ResolveGenericParams::go (union_decl.get_generic_params (), prefix,
- canonical_prefix);
-
- for (AST::StructField &field : union_decl.get_variants ())
- {
- if (field.get_field_type ().is_marked_for_strip ())
- continue;
-
- ResolveType::go (field.get_field_type ());
- }
-
- resolver->get_type_scope ().pop ();
- }
-
- void visit (AST::Function &function) override
- {
- auto decl
- = CanonicalPath::new_seg (function.get_node_id (),
- function.get_function_name ().as_string ());
- auto path = decl; // this ensures we have the correct relative resolution
- auto cpath = canonical_prefix.append (decl);
- mappings.insert_canonical_path (function.get_node_id (), cpath);
-
- resolver->get_name_scope ().insert (
- path, function.get_node_id (), function.get_locus (), false,
- Rib::ItemType::Function,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, function.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId scope_node_id = function.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- if (function.has_generics ())
- ResolveGenericParams::go (function.get_generic_params (), prefix,
- canonical_prefix);
-
- if (function.has_return_type ())
- ResolveType::go (function.get_return_type ());
-
- std::vector<PatternBinding> bindings
- = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
-
- // we make a new scope so the names of parameters are resolved and shadowed
- // correctly
- for (auto &p : function.get_function_params ())
- {
- if (p->is_variadic ())
- {
- auto &param = static_cast<AST::VariadicParam &> (*p);
- PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param,
- bindings);
- }
-
- else if (p->is_self ())
- {
- auto &param = static_cast<AST::SelfParam &> (*p);
- ResolveType::go (param.get_type ());
- }
- else
- {
- auto &param = static_cast<AST::FunctionParam &> (*p);
-
- ResolveType::go (param.get_type ());
- PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param,
- bindings);
- }
- }
-
- // resolve the function body
- ResolveExpr::go (*function.get_definition ().value (), path, cpath);
-
- resolver->get_name_scope ().pop ();
- resolver->get_type_scope ().pop ();
- resolver->get_label_scope ().pop ();
- }
-
- void visit (AST::ExternBlock &extern_block) override;
- void visit (AST::Trait &trait) override;
- void visit (AST::InherentImpl &impl_block) override;
- void visit (AST::TraitImpl &impl_block) override;
- void visit (AST::StaticItem &var) override;
-
-private:
- ResolveStmt (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix,
- const CanonicalPath &enum_prefix)
- : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix),
- enum_prefix (enum_prefix)
- {}
-
- const CanonicalPath &prefix;
- const CanonicalPath &canonical_prefix;
-
- /* item declaration statements are not given a canonical path, but enum items
- * (variants) do inherit the enum path/identifier name. */
- const CanonicalPath &enum_prefix;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_AST_RESOLVE_STMT_H
diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc
deleted file mode 100644
index 9b38e6a..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-ast-resolve-struct-expr-field.h"
-#include "rust-ast-resolve-expr.h"
-
-namespace Rust {
-namespace Resolver {
-
-void
-ResolveStructExprField::go (AST::StructExprField &field,
- const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
-{
- ResolveStructExprField resolver (prefix, canonical_prefix);
- field.accept_vis (resolver);
-}
-
-ResolveStructExprField::ResolveStructExprField (
- const CanonicalPath &prefix, const CanonicalPath &canonical_prefix)
- : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
-{}
-
-void
-ResolveStructExprField::visit (AST::StructExprFieldIdentifierValue &field)
-{
- ResolveExpr::go (field.get_value (), prefix, canonical_prefix);
-}
-
-void
-ResolveStructExprField::visit (AST::StructExprFieldIndexValue &field)
-{
- ResolveExpr::go (field.get_value (), prefix, canonical_prefix);
-}
-
-void
-ResolveStructExprField::visit (AST::StructExprFieldIdentifier &field)
-{
- AST::IdentifierExpr expr (field.get_field_name (), {}, field.get_locus ());
- expr.set_node_id (field.get_node_id ());
-
- ResolveExpr::go (expr, prefix, canonical_prefix);
-}
-
-} // namespace Resolver
-} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h
deleted file mode 100644
index 87fa60d..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_RESOLVE_STRUCT_EXPR_FIELD
-#define RUST_AST_RESOLVE_STRUCT_EXPR_FIELD
-
-#include "rust-ast-resolve-base.h"
-
-namespace Rust {
-namespace Resolver {
-
-// this resolves values being assigned not that the field actually exists yet.
-
-class ResolveStructExprField : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void go (AST::StructExprField &field, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix);
-
- void visit (AST::StructExprFieldIdentifierValue &field) override;
-
- void visit (AST::StructExprFieldIndexValue &field) override;
-
- void visit (AST::StructExprFieldIdentifier &field) override;
-
-private:
- ResolveStructExprField (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix);
-
- const CanonicalPath &prefix;
- const CanonicalPath &canonical_prefix;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_AST_RESOLVE_STRUCT_EXPR_FIELD
diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
deleted file mode 100644
index 379ccab..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h
+++ /dev/null
@@ -1,500 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_RESOLVE_TOPLEVEL_H
-#define RUST_AST_RESOLVE_TOPLEVEL_H
-
-#include "rust-ast-resolve-base.h"
-#include "rust-ast-resolve-implitem.h"
-#include "rust-name-resolver.h"
-
-namespace Rust {
-namespace Resolver {
-
-class ResolveTopLevel : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void go (AST::Item &item, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
- {
- if (item.is_marked_for_strip ())
- return;
-
- ResolveTopLevel resolver (prefix, canonical_prefix);
- item.accept_vis (resolver);
-
- NodeId current_module = resolver.resolver->peek_current_module_scope ();
- resolver.mappings.insert_child_item_to_parent_module_mapping (
- item.get_node_id (), current_module);
- }
-
- void visit (AST::Module &module) override
- {
- auto mod = CanonicalPath::new_seg (module.get_node_id (),
- module.get_name ().as_string ());
- auto path = prefix.append (mod);
- auto cpath = canonical_prefix.append (mod);
-
- resolver->get_name_scope ().insert (
- path, module.get_node_id (), module.get_locus (), false,
- Rib::ItemType::Module,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, module.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, mod);
- mappings.insert_module_child (current_module, module.get_node_id ());
-
- resolver->push_new_module_scope (module.get_node_id ());
- for (auto &item : module.get_items ())
- ResolveTopLevel::go (*item, path, cpath);
-
- resolver->pop_module_scope ();
-
- mappings.insert_canonical_path (module.get_node_id (), cpath);
- }
-
- void visit (AST::TypeAlias &alias) override
- {
- auto talias
- = CanonicalPath::new_seg (alias.get_node_id (),
- alias.get_new_type_name ().as_string ());
- auto path = prefix.append (talias);
- auto cpath = canonical_prefix.append (talias);
-
- resolver->get_type_scope ().insert (
- path, alias.get_node_id (), alias.get_locus (), false,
- Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, alias.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, talias);
- mappings.insert_canonical_path (alias.get_node_id (), cpath);
- }
-
- void visit (AST::TupleStruct &struct_decl) override
- {
- auto decl
- = CanonicalPath::new_seg (struct_decl.get_node_id (),
- struct_decl.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_type_scope ().insert (
- path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
- Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, struct_decl.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- mappings.insert_canonical_path (struct_decl.get_node_id (), cpath);
- }
-
- void visit (AST::Enum &enum_decl) override
- {
- auto decl
- = CanonicalPath::new_seg (enum_decl.get_node_id (),
- enum_decl.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_type_scope ().insert (
- path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
- Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, enum_decl.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- resolver->push_new_module_scope (enum_decl.get_node_id ());
- for (auto &variant : enum_decl.get_variants ())
- ResolveTopLevel::go (*variant, path, cpath);
-
- resolver->pop_module_scope ();
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- mappings.insert_canonical_path (enum_decl.get_node_id (), cpath);
- }
-
- void visit (AST::EnumItem &item) override
- {
- auto decl = CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_type_scope ().insert (
- path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, item.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- mappings.insert_canonical_path (item.get_node_id (), cpath);
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- mappings.insert_module_child (current_module, item.get_node_id ());
- }
-
- void visit (AST::EnumItemTuple &item) override
- {
- auto decl = CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_type_scope ().insert (
- path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, item.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- mappings.insert_canonical_path (item.get_node_id (), cpath);
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- mappings.insert_module_child (current_module, item.get_node_id ());
- }
-
- void visit (AST::EnumItemStruct &item) override
- {
- auto decl = CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_type_scope ().insert (
- path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, item.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- mappings.insert_canonical_path (item.get_node_id (), cpath);
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- mappings.insert_module_child (current_module, item.get_node_id ());
- }
-
- void visit (AST::EnumItemDiscriminant &item) override
- {
- auto decl = CanonicalPath::new_seg (item.get_node_id (),
- item.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_type_scope ().insert (
- path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, item.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- mappings.insert_canonical_path (item.get_node_id (), cpath);
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- mappings.insert_module_child (current_module, item.get_node_id ());
- }
-
- void visit (AST::StructStruct &struct_decl) override
- {
- auto decl
- = CanonicalPath::new_seg (struct_decl.get_node_id (),
- struct_decl.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- auto duplicate_item
- = [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, struct_decl.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- };
-
- resolver->get_type_scope ().insert (path, struct_decl.get_node_id (),
- struct_decl.get_locus (), false,
- Rib::ItemType::Type, duplicate_item);
-
- if (struct_decl.is_unit_struct ())
- resolver->get_name_scope ().insert (path, struct_decl.get_node_id (),
- struct_decl.get_locus (), false,
- Rib::ItemType::Type, duplicate_item);
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- mappings.insert_canonical_path (struct_decl.get_node_id (), cpath);
- }
-
- void visit (AST::Union &union_decl) override
- {
- auto decl
- = CanonicalPath::new_seg (union_decl.get_node_id (),
- union_decl.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_type_scope ().insert (
- path, union_decl.get_node_id (), union_decl.get_locus (), false,
- Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, union_decl.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- mappings.insert_canonical_path (union_decl.get_node_id (), cpath);
- }
-
- void visit (AST::StaticItem &var) override
- {
- auto decl = CanonicalPath::new_seg (var.get_node_id (),
- var.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_name_scope ().insert (
- path, var.get_node_id (), var.get_locus (), false, Rib::ItemType::Static,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, var.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- mappings.insert_canonical_path (var.get_node_id (), cpath);
- }
-
- void visit (AST::ConstantItem &constant) override
- {
- auto decl = CanonicalPath::new_seg (constant.get_node_id (),
- constant.get_identifier ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_name_scope ().insert (
- path, constant.get_node_id (), constant.get_locus (), false,
- Rib::ItemType::Const,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, constant.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- mappings.insert_canonical_path (constant.get_node_id (), cpath);
- }
-
- void visit (AST::Function &function) override
- {
- auto decl
- = CanonicalPath::new_seg (function.get_node_id (),
- function.get_function_name ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_name_scope ().insert (
- path, function.get_node_id (), function.get_locus (), false,
- Rib::ItemType::Function,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, function.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- mappings.insert_canonical_path (function.get_node_id (), cpath);
- }
-
- void visit (AST::InherentImpl &impl_block) override
- {
- std::string raw_impl_type_path = impl_block.get_type ().as_string ();
- CanonicalPath impl_type_seg
- = CanonicalPath::new_seg (impl_block.get_type ().get_node_id (),
- raw_impl_type_path);
-
- CanonicalPath impl_type
- = CanonicalPath::inherent_impl_seg (impl_block.get_node_id (),
- impl_type_seg);
- CanonicalPath impl_prefix = prefix.append (impl_type_seg);
-
- for (auto &impl_item : impl_block.get_impl_items ())
- ResolveToplevelImplItem::go (*impl_item, impl_prefix);
- }
-
- void visit (AST::TraitImpl &impl_block) override
- {
- std::string raw_impl_type_path = impl_block.get_type ().as_string ();
- CanonicalPath impl_type_seg
- = CanonicalPath::new_seg (impl_block.get_type ().get_node_id (),
- raw_impl_type_path);
-
- std::string raw_trait_type_path = impl_block.get_trait_path ().as_string ();
- CanonicalPath trait_type_seg
- = CanonicalPath::new_seg (impl_block.get_trait_path ().get_node_id (),
- raw_trait_type_path);
-
- CanonicalPath projection
- = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (),
- trait_type_seg,
- impl_type_seg);
- CanonicalPath impl_prefix = prefix.append (projection);
-
- resolver->get_name_scope ().insert (
- impl_prefix, impl_block.get_node_id (), impl_block.get_locus (), false,
- Rib::ItemType::TraitImpl,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, impl_block.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- for (auto &impl_item : impl_block.get_impl_items ())
- ResolveToplevelImplItem::go (*impl_item, impl_prefix);
- }
-
- void visit (AST::Trait &trait) override
- {
- auto decl = CanonicalPath::new_seg (trait.get_node_id (),
- trait.get_identifier ().as_string ());
- auto path = prefix.append (decl);
- auto cpath = canonical_prefix.append (decl);
-
- resolver->get_type_scope ().insert (
- path, trait.get_node_id (), trait.get_locus (), false,
- Rib::ItemType::Trait,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, trait.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
-
- for (auto &item : trait.get_trait_items ())
- ResolveTopLevelTraitItems::go (item.get (), path, cpath);
-
- NodeId current_module = resolver->peek_current_module_scope ();
- mappings.insert_module_child_item (current_module, decl);
- mappings.insert_canonical_path (trait.get_node_id (), cpath);
- }
-
- void visit (AST::ExternBlock &extern_block) override
- {
- for (auto &item : extern_block.get_extern_items ())
- {
- ResolveToplevelExternItem::go (*item, prefix);
- }
- }
-
- void visit (AST::ExternCrate &extern_crate) override
- {
- if (extern_crate.is_marked_for_strip ())
- return;
-
- NodeId resolved_crate = UNKNOWN_NODEID;
- if (extern_crate.references_self ())
- {
- CrateNum crate_num = mappings.get_current_crate ();
- resolved_crate = mappings.crate_num_to_nodeid (crate_num).value ();
- }
- else
- {
- auto cnum
- = mappings.lookup_crate_name (extern_crate.get_referenced_crate ());
- if (!cnum)
- {
- rust_error_at (extern_crate.get_locus (), "unknown crate %qs",
- extern_crate.get_referenced_crate ().c_str ());
- return;
- }
- if (auto resolved = mappings.crate_num_to_nodeid (*cnum))
- resolved_crate = resolved.value ();
- else
- {
- rust_internal_error_at (extern_crate.get_locus (),
- "failed to resolve crate to nodeid");
- return;
- }
- }
-
- if (resolved_crate == UNKNOWN_NODEID)
- {
- rust_error_at (extern_crate.get_locus (), "failed to resolve crate");
- return;
- }
-
- // mark the node as resolved
- resolver->insert_resolved_name (extern_crate.get_node_id (),
- resolved_crate);
- CanonicalPath decl
- = extern_crate.has_as_clause ()
- ? CanonicalPath::new_seg (extern_crate.get_node_id (),
- extern_crate.get_as_clause ())
- : CanonicalPath::new_seg (extern_crate.get_node_id (),
- extern_crate.get_referenced_crate ());
-
- resolver->get_type_scope ().insert (
- decl, resolved_crate, extern_crate.get_locus (), false,
- Rib::ItemType::ExternCrate,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rich_location r (line_table, extern_crate.get_locus ());
- r.add_range (locus);
- rust_error_at (r, "defined multiple times");
- });
- }
-
-private:
- ResolveTopLevel (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
- : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
- {}
-
- const CanonicalPath &prefix;
- const CanonicalPath &canonical_prefix;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_AST_RESOLVE_TOPLEVEL_H
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
deleted file mode 100644
index 5ab0c44..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ /dev/null
@@ -1,783 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-ast-resolve-type.h"
-#include "rust-ast-resolve-expr.h"
-#include "rust-canonical-path.h"
-#include "rust-type.h"
-#include "rust-hir-map.h"
-
-namespace Rust {
-namespace Resolver {
-
-// rust-ast-resolve-type.h
-
-NodeId
-ResolveType::go (AST::Type &type)
-{
- ResolveType resolver;
- type.accept_vis (resolver);
- return resolver.resolved_node;
-}
-
-void
-ResolveType::visit (AST::BareFunctionType &fntype)
-{
- for (auto &param : fntype.get_function_params ())
- ResolveType::go (param.get_type ());
-
- if (fntype.has_return_type ())
- ResolveType::go (fntype.get_return_type ());
-}
-
-void
-ResolveType::visit (AST::TupleType &tuple)
-{
- if (tuple.is_unit_type ())
- {
- resolved_node = resolver->get_unit_type_node_id ();
- return;
- }
-
- for (auto &elem : tuple.get_elems ())
- ResolveType::go (*elem);
-}
-
-void
-ResolveType::visit (AST::TypePath &path)
-{
- ResolveRelativeTypePath::go (path, resolved_node);
-}
-
-void
-ResolveType::visit (AST::QualifiedPathInType &path)
-{
- ResolveRelativeQualTypePath::go (path);
-}
-
-void
-ResolveType::visit (AST::ArrayType &type)
-{
- type.get_elem_type ().accept_vis (*this);
- ResolveExpr::go (type.get_size_expr (), CanonicalPath::create_empty (),
- CanonicalPath::create_empty ());
-}
-
-void
-ResolveType::visit (AST::TraitObjectTypeOneBound &type)
-{
- ResolveTypeBound::go (type.get_trait_bound ());
-}
-
-void
-ResolveType::visit (AST::TraitObjectType &type)
-{
- for (auto &bound : type.get_type_param_bounds ())
- {
- /* NodeId bound_resolved_id = */
- ResolveTypeBound::go (*bound);
- }
-}
-
-void
-ResolveType::visit (AST::ParenthesisedType &type)
-{
- resolved_node = ResolveType::go (*type.get_type_in_parens ());
-}
-
-void
-ResolveType::visit (AST::ReferenceType &type)
-{
- resolved_node = ResolveType::go (type.get_type_referenced ());
-}
-
-void
-ResolveType::visit (AST::RawPointerType &type)
-{
- resolved_node = ResolveType::go (type.get_type_pointed_to ());
-}
-
-void
-ResolveType::visit (AST::InferredType &)
-{
- // nothing to do
-}
-
-void
-ResolveType::visit (AST::NeverType &)
-{
- resolved_node = resolver->get_never_type_node_id ();
-}
-
-void
-ResolveType::visit (AST::SliceType &type)
-{
- resolved_node = ResolveType::go (type.get_elem_type ());
-}
-
-void
-ResolveType::visit (AST::ImplTraitType &type)
-{
- for (auto &bound : type.get_type_param_bounds ())
- ResolveTypeBound::go (*bound);
-}
-
-void
-ResolveType::visit (AST::ImplTraitTypeOneBound &type)
-{
- ResolveTypeBound::go (type.get_trait_bound ());
-}
-
-// resolve relative type-paths
-
-bool
-ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
-{
- auto resolver = Resolver::get ();
- auto &mappings = Analysis::Mappings::get ();
-
- NodeId module_scope_id = resolver->peek_current_module_scope ();
- NodeId previous_resolved_node_id = module_scope_id;
- for (size_t i = 0; i < path.get_segments ().size (); i++)
- {
- auto &segment = path.get_segments ().at (i);
- bool is_first_segment = i == 0;
- NodeId crate_scope_id = resolver->peek_crate_module_scope ();
- auto ident_string = segment->is_lang_item ()
- ? LangItem::PrettyString (segment->get_lang_item ())
- : segment->get_ident_segment ().as_string ();
-
- resolved_node_id = UNKNOWN_NODEID;
-
- if (segment->is_lang_item ())
- {
- resolved_node_id = Analysis::Mappings::get ().get_lang_item_node (
- segment->get_lang_item ());
- previous_resolved_node_id = resolved_node_id;
- }
- else
- {
- bool in_middle_of_path = i > 0;
- if (in_middle_of_path && segment->is_lower_self_seg ())
- {
- rust_error_at (segment->get_locus (), ErrorCode::E0433,
- "leading path segment %qs can only be used at the "
- "beginning of a path",
- segment->as_string ().c_str ());
- return false;
- }
-
- if (segment->is_crate_path_seg ())
- {
- // what is the current crate scope node id?
- module_scope_id = crate_scope_id;
- previous_resolved_node_id = module_scope_id;
- resolver->insert_resolved_name (segment->get_node_id (),
- module_scope_id);
-
- continue;
- }
- else if (segment->is_super_path_seg ())
- {
- if (module_scope_id == crate_scope_id)
- {
- rust_error_at (segment->get_locus (),
- "cannot use super at the crate scope");
- return false;
- }
-
- module_scope_id = resolver->peek_parent_module_scope ();
- previous_resolved_node_id = module_scope_id;
- resolver->insert_resolved_name (segment->get_node_id (),
- module_scope_id);
- continue;
- }
- }
-
- switch (segment->get_type ())
- {
- case AST::TypePathSegment::SegmentType::GENERIC: {
- AST::TypePathSegmentGeneric *s
- = static_cast<AST::TypePathSegmentGeneric *> (segment.get ());
- if (s->has_generic_args ())
- ResolveGenericArgs::go (s->get_generic_args ());
- }
- break;
-
- case AST::TypePathSegment::SegmentType::REG:
- // nothing to do
- break;
-
- case AST::TypePathSegment::SegmentType::FUNCTION:
- AST::TypePathSegmentFunction *fnseg
- = static_cast<AST::TypePathSegmentFunction *> (segment.get ());
-
- AST::TypePathFunction &fn = fnseg->get_type_path_function ();
- for (auto &param : fn.get_params ())
- {
- ResolveType::go (*param);
- }
-
- if (fn.has_return_type ())
- {
- ResolveType::go (fn.get_return_type ());
- }
-
- break;
- }
-
- if (is_first_segment)
- {
- // name scope first
- NodeId resolved_node = UNKNOWN_NODEID;
- const CanonicalPath path
- = CanonicalPath::new_seg (segment->get_node_id (), ident_string);
- if (resolver->get_type_scope ().lookup (path, &resolved_node))
- {
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_type (segment->get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node);
- else
- resolver->insert_resolved_type (segment->get_node_id (),
- resolved_node);
- resolved_node_id = resolved_node;
- }
- else if (resolver->get_name_scope ().lookup (path, &resolved_node))
- {
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_name (segment->get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node);
- else
- resolver->insert_resolved_name (segment->get_node_id (),
- resolved_node);
- resolved_node_id = resolved_node;
- }
- else if (!segment->is_lang_item () && segment->is_lower_self_seg ())
- {
- // what is the current crate scope node id?
- module_scope_id = crate_scope_id;
- previous_resolved_node_id = module_scope_id;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok = resolver->lookup_resolved_name (segment->get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == module_scope_id);
- else
- resolver->insert_resolved_name (segment->get_node_id (),
- module_scope_id);
-
- continue;
- }
- }
-
- if (resolved_node_id == UNKNOWN_NODEID
- && previous_resolved_node_id == module_scope_id)
- {
- tl::optional<CanonicalPath &> resolved_child
- = mappings.lookup_module_child (module_scope_id, ident_string);
- if (resolved_child.has_value ())
- {
- NodeId resolved_node = resolved_child->get_node_id ();
- if (resolver->get_name_scope ().decl_was_declared_here (
- resolved_node))
- {
- resolved_node_id = resolved_node;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok
- = resolver->lookup_resolved_name (segment->get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node);
- else
- resolver->insert_resolved_name (segment->get_node_id (),
- resolved_node);
- }
- else if (resolver->get_type_scope ().decl_was_declared_here (
- resolved_node))
- {
- resolved_node_id = resolved_node;
-
- NodeId existing = UNKNOWN_NODEID;
- bool ok
- = resolver->lookup_resolved_type (segment->get_node_id (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node);
- else
- resolver->insert_resolved_type (segment->get_node_id (),
- resolved_node);
- }
- else
- {
- rust_error_at (segment->get_locus (),
- "Cannot find path %qs in this scope",
- segment->as_string ().c_str ());
- return false;
- }
- }
- }
-
- bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID;
- if (did_resolve_segment)
- {
- if (mappings.node_is_module (resolved_node_id)
- || mappings.node_is_crate (resolved_node_id))
- {
- module_scope_id = resolved_node_id;
- }
- previous_resolved_node_id = resolved_node_id;
- }
- else if (is_first_segment)
- {
- rust_error_at (segment->get_locus (), ErrorCode::E0412,
- "could not resolve type path %qs",
- segment->as_string ().c_str ());
- return false;
- }
- }
-
- if (resolved_node_id != UNKNOWN_NODEID)
- {
- // name scope first
- if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
- {
- NodeId existing = UNKNOWN_NODEID;
- bool ok
- = resolver->lookup_resolved_name (path.get_node_id (), &existing);
-
- if (ok)
- rust_assert (existing == resolved_node_id);
- else
- resolver->insert_resolved_name (path.get_node_id (),
- resolved_node_id);
- }
- // check the type scope
- else if (resolver->get_type_scope ().decl_was_declared_here (
- resolved_node_id))
- {
- NodeId existing = UNKNOWN_NODEID;
- bool ok
- = resolver->lookup_resolved_type (path.get_node_id (), &existing);
-
- if (ok)
- rust_assert (existing == resolved_node_id);
- else
- resolver->insert_resolved_type (path.get_node_id (),
- resolved_node_id);
- }
- else
- {
- rust_unreachable ();
- }
- }
-
- return true;
-}
-
-// qualified type paths
-
-ResolveRelativeQualTypePath::ResolveRelativeQualTypePath ()
- : failure_flag (false)
-{}
-
-bool
-ResolveRelativeQualTypePath::go (AST::QualifiedPathInType &path)
-{
- ResolveRelativeQualTypePath o;
-
- // resolve the type and trait path
- auto &qualified_path = path.get_qualified_path_type ();
- if (!o.resolve_qual_seg (qualified_path))
- return false;
-
- // qualified types are similar to other paths in that we cannot guarantee
- // that we can resolve the path at name resolution. We must look up
- // associated types and type information to figure this out properly
-
- std::unique_ptr<AST::TypePathSegment> &associated
- = path.get_associated_segment ();
-
- associated->accept_vis (o);
- if (o.failure_flag)
- return false;
-
- for (auto &seg : path.get_segments ())
- {
- seg->accept_vis (o);
- if (o.failure_flag)
- return false;
- }
-
- return true;
-}
-
-bool
-ResolveRelativeQualTypePath::resolve_qual_seg (AST::QualifiedPathType &seg)
-{
- if (seg.is_error ())
- {
- rust_error_at (seg.get_locus (), "segment has error: %s",
- seg.as_string ().c_str ());
- return false;
- }
-
- auto &type = seg.get_type ();
- ResolveType::go (type);
-
- if (seg.has_as_clause ())
- ResolveType::go (seg.get_as_type_path ());
-
- return true;
-}
-
-void
-ResolveRelativeQualTypePath::visit (AST::TypePathSegmentGeneric &seg)
-{
- if (seg.is_error ())
- {
- failure_flag = true;
- rust_error_at (seg.get_locus (), "segment has error: %s",
- seg.as_string ().c_str ());
- return;
- }
-
- ResolveGenericArgs::go (seg.get_generic_args ());
-}
-
-void
-ResolveRelativeQualTypePath::visit (AST::TypePathSegment &seg)
-{
- if (seg.is_error ())
- {
- failure_flag = true;
- rust_error_at (seg.get_locus (), "segment has error: %s",
- seg.as_string ().c_str ());
- return;
- }
-}
-
-// resolve to canonical path
-
-bool
-ResolveTypeToCanonicalPath::go (AST::Type &type, CanonicalPath &result)
-{
- ResolveTypeToCanonicalPath resolver;
- type.accept_vis (resolver);
- result = resolver.result;
- return !resolver.result.is_empty ();
-}
-
-void
-ResolveTypeToCanonicalPath::visit (AST::TypePath &path)
-{
- NodeId resolved_node = UNKNOWN_NODEID;
- if (!resolver->lookup_resolved_name (path.get_node_id (), &resolved_node))
- {
- resolver->lookup_resolved_type (path.get_node_id (), &resolved_node);
- }
-
- if (resolved_node == UNKNOWN_NODEID)
- return;
-
- if (auto type_path = mappings.lookup_canonical_path (resolved_node))
- {
- auto &final_seg = path.get_segments ().back ();
- switch (final_seg->get_type ())
- {
- case AST::TypePathSegment::SegmentType::GENERIC: {
- AST::TypePathSegmentGeneric *s
- = static_cast<AST::TypePathSegmentGeneric *> (final_seg.get ());
-
- std::vector<CanonicalPath> args;
- if (s->has_generic_args ())
- {
- ResolveGenericArgs::go (s->get_generic_args ());
- for (auto &generic : s->get_generic_args ().get_generic_args ())
- {
- // FIXME: What do we want to do here in case there is a
- // constant or an ambiguous const generic?
- // TODO: At that point, will all generics have been
- // disambiguated? Can we thus canonical resolve types and
- // const and `rust_unreachable` on ambiguous types?
- // This is probably fine as we just want to canonicalize
- // types, right?
- if (generic.get_kind () == AST::GenericArg::Kind::Type)
- {
- CanonicalPath arg = CanonicalPath::create_empty ();
- bool ok
- = ResolveTypeToCanonicalPath::go (generic.get_type (),
- arg);
- if (ok)
- args.push_back (std::move (arg));
- }
- }
- }
-
- result = *type_path;
- if (!args.empty ())
- {
- // append this onto the path
- std::string buf;
- for (size_t i = 0; i < args.size (); i++)
- {
- bool has_next = (i + 1) < args.size ();
- const auto &arg = args.at (i);
-
- buf += arg.get ();
- if (has_next)
- buf += ", ";
- }
-
- std::string arg_seg = "<" + buf + ">";
- CanonicalPath argument_seg
- = CanonicalPath::new_seg (s->get_node_id (), arg_seg);
- result = result.append (argument_seg);
- }
- }
- break;
-
- default:
- result = *type_path;
- break;
- }
- }
-}
-
-void
-ResolveTypeToCanonicalPath::visit (AST::ReferenceType &type)
-{
- CanonicalPath path = CanonicalPath::create_empty ();
- bool ok = ResolveTypeToCanonicalPath::go (type.get_type_referenced (), path);
- if (ok)
- {
- std::string ref_type_str = type.is_mut () ? "mut" : "";
- std::string ref_path = "&" + ref_type_str + " " + path.get ();
- result = CanonicalPath::new_seg (type.get_node_id (), ref_path);
- }
-}
-
-void
-ResolveTypeToCanonicalPath::visit (AST::RawPointerType &type)
-{
- CanonicalPath path = CanonicalPath::create_empty ();
- bool ok = ResolveTypeToCanonicalPath::go (type.get_type_pointed_to (), path);
- if (ok)
- {
- std::string ptr_type_str
- = type.get_pointer_type () == AST::RawPointerType::CONST ? "const"
- : "mut";
- std::string ptr_path = "*" + ptr_type_str + " " + path.get ();
- result = CanonicalPath::new_seg (type.get_node_id (), ptr_path);
- }
-}
-
-void
-ResolveTypeToCanonicalPath::visit (AST::SliceType &type)
-{
- CanonicalPath path = CanonicalPath::create_empty ();
- bool ok = ResolveTypeToCanonicalPath::go (type.get_elem_type (), path);
- if (ok)
- {
- std::string slice_path = "[" + path.get () + "]";
- result = CanonicalPath::new_seg (type.get_node_id (), slice_path);
- }
-}
-
-void
-ResolveTypeToCanonicalPath::visit (AST::TraitObjectTypeOneBound &type)
-{
- CanonicalPath path = CanonicalPath::create_empty ();
- bool ok
- = ResolveTypeToCanonicalPath::go (type.get_trait_bound ().get_type_path (),
- path);
- if (ok)
- {
- std::string slice_path = "<dyn " + path.get () + ">";
- result = CanonicalPath::new_seg (type.get_node_id (), slice_path);
- }
-}
-
-void
-ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &type)
-{
- rust_assert (!type.get_type_param_bounds ().empty ());
-
- auto &first_bound = type.get_type_param_bounds ().front ();
-
- // Is it allowed or even possible to have a lifetime bound as a first bound?
- if (first_bound->get_bound_type () == AST::TraitBound::LIFETIME)
- rust_unreachable ();
-
- auto &trait = static_cast<AST::TraitBound &> (*first_bound);
-
- CanonicalPath path = CanonicalPath::create_empty ();
- bool ok = ResolveTypeToCanonicalPath::go (trait.get_type_path (), path);
-
- // right?
- rust_assert (ok);
-
- auto slice_path = "<dyn " + path.get ();
-
- for (size_t idx = 1; idx < type.get_type_param_bounds ().size (); idx++)
- {
- auto &additional_bound = type.get_type_param_bounds ()[idx];
-
- std::string str;
-
- switch (additional_bound->get_bound_type ())
- {
- case AST::TypeParamBound::TRAIT: {
- auto bound_path = CanonicalPath::create_empty ();
-
- auto &bound_type_path
- = static_cast<AST::TraitBound &> (*additional_bound)
- .get_type_path ();
- bool ok
- = ResolveTypeToCanonicalPath::go (bound_type_path, bound_path);
-
- if (!ok)
- continue;
-
- str = bound_path.get ();
- break;
- }
- case AST::TypeParamBound::LIFETIME:
- rust_unreachable ();
- break;
- }
- slice_path += " + " + str;
- }
-
- slice_path += ">";
-
- result = CanonicalPath::new_seg (type.get_node_id (), slice_path);
-}
-
-void
-ResolveTypeToCanonicalPath::visit (AST::NeverType &type)
-{
- result = CanonicalPath::new_seg (type.get_node_id (), "!");
-}
-
-void
-ResolveTypeToCanonicalPath::visit (AST::TupleType &type)
-{
- if (!type.is_unit_type ())
- rust_unreachable ();
-
- result = CanonicalPath::new_seg (type.get_node_id (), "()");
-}
-
-ResolveTypeToCanonicalPath::ResolveTypeToCanonicalPath ()
- : ResolverBase (), result (CanonicalPath::create_empty ())
-{}
-
-bool
-ResolveGenericArgs::is_const_value_name (const CanonicalPath &path)
-{
- NodeId resolved;
- auto found = resolver->get_name_scope ().lookup (path, &resolved);
-
- return found;
-}
-
-bool
-ResolveGenericArgs::is_type_name (const CanonicalPath &path)
-{
- NodeId resolved;
- auto found = resolver->get_type_scope ().lookup (path, &resolved);
-
- return found;
-}
-
-void
-ResolveGenericArgs::disambiguate (AST::GenericArg &arg)
-{
- auto path = canonical_prefix.append (
- CanonicalPath::new_seg (UNKNOWN_NODEID, arg.get_path ()));
-
- auto is_type = is_type_name (path);
- auto is_value = is_const_value_name (path);
-
- // In case we cannot find anything, we resolve the ambiguity to a type.
- // This causes the typechecker to error out properly and when necessary.
- // But types also take priority over const values in the case of
- // ambiguities, hence the weird control flow
- if (is_type || (!is_type && !is_value))
- arg = arg.disambiguate_to_type ();
- else if (is_value)
- arg = arg.disambiguate_to_const ();
-}
-
-void
-ResolveGenericArgs::resolve_disambiguated_generic (AST::GenericArg &arg)
-{
- switch (arg.get_kind ())
- {
- case AST::GenericArg::Kind::Const:
- ResolveExpr::go (arg.get_expression (), prefix, canonical_prefix);
- break;
- case AST::GenericArg::Kind::Type:
- ResolveType::go (arg.get_type ());
- break;
- default:
- rust_unreachable ();
- }
-}
-void
-ResolveGenericArgs::go (AST::GenericArgs &generic_args)
-{
- auto empty = CanonicalPath::create_empty ();
-
- go (generic_args, empty, empty);
-}
-
-void
-ResolveGenericArgs::go (AST::GenericArgs &generic_args,
- const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
-{
- auto resolver = ResolveGenericArgs (prefix, canonical_prefix);
-
- for (auto &arg : generic_args.get_generic_args ())
- {
- if (arg.get_kind () == AST::GenericArg::Kind::Either)
- resolver.disambiguate (arg);
-
- resolver.resolve_disambiguated_generic (arg);
- }
-
- for (auto &binding : generic_args.get_binding_args ())
- {
- ResolveType::go (binding.get_type ());
- }
-}
-
-} // namespace Resolver
-} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h
deleted file mode 100644
index 8379d0e..0000000
--- a/gcc/rust/resolve/rust-ast-resolve-type.h
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_RESOLVE_TYPE_H
-#define RUST_AST_RESOLVE_TYPE_H
-
-#include "rust-ast-resolve-base.h"
-#include "rust-ast-resolve-expr.h"
-#include "rust-diagnostics.h"
-#include "rust-hir-map.h"
-#include "rust-path.h"
-#include "rust-type.h"
-#include "util/rust-hir-map.h"
-
-namespace Rust {
-namespace Resolver {
-
-class ResolveRelativeTypePath
-{
-public:
- static bool go (AST::TypePath &path, NodeId &resolved_node_id);
-};
-
-class ResolveRelativeQualTypePath : public ResolverBase
-{
- using ResolverBase::visit;
-
-public:
- static bool go (AST::QualifiedPathInType &path);
-
- void visit (AST::TypePathSegmentGeneric &seg) override;
-
- void visit (AST::TypePathSegment &seg) override;
-
-protected:
- bool resolve_qual_seg (AST::QualifiedPathType &seg);
-
-private:
- ResolveRelativeQualTypePath ();
-
- bool failure_flag;
-};
-
-class ResolveType : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static NodeId go (AST::Type &type);
-
- void visit (AST::BareFunctionType &fntype) override;
- void visit (AST::TupleType &tuple) override;
- void visit (AST::TypePath &path) override;
- void visit (AST::QualifiedPathInType &path) override;
- void visit (AST::ArrayType &type) override;
- void visit (AST::ReferenceType &type) override;
- void visit (AST::InferredType &type) override;
- void visit (AST::NeverType &type) override;
- void visit (AST::RawPointerType &type) override;
- void visit (AST::TraitObjectTypeOneBound &type) override;
- void visit (AST::TraitObjectType &type) override;
- void visit (AST::ParenthesisedType &type) override;
- void visit (AST::SliceType &type) override;
- void visit (AST::ImplTraitType &type) override;
- void visit (AST::ImplTraitTypeOneBound &type) override;
-
-private:
- ResolveType () : ResolverBase () {}
-};
-
-class ResolveTypeBound : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static NodeId go (AST::TypeParamBound &type)
- {
- ResolveTypeBound resolver;
- type.accept_vis (resolver);
- return resolver.resolved_node;
- };
-
- void visit (AST::TraitBound &bound) override
- {
- resolved_node = ResolveType::go (bound.get_type_path ());
- }
-
-private:
- ResolveTypeBound () : ResolverBase () {}
-};
-
-class ResolveGenericParams : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void go (std::vector<std::unique_ptr<AST::GenericParam>> &params,
- const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
- {
- ResolveGenericParams resolver (prefix, canonical_prefix);
-
- // this needs to be done in two phases as they can be used and defined later
- // in bounds
- for (auto &param : params)
- param->accept_vis (resolver);
-
- resolver.first_pass = false;
-
- for (auto &param : params)
- param->accept_vis (resolver);
- }
-
- static void go_single (AST::GenericParam &param, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
- {
- ResolveGenericParams resolver (prefix, canonical_prefix);
-
- param.accept_vis (resolver);
- resolver.first_pass = false;
- param.accept_vis (resolver);
- }
-
- void visit (AST::ConstGenericParam &param) override
- {
- if (first_pass)
- ResolveType::go (param.get_type ());
- else if (param.has_default_value ())
- ResolveExpr::go (param.get_default_value ().get_expression (), prefix,
- canonical_prefix);
- }
-
- void visit (AST::TypeParam &param) override
- {
- if (first_pass)
- {
- // if it has a type lets resolve it
- if (param.has_type ())
- ResolveType::go (param.get_type ());
-
- auto seg = CanonicalPath::new_seg (
- param.get_node_id (), param.get_type_representation ().as_string ());
- resolver->get_type_scope ().insert (
- seg, param.get_node_id (), param.get_locus (), false,
- Rib::ItemType::Type,
- [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
- rust_error_at (param.get_locus (),
- "generic param defined multiple times");
- rust_error_at (locus, "was defined here");
- });
-
- mappings.insert_canonical_path (param.get_node_id (), seg);
- }
- else if (param.has_type_param_bounds ())
- {
- for (auto &bound : param.get_type_param_bounds ())
- ResolveTypeBound::go (*bound);
- }
- }
-
-private:
- ResolveGenericParams (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
- : ResolverBase (), first_pass (true), prefix (prefix),
- canonical_prefix (canonical_prefix)
- {}
-
- bool first_pass;
- const CanonicalPath &prefix;
- const CanonicalPath &canonical_prefix;
-};
-
-class ResolveWhereClause : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void Resolve (AST::WhereClause &where_clause)
- {
- ResolveWhereClause r;
- for (auto &clause : where_clause.get_items ())
- clause->accept_vis (r);
- }
-
- void visit (AST::TypeBoundWhereClauseItem &item) override
- {
- ResolveType::go (item.get_type ());
- if (item.has_type_param_bounds ())
- {
- for (auto &bound : item.get_type_param_bounds ())
- {
- ResolveTypeBound::go (*bound);
- }
- }
- }
-
-private:
- ResolveWhereClause () : ResolverBase () {}
-};
-
-class ResolveTypeToCanonicalPath : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static bool go (AST::Type &type, CanonicalPath &result);
-
- void visit (AST::TypePath &path) override;
-
- void visit (AST::ReferenceType &type) override;
-
- void visit (AST::RawPointerType &type) override;
-
- void visit (AST::SliceType &type) override;
-
- void visit (AST::TraitObjectTypeOneBound &type) override;
-
- void visit (AST::TraitObjectType &type) override;
-
- void visit (AST::NeverType &type) override;
-
- void visit (AST::TupleType &type) override;
-
-private:
- ResolveTypeToCanonicalPath ();
-
- CanonicalPath result;
-};
-
-class ResolveGenericArgs : public ResolverBase
-{
- using Rust::Resolver::ResolverBase::visit;
-
-public:
- static void go (AST::GenericArgs &generic_args);
- static void go (AST::GenericArgs &generic_args, const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix);
-
-private:
- ResolveGenericArgs (const CanonicalPath &prefix,
- const CanonicalPath &canonical_prefix)
- : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
- {}
-
- bool is_type_name (const CanonicalPath &path);
- bool is_const_value_name (const CanonicalPath &path);
-
- /**
- * Resolve a disambiguated generic arg
- */
- void disambiguate (AST::GenericArg &arg);
-
- /**
- * Resolve a disambiguated generic arg
- */
- void resolve_disambiguated_generic (AST::GenericArg &arg);
-
- const CanonicalPath &prefix;
- const CanonicalPath &canonical_prefix;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_AST_RESOLVE_TYPE_H
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
deleted file mode 100644
index 3e3c992..0000000
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-ast-resolve.h"
-#include "rust-ast-full.h"
-#include "rust-tyty.h"
-#include "rust-ast-resolve-toplevel.h"
-#include "rust-ast-resolve-item.h"
-#include "rust-ast-resolve-expr.h"
-#include "rust-ast-resolve-struct-expr-field.h"
-
-extern bool
-saw_errors (void);
-
-namespace Rust {
-namespace Resolver {
-
-// NameResolution
-
-NameResolution *
-NameResolution::get ()
-{
- static NameResolution *instance;
- if (instance == nullptr)
- instance = new NameResolution ();
-
- return instance;
-}
-
-NameResolution::NameResolution ()
- : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ())
-{
- // these are global
- resolver->get_type_scope ().push (mappings.get_next_node_id ());
- resolver->insert_builtin_types (resolver->get_type_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
-}
-
-void
-NameResolution::Resolve (AST::Crate &crate)
-{
- auto resolver = get ();
- resolver->go (crate);
-}
-
-void
-NameResolution::go (AST::Crate &crate)
-{
- // lookup current crate name
- CrateNum cnum = mappings.get_current_crate ();
-
- // Clones the crate name instead of references due to gcc's possibly
- // dangling references warnings
- const auto crate_name = mappings.get_crate_name (cnum).value ();
-
- // setup the ribs
- NodeId scope_node_id = crate.get_node_id ();
- resolver->get_name_scope ().push (scope_node_id);
- resolver->get_type_scope ().push (scope_node_id);
- resolver->get_label_scope ().push (scope_node_id);
- resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
- resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
-
- // get the root segment
- CanonicalPath crate_prefix
- = CanonicalPath::new_seg (scope_node_id, crate_name);
- crate_prefix.set_crate_num (cnum);
-
- // setup a dummy crate node
- resolver->get_name_scope ().insert (
- CanonicalPath::new_seg (crate.get_node_id (), "__$$crate__"),
- crate.get_node_id (), UNDEF_LOCATION);
-
- // setup the root scope
- resolver->push_new_module_scope (scope_node_id);
-
- // first gather the top-level namespace names then we drill down so this
- // allows for resolving forward declarations since an impl block might have
- // a Self type Foo which is defined after the impl block for example.
- for (auto &item : crate.items)
- ResolveTopLevel::go (*item, CanonicalPath::create_empty (), crate_prefix);
-
- // FIXME remove this
- if (saw_errors ())
- {
- resolver->pop_module_scope ();
- return;
- }
-
- // next we can drill down into the items and their scopes
- for (auto &item : crate.items)
- ResolveItem::go (*item, CanonicalPath::create_empty (), crate_prefix);
-
- // done
- resolver->pop_module_scope ();
-}
-
-} // namespace Resolver
-} // namespace Rust
diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc
index 7528e79..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)
{
- auto inner_fn = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); };
+ for (auto &pattern : expr.get_patterns ())
+ visit (pattern);
+}
- ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn,
+void
+DefaultResolver::visit (AST::IfLetExpr &expr)
+{
+ auto inner_vis = [this, &expr] () {
+ visit_if_let_patterns (expr);
+ visit (expr.get_if_block ());
+ };
+
+ visit_outer_attrs (expr);
+
+ visit (expr.get_value_expr ());
+
+ ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), inner_vis);
+}
+
+void
+DefaultResolver::visit (AST::IfLetExprConseqElse &expr)
+{
+ DefaultResolver::visit (static_cast<AST::IfLetExpr &> (expr));
+ visit (expr.get_else_block ());
+}
+
+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,78 @@ 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
+DefaultResolver::visit (AST::TypeParam &param)
+{
+ auto expr_vis = [this, &param] () { AST::DefaultASTVisitor::visit (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
diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h
index 587d7d4..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,18 +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 afaca1f..0dff831 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,21 +65,22 @@ 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 ();
}
bool
Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
{
- auto resolved
- = ctx.resolve_path (glob.to_resolve.get_segments (), Namespace::Types);
+ auto resolved = ctx.resolve_path (glob.to_resolve, Namespace::Types);
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;
@@ -141,6 +145,10 @@ Early::build_import_mapping (
// be moved into the newly created import mappings
auto path = import.to_resolve;
+ // used to skip the "unresolved import" error
+ // if we output other errors during resolution
+ size_t old_error_count = macro_resolve_errors.size ();
+
switch (import.kind)
{
case TopLevel::ImportKind::Kind::Glob:
@@ -154,7 +162,7 @@ Early::build_import_mapping (
break;
}
- if (!found)
+ if (!found && old_error_count == macro_resolve_errors.size ())
collect_error (Error (path.get_final_segment ().get_locus (),
ErrorCode::E0433, "unresolved import %qs",
path.as_string ().c_str ()));
@@ -246,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 ())
@@ -269,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;
}
@@ -311,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
@@ -325,18 +340,17 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
auto pm_def = mappings.lookup_derive_proc_macro_def (
definition->get_node_id ());
- rust_assert (pm_def.has_value ());
-
- mappings.insert_derive_proc_macro_invocation (trait,
- pm_def.value ());
+ if (pm_def.has_value ())
+ mappings.insert_derive_proc_macro_invocation (trait,
+ pm_def.value ());
}
}
else if (Analysis::BuiltinAttributeMappings::get ()
->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
@@ -348,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 ());
@@ -390,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 ());
- GlobbingVisitor glob_visitor (ctx);
- glob_visitor.go (module.value ());
+ rust_assert (container);
+
+ GlobbingVisitor (ctx).go (container.value ());
}
void
@@ -417,12 +432,15 @@ 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 ())
{
- rust_assert (segments.size () > 1);
+ // Erroneous `self` or `{self}` use declaration
+ if (segments.size () == 1)
+ break;
declared_name = segments[segments.size () - 2].as_string ();
}
else
@@ -431,8 +449,8 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping)
break;
}
case AST::UseTreeRebind::NewBindType::WILDCARD:
- rust_unreachable ();
- break;
+ // We don't want to insert it into the trie
+ return;
}
for (auto &&definition : data.definitions ())
@@ -443,6 +461,19 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping)
void
Early::visit (AST::UseDeclaration &decl)
{
+ // We do not want to visit the use trees, we're only looking for top level
+ // rebind. eg. `use something;` or `use something::other;`
+ if (decl.get_tree ()->get_kind () == AST::UseTree::Kind::Rebind)
+ {
+ auto &rebind = static_cast<AST::UseTreeRebind &> (*decl.get_tree ());
+ if (rebind.get_path ().get_final_segment ().is_lower_self_seg ())
+ {
+ collect_error (
+ Error (decl.get_locus (), ErrorCode::E0429,
+ "%<self%> imports are only allowed within a { } list"));
+ }
+ }
+
auto &imports = toplevel.get_imports_to_resolve ();
auto current_import = imports.find (decl.get_node_id ());
if (current_import != imports.end ())
@@ -468,5 +499,31 @@ Early::visit (AST::UseDeclaration &decl)
DefaultResolver::visit (decl);
}
+void
+Early::visit (AST::UseTreeList &use_list)
+{
+ if (!use_list.has_path ())
+ {
+ for (auto &&tree : use_list.get_trees ())
+ {
+ if (tree->get_kind () == AST::UseTree::Kind::Rebind)
+ {
+ auto &rebind = static_cast<AST::UseTreeRebind &> (*tree);
+ auto path_size = rebind.get_path ().get_segments ().size ();
+ if (path_size == 1
+ && rebind.get_path ()
+ .get_final_segment ()
+ .is_lower_self_seg ())
+ {
+ collect_error (Error (rebind.get_locus (), ErrorCode::E0431,
+ "%<self%> import can only appear in an "
+ "import list with a non-empty prefix"));
+ }
+ }
+ }
+ }
+ DefaultResolver::visit (use_list);
+}
+
} // namespace Resolver2_0
} // namespace Rust
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 c4226fe..3940386 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -61,6 +61,7 @@ public:
void visit (AST::Function &) override;
void visit (AST::StructStruct &) override;
void visit (AST::UseDeclaration &) override;
+ void visit (AST::UseTreeList &) override;
struct ImportData
{
@@ -83,15 +84,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 +108,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 +118,7 @@ public:
std::vector<std::pair<Rib::Definition, Namespace>> resolved_definitions;
// For Glob
- Rib::Definition glob_module;
+ Rib::Definition glob_container;
};
struct ImportPair
@@ -218,7 +219,6 @@ private:
std::vector<std::pair<Rib::Definition, Namespace>>
resolve_path_in_all_ns (const P &path)
{
- const auto &segments = path.get_segments ();
std::vector<std::pair<Rib::Definition, Namespace>> resolved;
// Pair a definition with the namespace it was found in
@@ -229,13 +229,22 @@ private:
};
};
- ctx.resolve_path (segments, Namespace::Values)
+ std::vector<Error> value_errors;
+ std::vector<Error> type_errors;
+ std::vector<Error> macro_errors;
+
+ ctx.resolve_path (path, value_errors, Namespace::Values)
.map (pair_with_ns (Namespace::Values));
- ctx.resolve_path (segments, Namespace::Types)
+ ctx.resolve_path (path, type_errors, Namespace::Types)
.map (pair_with_ns (Namespace::Types));
- ctx.resolve_path (segments, Namespace::Macros)
+ ctx.resolve_path (path, macro_errors, Namespace::Macros)
.map (pair_with_ns (Namespace::Macros));
+ if (!value_errors.empty () && !type_errors.empty ()
+ && !macro_errors.empty ())
+ for (auto &ent : value_errors)
+ collect_error (std::move (ent));
+
return resolved;
}
diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc
deleted file mode 100644
index fc9a26c..0000000
--- a/gcc/rust/resolve/rust-early-name-resolver.cc
+++ /dev/null
@@ -1,589 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-early-name-resolver.h"
-#include "rust-pattern.h"
-#include "rust-name-resolver.h"
-#include "rust-macro-builtins.h"
-#include "rust-attribute-values.h"
-
-namespace Rust {
-namespace Resolver {
-
-// Check if a module contains the `#[macro_use]` attribute
-static bool
-is_macro_use_module (const AST::Module &mod)
-{
- for (const auto &attr : mod.get_outer_attrs ())
- if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE)
- return true;
-
- return false;
-}
-
-std::vector<std::unique_ptr<AST::Item>>
-EarlyNameResolver::accumulate_escaped_macros (AST::Module &module)
-{
- if (!is_macro_use_module (module))
- return {};
-
- // 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)
- if (module.get_kind () == AST::Module::UNLOADED)
- module.load_items ();
-
- std::vector<std::unique_ptr<AST::Item>> escaped_macros;
-
- scoped (module.get_node_id (), [&module, &escaped_macros, this] {
- for (auto &item : module.get_items ())
- {
- if (item->get_item_kind () == AST::Item::Kind::Module)
- {
- auto &module = *static_cast<AST::Module *> (item.get ());
- auto new_macros = accumulate_escaped_macros (module);
-
- std::move (new_macros.begin (), new_macros.end (),
- std::back_inserter (escaped_macros));
-
- continue;
- }
-
- if (item->get_item_kind () == AST::Item::Kind::MacroRulesDefinition)
- escaped_macros.emplace_back (item->clone_item ());
- }
- });
-
- return escaped_macros;
-}
-
-EarlyNameResolver::EarlyNameResolver ()
- : current_scope (UNKNOWN_NODEID), resolver (*Resolver::get ()),
- mappings (Analysis::Mappings::get ())
-{}
-
-void
-EarlyNameResolver::go (AST::Crate &crate)
-{
- visit (crate);
-}
-
-void
-EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args)
-{
- for (auto &arg : generic_args.get_generic_args ())
- arg.accept_vis (*this);
-
- for (auto &arg : generic_args.get_binding_args ())
- arg.get_type ().accept_vis (*this);
-}
-
-void
-EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path)
-{
- path.get_type ().accept_vis (*this);
-
- if (path.has_as_clause ())
- path.get_as_type_path ().accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::Crate &crate)
-{
- std::vector<std::unique_ptr<AST::Item>> new_items;
- auto items = crate.take_items ();
-
- scoped (crate.get_node_id (), [&items, &new_items, this] {
- for (auto &&item : items)
- {
- auto new_macros = std::vector<std::unique_ptr<AST::Item>> ();
-
- if (item->get_item_kind () == AST::Item::Kind::Module)
- new_macros = accumulate_escaped_macros (
- *static_cast<AST::Module *> (item.get ()));
-
- new_items.emplace_back (std::move (item));
- std::move (new_macros.begin (), new_macros.end (),
- std::back_inserter (new_items));
- }
- });
-
- crate.set_items (std::move (new_items));
-
- scoped (crate.get_node_id (), [&crate, this] () {
- for (auto &item : crate.items)
- item->accept_vis (*this);
- });
-}
-
-void
-EarlyNameResolver::visit (AST::DelimTokenTree &)
-{}
-
-void
-EarlyNameResolver::visit (AST::AttrInputMetaItemContainer &)
-{}
-
-void
-EarlyNameResolver::visit (AST::IdentifierExpr &)
-{}
-
-void
-EarlyNameResolver::visit (AST::LifetimeParam &)
-{}
-
-void
-EarlyNameResolver::visit (AST::ConstGenericParam &)
-{}
-
-// FIXME: ARTHUR: Do we need to perform macro resolution for paths as well?
-// std::arch::asm!()?
-void
-EarlyNameResolver::visit (AST::PathInExpression &path)
-{
- if (!path.is_lang_item ())
- for (auto &segment : path.get_segments ())
- if (segment.has_generic_args ())
- resolve_generic_args (segment.get_generic_args ());
-}
-
-void
-EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment)
-{
- if (segment.has_generic_args ())
- resolve_generic_args (segment.get_generic_args ());
-}
-
-void
-EarlyNameResolver::visit (AST::QualifiedPathInExpression &path)
-{
- resolve_qualified_path_type (path.get_qualified_path_type ());
-
- for (auto &segment : path.get_segments ())
- if (segment.has_generic_args ())
- resolve_generic_args (segment.get_generic_args ());
-}
-
-void
-EarlyNameResolver::visit (AST::QualifiedPathInType &path)
-{
- resolve_qualified_path_type (path.get_qualified_path_type ());
-
- for (auto &segment : path.get_segments ())
- segment->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::LiteralExpr &)
-{}
-
-void
-EarlyNameResolver::visit (AST::AttrInputLiteral &)
-{}
-
-void
-EarlyNameResolver::visit (AST::AttrInputMacro &)
-{}
-
-void
-EarlyNameResolver::visit (AST::MetaItemLitExpr &)
-{}
-
-void
-EarlyNameResolver::visit (AST::MetaItemPathLit &)
-{}
-
-void
-EarlyNameResolver::visit (AST::StructExprStruct &)
-{}
-
-void
-EarlyNameResolver::visit (AST::StructExprFieldIdentifier &)
-{}
-
-void
-EarlyNameResolver::visit (AST::StructExprStructBase &)
-{}
-
-void
-EarlyNameResolver::visit (AST::BlockExpr &expr)
-{
- scoped (expr.get_node_id (), [&expr, this] () {
- for (auto &stmt : expr.get_statements ())
- stmt->accept_vis (*this);
-
- if (expr.has_tail_expr ())
- expr.get_tail_expr ().accept_vis (*this);
- });
-}
-
-void
-EarlyNameResolver::visit (AST::ContinueExpr &)
-{}
-
-void
-EarlyNameResolver::visit (AST::RangeFullExpr &)
-{}
-
-void
-EarlyNameResolver::visit (AST::ForLoopExpr &expr)
-{
- scoped (expr.get_node_id (), [&expr, this] () {
- expr.get_pattern ().accept_vis (*this);
- expr.get_iterator_expr ().accept_vis (*this);
- expr.get_loop_block ().accept_vis (*this);
- });
-}
-
-void
-EarlyNameResolver::visit (AST::IfLetExpr &expr)
-{
- expr.get_value_expr ().accept_vis (*this);
-
- scoped (expr.get_node_id (),
- [&expr, this] () { expr.get_if_block ().accept_vis (*this); });
-}
-
-void
-EarlyNameResolver::visit (AST::MatchExpr &expr)
-{
- expr.get_scrutinee_expr ().accept_vis (*this);
-
- scoped (expr.get_node_id (), [&expr, this] () {
- for (auto &arm : expr.get_match_cases ())
- {
- scoped (arm.get_node_id (), [&arm, this] () {
- if (arm.get_arm ().has_match_arm_guard ())
- arm.get_arm ().get_guard_expr ().accept_vis (*this);
-
- for (auto &pattern : arm.get_arm ().get_patterns ())
- pattern->accept_vis (*this);
-
- arm.get_expr ().accept_vis (*this);
- });
- }
- });
-}
-
-void
-EarlyNameResolver::visit (AST::LifetimeWhereClauseItem &)
-{}
-
-void
-EarlyNameResolver::visit (AST::Module &module)
-{
- if (module.get_kind () == AST::Module::UNLOADED)
- module.load_items ();
-
- // so we need to only go "one scope down" for fetching macros. Macros within
- // functions are still scoped only within that function. But we have to be
- // careful because nested modules with #[macro_use] actually works!
- std::vector<std::unique_ptr<AST::Item>> new_items;
- auto items = module.take_items ();
-
- scoped (module.get_node_id (), [&items, &new_items, this] {
- for (auto &&item : items)
- {
- auto new_macros = std::vector<std::unique_ptr<AST::Item>> ();
-
- if (item->get_item_kind () == AST::Item::Kind::Module)
- new_macros = accumulate_escaped_macros (
- *static_cast<AST::Module *> (item.get ()));
-
- new_items.emplace_back (std::move (item));
- std::move (new_macros.begin (), new_macros.end (),
- std::back_inserter (new_items));
- }
- });
-
- module.set_items (std::move (new_items));
-
- scoped (module.get_node_id (), [&module, this] () {
- for (auto &item : module.get_items ())
- item->accept_vis (*this);
- });
-}
-
-void
-EarlyNameResolver::visit (AST::ExternCrate &)
-{}
-
-void
-EarlyNameResolver::visit (AST::UseTreeGlob &)
-{}
-
-void
-EarlyNameResolver::visit (AST::UseTreeList &)
-{}
-
-void
-EarlyNameResolver::visit (AST::UseTreeRebind &)
-{}
-
-void
-EarlyNameResolver::visit (AST::UseDeclaration &)
-{}
-
-void
-EarlyNameResolver::visit (AST::EnumItem &)
-{}
-
-void
-EarlyNameResolver::visit (AST::Union &)
-{}
-
-void
-EarlyNameResolver::visit (AST::TraitItemType &)
-{}
-
-void
-EarlyNameResolver::visit (AST::Trait &trait)
-{
- // shouldn't need to visit trait.get_implicit_self ()
-
- for (auto &generic : trait.get_generic_params ())
- generic->accept_vis (*this);
-
- scoped (trait.get_node_id (), [&trait, this] () {
- for (auto &item : trait.get_trait_items ())
- item->accept_vis (*this);
- });
-}
-
-void
-EarlyNameResolver::visit (AST::InherentImpl &impl)
-{
- impl.get_type ().accept_vis (*this);
-
- for (auto &generic : impl.get_generic_params ())
- generic->accept_vis (*this);
-
- scoped (impl.get_node_id (), [&impl, this] () {
- for (auto &item : impl.get_impl_items ())
- item->accept_vis (*this);
- });
-}
-
-void
-EarlyNameResolver::visit (AST::TraitImpl &impl)
-{
- impl.get_type ().accept_vis (*this);
-
- for (auto &generic : impl.get_generic_params ())
- generic->accept_vis (*this);
-
- scoped (impl.get_node_id (), [&impl, this] () {
- for (auto &item : impl.get_impl_items ())
- item->accept_vis (*this);
- });
-}
-
-void
-EarlyNameResolver::visit (AST::ExternalTypeItem &item)
-{
- // nothing to do?
-}
-
-void
-EarlyNameResolver::visit (AST::ExternBlock &block)
-{
- scoped (block.get_node_id (), [&block, this] () {
- for (auto &item : block.get_extern_items ())
- item->accept_vis (*this);
- });
-}
-
-void
-EarlyNameResolver::visit (AST::MacroMatchRepetition &)
-{}
-
-void
-EarlyNameResolver::visit (AST::MacroMatcher &)
-{}
-
-void
-EarlyNameResolver::visit (AST::MacroRulesDefinition &rules_def)
-{
- auto path = CanonicalPath::new_seg (rules_def.get_node_id (),
- rules_def.get_rule_name ().as_string ());
- resolver.get_macro_scope ().insert (path, rules_def.get_node_id (),
- rules_def.get_locus ());
-
- /* Since the EarlyNameResolver runs multiple time (fixed point algorithm)
- * we could be inserting the same macro def over and over again until we
- * implement some optimizations */
- // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead
- if (mappings.lookup_macro_def (rules_def.get_node_id ()))
- return;
-
- mappings.insert_macro_def (&rules_def);
- rust_debug_loc (rules_def.get_locus (), "inserting macro def: [%s]",
- path.get ().c_str ());
-}
-
-void
-EarlyNameResolver::visit (AST::MacroInvocation &invoc)
-{
- auto &invoc_data = invoc.get_invoc_data ();
- auto has_semicolon = invoc.has_semicolon ();
-
- if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
- for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
- pending_invoc->accept_vis (*this);
-
- // ??
- // switch on type of macro:
- // - '!' syntax macro (inner switch)
- // - procedural macro - "A token-based function-like macro"
- // - 'macro_rules' (by example/pattern-match) macro? or not? "an
- // AST-based function-like macro"
- // - else is unreachable
- // - attribute syntax macro (inner switch)
- // - procedural macro attribute syntax - "A token-based attribute
- // macro"
- // - legacy macro attribute syntax? - "an AST-based attribute macro"
- // - non-macro attribute: mark known
- // - else is unreachable
- // - derive macro (inner switch)
- // - derive or legacy derive - "token-based" vs "AST-based"
- // - else is unreachable
- // - derive container macro - unreachable
-
- // lookup the rules for this macro
- NodeId resolved_node = UNKNOWN_NODEID;
- NodeId source_node = UNKNOWN_NODEID;
- if (has_semicolon)
- source_node = invoc.get_macro_node_id ();
- else
- source_node = invoc.get_node_id ();
- auto seg
- = CanonicalPath::new_seg (source_node, invoc_data.get_path ().as_string ());
-
- bool found = resolver.get_macro_scope ().lookup (seg, &resolved_node);
- if (!found)
- {
- rust_error_at (invoc.get_locus (), ErrorCode::E0433,
- "could not resolve macro invocation %qs",
- seg.get ().c_str ());
- return;
- }
-
- // lookup the rules
- auto rules_def = mappings.lookup_macro_def (resolved_node);
-
- auto &outer_attrs = rules_def.value ()->get_outer_attrs ();
- bool is_builtin
- = std::any_of (outer_attrs.begin (), outer_attrs.end (),
- [] (AST::Attribute attr) {
- return attr.get_path ()
- == Values::Attributes::RUSTC_BUILTIN_MACRO;
- });
-
- if (is_builtin)
- {
- auto builtin_kind = builtin_macro_from_string (
- rules_def.value ()->get_rule_name ().as_string ());
- invoc.map_to_builtin (builtin_kind.value ());
- }
-
- auto attributes = rules_def.value ()->get_outer_attrs ();
-
- /* Since the EarlyNameResolver runs multiple time (fixed point algorithm)
- * we could be inserting the same macro def over and over again until we
- * implement some optimizations */
- // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead
- if (mappings.lookup_macro_invocation (invoc))
- return;
-
- mappings.insert_macro_invocation (invoc, *rules_def);
-}
-
-// FIXME: ARTHUR: Do we need to resolve these as well here?
-
-void
-EarlyNameResolver::visit (AST::MetaItemPath &)
-{}
-
-void
-EarlyNameResolver::visit (AST::MetaItemSeq &)
-{}
-
-void
-EarlyNameResolver::visit (AST::MetaNameValueStr &)
-{}
-
-void
-EarlyNameResolver::visit (AST::MetaListPaths &)
-{}
-
-void
-EarlyNameResolver::visit (AST::MetaListNameValueStr &)
-{}
-
-void
-EarlyNameResolver::visit (AST::RangePatternBoundLiteral &)
-{}
-
-void
-EarlyNameResolver::visit (AST::RangePatternBoundPath &)
-{}
-
-void
-EarlyNameResolver::visit (AST::RangePatternBoundQualPath &)
-{}
-
-void
-EarlyNameResolver::visit (AST::StructPatternFieldIdent &)
-{}
-
-void
-EarlyNameResolver::visit (AST::StructPattern &)
-{}
-
-void
-EarlyNameResolver::visit (AST::TupleStructPattern &pattern)
-{
- pattern.get_items ().accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TupleType &)
-{}
-
-void
-EarlyNameResolver::visit (AST::RawPointerType &)
-{}
-
-void
-EarlyNameResolver::visit (AST::ReferenceType &)
-{}
-
-void
-EarlyNameResolver::visit (AST::ArrayType &)
-{}
-
-void
-EarlyNameResolver::visit (AST::SliceType &)
-{}
-
-void
-EarlyNameResolver::visit (AST::InferredType &)
-{}
-
-} // namespace Resolver
-} // namespace Rust
diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h
deleted file mode 100644
index 26fc84d..0000000
--- a/gcc/rust/resolve/rust-early-name-resolver.h
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_EARLY_NAME_RESOLVER_H
-#define RUST_EARLY_NAME_RESOLVER_H
-
-#include "rust-name-resolver.h"
-#include "rust-system.h"
-#include "rust-ast.h"
-#include "rust-ast-visitor.h"
-
-namespace Rust {
-namespace Resolver {
-
-class EarlyNameResolver : public AST::DefaultASTVisitor
-{
-public:
- EarlyNameResolver ();
-
- void go (AST::Crate &crate);
-
-private:
- using AST::DefaultASTVisitor::visit;
-
- /**
- * Execute a lambda within a scope. This is equivalent to calling
- * `enter_scope` before your code and `exit_scope` after. This ensures
- * no errors can be committed
- */
- void scoped (NodeId scope_id, std::function<void ()> fn)
- {
- auto old_scope = current_scope;
- current_scope = scope_id;
- resolver.get_macro_scope ().push (scope_id);
- resolver.push_new_macro_rib (resolver.get_macro_scope ().peek ());
-
- fn ();
-
- resolver.get_macro_scope ().pop ();
- current_scope = old_scope;
- }
-
- /**
- * Accumulate all of the nested macros which escape their module through the
- * use of the #[macro_use] attribute.
- *
- * This function recursively accumulates macros in all of the nested modules
- * of an item container (an AST::Crate or an AST::Module) and returns this new
- * list of items. You can then use the `take_items` and `set_items` functions
- * on these containers to replace their list of items.
- */
- std::vector<std::unique_ptr<AST::Item>>
- accumulate_escaped_macros (AST::Module &module);
-
- /**
- * The "scope" we are currently in.
- *
- * This involves lexical scopes:
- *
- * ```rust
- * // current_scope = crate_id;
- * macro_rules! foo { () => {} )
- *
- * {
- * // current_scope = current_block_id;
- * macro_rules! foo { () => { something!(); } }
- * }
- * // current_scope = crate_id;
- * ```
- *
- * as well as any sort of scope-like structure that might impact import name
- * resolution or macro name resolution:
- *
- * ```rust
- * macro_rules! foo {
- * () => { fn empty() {} }
- * }
- *
- *
- * trait Foo {
- * fn foo() {
- * fn inner_foo() {
- * macro_rules! foo { () => {} )
- *
- * foo!();
- * }
- *
- * foo!();
- * }
- *
- * foo!();
- * }
- *
- * foo!();
- * ```
- */
- NodeId current_scope;
-
- /* The crate's scope */
- NodeId crate_scope;
-
- Resolver &resolver;
- Analysis::Mappings &mappings;
-
- /**
- * Early name-resolve generic args, which can be macro invocations
- */
- void resolve_generic_args (AST::GenericArgs &generic_args);
-
- /**
- * Early name-resolve a qualified path type, which can contain macro
- * invocations
- */
- void resolve_qualified_path_type (AST::QualifiedPathType &path);
-
- virtual void visit (AST::Crate &crate);
- virtual void visit (AST::DelimTokenTree &delim_tok_tree);
- virtual void visit (AST::AttrInputMetaItemContainer &input);
- virtual void visit (AST::IdentifierExpr &ident_expr);
- virtual void visit (AST::LifetimeParam &lifetime_param);
- virtual void visit (AST::ConstGenericParam &const_param);
- virtual void visit (AST::PathInExpression &path);
- virtual void visit (AST::TypePathSegmentGeneric &segment);
- virtual void visit (AST::QualifiedPathInExpression &path);
- virtual void visit (AST::QualifiedPathInType &path);
- virtual void visit (AST::LiteralExpr &expr);
- 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::StructExprStruct &expr);
- virtual void visit (AST::StructExprFieldIdentifier &field);
- virtual void visit (AST::StructExprStructBase &expr);
- virtual void visit (AST::BlockExpr &expr);
- virtual void visit (AST::ContinueExpr &expr);
- virtual void visit (AST::RangeFullExpr &expr);
- virtual void visit (AST::ForLoopExpr &expr);
- virtual void visit (AST::IfLetExpr &expr);
- virtual void visit (AST::MatchExpr &expr);
- virtual void visit (AST::LifetimeWhereClauseItem &item);
- virtual void visit (AST::Module &module);
- virtual void visit (AST::ExternCrate &crate);
- virtual void visit (AST::UseTreeGlob &use_tree);
- virtual void visit (AST::UseTreeList &use_tree);
- virtual void visit (AST::UseTreeRebind &use_tree);
- virtual void visit (AST::UseDeclaration &use_decl);
- virtual void visit (AST::EnumItem &item);
- virtual void visit (AST::Union &union_item);
- virtual void visit (AST::TraitItemType &item);
- virtual void visit (AST::Trait &trait);
- virtual void visit (AST::InherentImpl &impl);
- virtual void visit (AST::TraitImpl &impl);
- virtual void visit (AST::ExternalTypeItem &item);
- virtual void visit (AST::ExternBlock &block);
- virtual void visit (AST::MacroMatchRepetition &match);
- virtual void visit (AST::MacroMatcher &matcher);
- virtual void visit (AST::MacroRulesDefinition &rules_def);
- virtual void visit (AST::MacroInvocation &macro_invoc);
- virtual void visit (AST::MetaItemPath &meta_item);
- virtual void visit (AST::MetaItemSeq &meta_item);
- virtual void visit (AST::MetaNameValueStr &meta_item);
- virtual void visit (AST::MetaListPaths &meta_item);
- virtual void visit (AST::MetaListNameValueStr &meta_item);
- virtual void visit (AST::RangePatternBoundLiteral &bound);
- virtual void visit (AST::RangePatternBoundPath &bound);
- virtual void visit (AST::RangePatternBoundQualPath &bound);
- virtual void visit (AST::StructPatternFieldIdent &field);
- virtual void visit (AST::StructPattern &pattern);
- virtual void visit (AST::TupleStructPattern &pattern);
- virtual void visit (AST::TupleType &type);
- virtual void visit (AST::RawPointerType &type);
- virtual void visit (AST::ReferenceType &type);
- virtual void visit (AST::ArrayType &type);
- virtual void visit (AST::SliceType &type);
- virtual void visit (AST::InferredType &type);
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_EARLY_NAME_RESOLVER_H
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 f390e38..75dd873 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -543,12 +543,20 @@ private:
Node root;
};
+enum class ResolutionMode
+{
+ Normal,
+ FromRoot,
+ FromExtern, // extern prelude
+};
+
template <Namespace N> class ForeverStack
{
public:
ForeverStack ()
: root (Node (Rib (Rib::Kind::Normal), UNKNOWN_NODEID)),
lang_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID, root)),
+ extern_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID)),
cursor_reference (root)
{
rust_assert (root.is_root ());
@@ -671,11 +679,9 @@ public:
*/
template <typename S>
tl::optional<Rib::Definition> resolve_path (
- const std::vector<S> &segments,
- std::function<void (const S &, NodeId)> insert_segment_resolution);
-
- // FIXME: Documentation
- tl::optional<Resolver::CanonicalPath> to_canonical_path (NodeId id) const;
+ 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<Rib &> to_rib (NodeId rib_id);
@@ -737,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
{
@@ -768,6 +777,10 @@ private:
* resolution
*/
Node lang_prelude;
+ /*
+ * The extern prelude, used for resolving external crates
+ */
+ Node extern_prelude;
std::reference_wrapper<Node> cursor_reference;
@@ -787,13 +800,15 @@ private:
tl::optional<SegIterator<S>> find_starting_point (
const std::vector<S> &segments,
std::reference_wrapper<Node> &starting_point,
- std::function<void (const S &, NodeId)> insert_segment_resolution);
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors);
template <typename S>
tl::optional<Node &> resolve_segments (
Node &starting_point, const std::vector<S> &segments,
SegIterator<S> iterator,
- std::function<void (const S &, NodeId)> insert_segment_resolution);
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors);
tl::optional<Rib::Definition> resolve_final_segment (Node &final_node,
std::string &seg_name,
@@ -823,6 +838,21 @@ private:
tl::optional<Node &> dfs_node (Node &starting_point, NodeId to_find);
tl::optional<const Node &> dfs_node (const Node &starting_point,
NodeId to_find) const;
+
+public:
+ bool forward_declared (NodeId definition, NodeId usage)
+ {
+ if (peek ().kind != Rib::Kind::ForwardTypeParamBan)
+ return false;
+
+ const auto &definition_rib = dfs_rib (cursor (), definition);
+
+ if (!definition_rib)
+ return false;
+
+ return (definition_rib
+ && definition_rib.value ().kind == Rib::Kind::ForwardTypeParamBan);
+ }
};
} // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 885f282..848f5e6 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -20,6 +20,7 @@
#include "rust-ast.h"
#include "rust-diagnostics.h"
#include "rust-forever-stack.h"
+#include "rust-edition.h"
#include "rust-rib.h"
#include "rust-unwrap-segment.h"
#include "optional.h"
@@ -290,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 (
@@ -319,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 ());
@@ -397,12 +409,13 @@ ForeverStack<N>::find_closest_module (Node &starting_point)
* segments */
template <typename S>
static inline bool
-check_leading_kw_at_start (const S &segment, bool condition)
+check_leading_kw_at_start (std::vector<Error> &collect_errors, const S &segment,
+ bool condition)
{
if (condition)
- rust_error_at (
+ collect_errors.emplace_back (
segment.get_locus (), ErrorCode::E0433,
- "leading path segment %qs can only be used at the beginning of a path",
+ "%qs in paths can only be used in start position",
segment.as_string ().c_str ());
return condition;
@@ -418,7 +431,8 @@ template <typename S>
tl::optional<typename std::vector<S>::const_iterator>
ForeverStack<N>::find_starting_point (
const std::vector<S> &segments, std::reference_wrapper<Node> &starting_point,
- std::function<void (const S &, NodeId)> insert_segment_resolution)
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors)
{
auto iterator = segments.begin ();
@@ -435,8 +449,9 @@ ForeverStack<N>::find_starting_point (
// if we're after the first path segment and meet `self` or `crate`, it's
// an error - we should only be seeing `super` keywords at this point
- if (check_leading_kw_at_start (seg, !is_start (iterator, segments)
- && is_self_or_crate))
+ if (check_leading_kw_at_start (collect_errors, seg,
+ !is_start (iterator, segments)
+ && is_self_or_crate))
return tl::nullopt;
if (seg.is_crate_path_seg ())
@@ -459,8 +474,9 @@ ForeverStack<N>::find_starting_point (
starting_point = find_closest_module (starting_point);
if (starting_point.get ().is_root ())
{
- rust_error_at (seg.get_locus (), ErrorCode::E0433,
- "too many leading %<super%> keywords");
+ collect_errors.emplace_back (
+ seg.get_locus (), ErrorCode::E0433,
+ "too many leading %<super%> keywords");
return tl::nullopt;
}
@@ -486,7 +502,8 @@ tl::optional<typename ForeverStack<N>::Node &>
ForeverStack<N>::resolve_segments (
Node &starting_point, const std::vector<S> &segments,
typename std::vector<S>::const_iterator iterator,
- std::function<void (const S &, NodeId)> insert_segment_resolution)
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors)
{
Node *current_node = &starting_point;
for (; !is_last (iterator, segments); iterator++)
@@ -508,12 +525,13 @@ ForeverStack<N>::resolve_segments (
rust_debug ("[ARTHUR]: resolving segment part: %s", str.c_str ());
// check that we don't encounter *any* leading keywords afterwards
- if (check_leading_kw_at_start (seg, seg.is_crate_path_seg ()
- || seg.is_super_path_seg ()
- || seg.is_lower_self_seg ()))
+ if (check_leading_kw_at_start (collect_errors, seg,
+ seg.is_crate_path_seg ()
+ || seg.is_super_path_seg ()
+ || seg.is_lower_self_seg ()))
return tl::nullopt;
- tl::optional<typename ForeverStack<N>::Node &> child = tl::nullopt;
+ tl::optional<std::reference_wrapper<Node>> child = tl::nullopt;
/*
* On every iteration this loop either
@@ -535,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)
{
@@ -557,10 +583,17 @@ ForeverStack<N>::resolve_segments (
break;
}
- if (N == Namespace::Types)
+ auto rib_lookup = current_node->rib.get (seg.as_string ());
+ if (rib_lookup && !rib_lookup->is_ambiguous ())
{
- auto rib_lookup = current_node->rib.get (seg.as_string ());
- if (rib_lookup && !rib_lookup->is_ambiguous ())
+ if (Analysis::Mappings::get ()
+ .lookup_glob_container (rib_lookup->get_node_id ())
+ .has_value ())
+ {
+ child = dfs_node (root, rib_lookup->get_node_id ()).value ();
+ break;
+ }
+ else
{
insert_segment_resolution (outer_seg,
rib_lookup->get_node_id ());
@@ -585,9 +618,9 @@ ForeverStack<N>::resolve_segments (
current_node = &current_node->parent.value ();
}
- // if child didn't contain a value
- // the while loop above should have return'd or kept looping
- current_node = &child.value ();
+ // if child didn't point to a value
+ // the while loop above would have returned or kept looping
+ current_node = &child->get ();
insert_segment_resolution (outer_seg, current_node->id);
}
@@ -618,48 +651,118 @@ template <Namespace N>
template <typename S>
tl::optional<Rib::Definition>
ForeverStack<N>::resolve_path (
- const std::vector<S> &segments,
- std::function<void (const S &, NodeId)> insert_segment_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 ());
+
+ std::reference_wrapper<Node> starting_point = cursor ();
+ switch (mode)
+ {
+ 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);
+ 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 ());
+ 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)
- .and_then ([this, &segments, &starting_point, &insert_segment_resolution] (
- typename std::vector<S>::const_iterator iterator) {
- return resolve_segments (starting_point.get (), segments, iterator,
- insert_segment_resolution);
- })
+ 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> {
+ 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;
@@ -675,6 +778,26 @@ ForeverStack<N>::resolve_path (
if (!res)
res = get_lang_prelude (seg_name);
+ if (N == Namespace::Types && !res)
+ {
+ // HACK: check for a module after we check the language prelude
+ for (auto &kv : final_node.children)
+ {
+ auto &link = kv.first;
+
+ if (link.path.map_or (
+ [&seg_name] (Identifier path) {
+ auto &path_str = path.as_string ();
+ return path_str == seg_name;
+ },
+ false))
+ {
+ insert_segment_resolution (segments.back (), kv.second.id);
+ return Rib::Definition::NonShadowable (kv.second.id);
+ }
+ }
+ }
+
if (res && !res->is_ambiguous ())
insert_segment_resolution (segments.back (), res->get_node_id ());
@@ -744,67 +867,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-ice-finalizer.cc b/gcc/rust/resolve/rust-ice-finalizer.cc
index bd4763f..79a06c3 100644
--- a/gcc/rust/resolve/rust-ice-finalizer.cc
+++ b/gcc/rust/resolve/rust-ice-finalizer.cc
@@ -22,12 +22,12 @@ namespace Rust {
namespace Resolver {
void ATTRIBUTE_NORETURN
-funny_ice_text_finalizer (diagnostic_text_output_format &text_output,
- const diagnostic_info *diagnostic,
- diagnostic_t diag_kind)
+funny_ice_text_finalizer (diagnostics::text_sink &text_output,
+ const diagnostics::diagnostic_info *diagnostic,
+ enum diagnostics::kind diag_kind)
{
- gcc_assert (diag_kind == DK_ICE_NOBT);
- default_diagnostic_text_finalizer (text_output, diagnostic, diag_kind);
+ gcc_assert (diag_kind == diagnostics::kind::ice_nobt);
+ diagnostics::default_text_finalizer (text_output, diagnostic, diag_kind);
fnotice (stderr, "You have broken GCC Rust. This is a feature.\n");
exit (ICE_EXIT_CODE);
}
diff --git a/gcc/rust/resolve/rust-ice-finalizer.h b/gcc/rust/resolve/rust-ice-finalizer.h
index 85ab88f..5120176 100644
--- a/gcc/rust/resolve/rust-ice-finalizer.h
+++ b/gcc/rust/resolve/rust-ice-finalizer.h
@@ -55,9 +55,9 @@ namespace Resolver {
the default bug reporting instructions, as there is no bug to report. */
void ATTRIBUTE_NORETURN
-funny_ice_text_finalizer (diagnostic_text_output_format &text_output,
- const diagnostic_info *diagnostic,
- diagnostic_t diag_kind);
+funny_ice_text_finalizer (diagnostics::text_sink &text_output,
+ const diagnostics::diagnostic_info *diagnostic,
+ enum diagnostics::kind diag_kind);
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index 7d32374..96b38f4 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -19,10 +19,12 @@
#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"
#include "rust-name-resolution-context.h"
+#include "rust-resolve-builtins.h"
#include "rust-path.h"
#include "rust-system.h"
#include "rust-tyty.h"
@@ -33,99 +35,71 @@
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 ()
+void
+Late::go (AST::Crate &crate)
{
- return Analysis::Mappings::get ().get_next_node_id ();
-};
+ Builtins::setup_type_ctx ();
+
+ visit (crate);
+}
-static HirId
-next_hir_id ()
+void
+Late::new_label (Identifier name, NodeId id)
{
- return Analysis::Mappings::get ().get_next_hir_id ();
-};
+ // labels can always shadow, so `insert` should never fail. if it does, we're
+ // in big trouble!
+ auto ok = ctx.labels.insert (name, id);
+
+ rust_assert (ok);
+}
void
-Late::setup_builtin_types ()
-{
- // access the global type context to setup the TyTys
- auto &ty_ctx = *Resolver::TypeCheckContext::get ();
-
- // Late builtin type struct helper
- struct LType
- {
- std::string name;
- NodeId node_id;
- NodeId hir_id;
- TyTy::BaseType *type;
-
- explicit LType (std::string name, TyTy::BaseType *type)
- : name (name), node_id (next_node_id ()), hir_id (type->get_ref ()),
- type (type)
- {}
- };
-
- static const LType builtins[] = {
- {LType ("bool", new TyTy::BoolType (next_hir_id ()))},
- {LType ("u8", new TyTy::UintType (next_hir_id (), TyTy::UintType::U8))},
- {LType ("u16", new TyTy::UintType (next_hir_id (), TyTy::UintType::U16))},
- {LType ("u32", new TyTy::UintType (next_hir_id (), TyTy::UintType::U32))},
- {LType ("u64", new TyTy::UintType (next_hir_id (), TyTy::UintType::U64))},
- {LType ("u128", new TyTy::UintType (next_hir_id (), TyTy::UintType::U128))},
- {LType ("i8", new TyTy::IntType (next_hir_id (), TyTy::IntType::I8))},
- {LType ("i16", new TyTy::IntType (next_hir_id (), TyTy::IntType::I16))},
- {LType ("i32", new TyTy::IntType (next_hir_id (), TyTy::IntType::I32))},
- {LType ("i64", new TyTy::IntType (next_hir_id (), TyTy::IntType::I64))},
- {LType ("i128", new TyTy::IntType (next_hir_id (), TyTy::IntType::I128))},
- {LType ("f32", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F32))},
- {LType ("f64", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F64))},
- {LType ("usize", new TyTy::USizeType (next_hir_id ()))},
- {LType ("isize", new TyTy::ISizeType (next_hir_id ()))},
- {LType ("char", new TyTy::CharType (next_hir_id ()))},
- {LType ("str", new TyTy::StrType (next_hir_id ()))},
- {LType ("!", new TyTy::NeverType (next_hir_id ()))},
-
- // the unit type `()` does not play a part in name-resolution - so we only
- // insert it in the type context...
- };
-
- // There's a special Rib for putting prelude items, since prelude items need
- // to satisfy certain special rules.
- ctx.scoped (Rib::Kind::Prelude, 0, [this, &ty_ctx] (void) -> void {
- for (const auto &builtin : builtins)
- {
- auto ok = ctx.types.insert (builtin.name, builtin.node_id);
- rust_assert (ok);
-
- ctx.mappings.insert_node_to_hir (builtin.node_id, builtin.hir_id);
- ty_ctx.insert_builtin (builtin.hir_id, builtin.node_id, builtin.type);
- }
- });
-
- // ...here!
- auto *unit_type = TyTy::TupleType::get_unit_type ();
- ty_ctx.insert_builtin (unit_type->get_ref (), next_node_id (), unit_type);
+Late::visit (AST::ForLoopExpr &expr)
+{
+ visit_outer_attrs (expr);
+
+ ctx.bindings.enter (BindingSource::For);
+
+ visit (expr.get_pattern ());
+
+ ctx.bindings.exit ();
+
+ visit (expr.get_iterator_expr ());
+
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
+
+ visit (expr.get_loop_block ());
}
void
-Late::go (AST::Crate &crate)
+Late::visit_if_let_patterns (AST::IfLetExpr &expr)
{
- setup_builtin_types ();
+ ctx.bindings.enter (BindingSource::IfLet);
- for (auto &item : crate.items)
- item->accept_vis (*this);
+ DefaultResolver::visit_if_let_patterns (expr);
+
+ ctx.bindings.exit ();
}
void
-Late::new_label (Identifier name, NodeId id)
+Late::visit (AST::MatchArm &arm)
{
- // labels can always shadow, so `insert` should never fail. if it does, we're
- // in big trouble!
- auto ok = ctx.labels.insert (name, id);
+ visit_outer_attrs (arm);
- rust_assert (ok);
+ ctx.bindings.enter (BindingSource::Match);
+
+ for (auto &pattern : arm.get_patterns ())
+ visit (pattern);
+
+ ctx.bindings.exit ();
+
+ if (arm.has_match_arm_guard ())
+ visit (arm.get_guard_expr ());
}
void
@@ -138,8 +112,13 @@ Late::visit (AST::LetStmt &let)
// this makes variable shadowing work properly
if (let.has_init_expr ())
visit (let.get_init_expr ());
+
+ ctx.bindings.enter (BindingSource::Let);
+
visit (let.get_pattern ());
+ ctx.bindings.exit ();
+
if (let.has_else_expr ())
visit (let.get_init_expr ());
@@ -161,15 +140,109 @@ 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?
- // 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 ());
+ if (ctx.bindings.peek ().is_and_bound (ident))
+ {
+ if (ctx.bindings.peek ().get_source () == BindingSource::Param)
+ rust_error_at (
+ locus, ErrorCode::E0415,
+ "identifier %qs is bound more than once in the same parameter list",
+ ident.as_string ().c_str ());
+ else
+ rust_error_at (
+ locus, ErrorCode::E0416,
+ "identifier %qs is bound more than once in the same pattern",
+ ident.as_string ().c_str ());
+ return;
+ }
+
+ ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
+
+ if (ctx.bindings.peek ().is_or_bound (ident))
+ {
+ 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 (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);
+ for (auto &alt : pattern.get_alts ())
+ {
+ ctx.bindings.peek ().push (Binding::Kind::Product);
+ visit (alt);
+ ctx.bindings.peek ().merge ();
+ }
+ ctx.bindings.peek ().merge ();
+}
+
+void
+Late::visit_function_params (AST::Function &function)
+{
+ ctx.bindings.enter (BindingSource::Param);
+
+ for (auto &param : function.get_function_params ())
+ visit (param);
+
+ ctx.bindings.exit ();
+}
+
+void
+Late::visit (AST::StructPatternFieldIdent &field)
+{
+ visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (),
+ field.get_node_id (), field.is_ref (),
+ field.is_mut ());
}
void
@@ -187,6 +260,9 @@ Late::visit (AST::SelfParam &param)
void
Late::visit (AST::BreakExpr &expr)
{
+ if (expr.has_label ())
+ resolve_label (expr.get_label_unchecked ().get_lifetime ());
+
if (expr.has_break_expr ())
{
auto &break_expr = expr.get_break_expr ();
@@ -213,6 +289,38 @@ Late::visit (AST::BreakExpr &expr)
}
void
+Late::visit (AST::LoopLabel &label)
+{
+ auto &lifetime = label.get_lifetime ();
+ ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()),
+ lifetime.get_node_id ());
+}
+
+void
+Late::resolve_label (AST::Lifetime &lifetime)
+{
+ if (auto resolved = ctx.labels.get (lifetime.as_string ()))
+ {
+ if (resolved->get_node_id () != lifetime.get_node_id ())
+ ctx.map_usage (Usage (lifetime.get_node_id ()),
+ Definition (resolved->get_node_id ()));
+ }
+ else
+ rust_error_at (lifetime.get_locus (), ErrorCode::E0426,
+ "use of undeclared label %qs",
+ lifetime.as_string ().c_str ());
+}
+
+void
+Late::visit (AST::ContinueExpr &expr)
+{
+ if (expr.has_label ())
+ resolve_label (expr.get_label_unchecked ());
+
+ DefaultResolver::visit (expr);
+}
+
+void
Late::visit (AST::IdentifierExpr &expr)
{
// TODO: same thing as visit(PathInExpression) here?
@@ -228,8 +336,9 @@ Late::visit (AST::IdentifierExpr &expr)
}
else if (funny_error)
{
- diagnostic_text_finalizer (global_dc) = Resolver::funny_ice_text_finalizer;
- emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1,
+ 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 ());
}
@@ -307,14 +416,13 @@ Late::visit (AST::PathInExpression &expr)
return;
}
- auto resolved = ctx.resolve_path (expr.get_segments (), Namespace::Values,
- Namespace::Types);
+ auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types);
if (!resolved)
{
if (!ctx.lookup (expr.get_segments ().front ().get_node_id ()))
- rust_error_at (expr.get_locus (),
- "could not resolve path expression: %qs",
+ rust_error_at (expr.get_locus (), ErrorCode::E0433,
+ "Cannot find path %qs in this scope",
expr.as_simple_path ().as_string ().c_str ());
return;
}
@@ -331,43 +439,134 @@ Late::visit (AST::PathInExpression &expr)
}
void
-Late::visit (AST::TypePath &type)
+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;
+}
+
+template <typename P>
+static void
+resolve_type_path_like (NameResolutionContext &ctx, bool block_big_self,
+ P &type)
{
// should we add type path resolution in `ForeverStack` directly? Since it's
// quite more complicated.
// maybe we can overload `resolve_path<Namespace::Types>` to only do
// typepath-like path resolution? that sounds good
- DefaultResolver::visit (type);
-
- // take care of only simple cases
- // TODO: remove this?
- rust_assert (!type.has_opening_scope_resolution_op ());
+ // prevent "impl Self {}" and similar
+ if (type.get_segments ().size () == 1
+ && !unwrap_segment_get_lang_item (type.get_segments ().front ())
+ .has_value ()
+ && unwrap_type_segment (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.get_segments (), Namespace::Types);
+ auto resolved = ctx.resolve_path (type, Namespace::Types);
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 ());
+ if (!ctx.lookup (unwrap_segment_node_id (type.get_segments ().front ())))
+ rust_error_at (type.get_locus (), ErrorCode::E0412,
+ "could not resolve type path %qs",
+ unwrap_segment_error_string (type).c_str ());
return;
}
if (resolved->is_ambiguous ())
{
rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
- type.as_string ().c_str ());
+ unwrap_segment_error_string (type).c_str ());
return;
}
+ if (ctx.types.forward_declared (resolved->get_node_id (),
+ type.get_node_id ()))
+ {
+ rust_error_at (type.get_locus (), ErrorCode::E0128,
+ "type parameters with a default cannot use forward "
+ "declared identifiers");
+ }
+
ctx.map_usage (Usage (type.get_node_id ()),
Definition (resolved->get_node_id ()));
}
void
+Late::visit (AST::TypePath &type)
+{
+ DefaultResolver::visit (type);
+
+ resolve_type_path_like (ctx, block_big_self, 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
@@ -381,24 +580,13 @@ 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);
visit_inner_attrs (s);
DefaultResolver::visit (s.get_struct_name ());
- auto resolved
- = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types);
-
- ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
- Definition (resolved->get_node_id ()));
+ resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
}
void
@@ -409,11 +597,7 @@ Late::visit (AST::StructExprStructBase &s)
DefaultResolver::visit (s.get_struct_name ());
visit (s.get_struct_base ());
- auto resolved
- = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types);
-
- ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
- Definition (resolved->get_node_id ()));
+ resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
}
void
@@ -427,11 +611,7 @@ Late::visit (AST::StructExprStructFields &s)
for (auto &field : s.get_fields ())
visit (field);
- auto resolved
- = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types);
-
- ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
- Definition (resolved->get_node_id ()));
+ resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
}
// needed because Late::visit (AST::GenericArg &) is non-virtual
@@ -466,30 +646,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);
- DefaultResolver::visit (closure);
+ ctx.bindings.enter (BindingSource::Param);
+
+ DefaultResolver::visit_closure_params (closure);
+
+ ctx.bindings.exit ();
}
void
-Late::visit (AST::ClosureExprInnerTyped &closure)
+Late::visit (AST::ClosureExpr &expr)
{
- add_captures (closure, ctx);
- DefaultResolver::visit (closure);
+ // 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 ());
+ }
+
+ 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 ac376b5..608ae38 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -37,34 +37,48 @@ public:
void new_label (Identifier name, NodeId id);
+ // Specialized visit bits
+ void visit_function_params (AST::Function &function) override;
+
// 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;
+ void visit (AST::StructPatternFieldIdent &) override;
+ void visit (AST::AltPattern &) override;
void visit (AST::SelfParam &) override;
+ void visit (AST::MatchArm &) override;
+ void visit (AST::ForLoopExpr &) override;
+ void visit_if_let_patterns (AST::IfLetExpr &) override;
// resolutions
void visit (AST::IdentifierExpr &) override;
void visit (AST::StructExprFieldIdentifier &) override;
void visit (AST::BreakExpr &) override;
+ 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:
- /* Setup Rust's builtin types (u8, i32, !...) in the resolver */
- void setup_builtin_types ();
+ void resolve_label (AST::Lifetime &lifetime);
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 92c4863..1b84f1d 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -23,8 +23,169 @@
namespace Rust {
namespace Resolver2_0 {
+BindingLayer::BindingLayer (BindingSource source) : source (source)
+{
+ push (Binding::Kind::Product);
+}
+
+bool
+BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
+{
+ for (auto &bind : bindings)
+ {
+ if (bind.idents.find (ident.as_string ()) != bind.idents.cend ()
+ && bind.kind == kind)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+BindingLayer::push (Binding::Kind kind)
+{
+ bindings.push_back (Binding (kind));
+}
+
+bool
+BindingLayer::is_and_bound (Identifier ident)
+{
+ return bind_test (ident, Binding::Kind::Product);
+}
+
+bool
+BindingLayer::is_or_bound (Identifier ident)
+{
+ return bind_test (ident, Binding::Kind::Or);
+}
+
+void
+BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref,
+ bool is_mut)
+{
+ bindings.back ().idents.emplace (
+ std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut)));
+}
+
+void
+BindingLayer::merge ()
+{
+ auto last_binding = std::move (bindings.back ());
+ bindings.pop_back ();
+
+ 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)
+ {
+ 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
+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 ea81bde..558b3ca 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -23,6 +23,8 @@
#include "rust-forever-stack.h"
#include "rust-hir-map.h"
#include "rust-rib.h"
+#include "rust-stacked-contexts.h"
+#include "rust-item.h"
namespace Rust {
namespace Resolver2_0 {
@@ -156,6 +158,326 @@ 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
+ {
+ Product,
+ Or,
+ } kind;
+
+ // used to check the correctness of or-bindings
+ bool has_expected_bindings;
+
+ std::unordered_map<std::string, std::pair<location_t, IdentifierMode>> idents;
+
+ Binding (Binding::Kind kind) : kind (kind), has_expected_bindings (false) {}
+};
+
+/**
+ * Used to identify the source of a binding, and emit the correct error message.
+ */
+enum class BindingSource
+{
+ Match,
+ Let,
+ IfLet,
+ WhileLet,
+ For,
+ /* Closure param or function param */
+ Param
+};
+
+class BindingLayer
+{
+ BindingSource source;
+ std::vector<Binding> bindings;
+
+ bool bind_test (Identifier ident, Binding::Kind kind);
+
+public:
+ void push (Binding::Kind kind);
+
+ BindingLayer (BindingSource source);
+
+ /**
+ * Identifies if the identifier has been used in a product binding context.
+ * eg. `let (a, a) = test();`
+ */
+ bool is_and_bound (Identifier ident);
+
+ /**
+ * Identifies if the identifier has been used in a or context.
+ * eg. `let (a, 1) | (a, 2) = test()`
+ */
+ bool is_or_bound (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
{
@@ -212,6 +534,9 @@ public:
ForeverStack<Namespace::Labels> labels;
Analysis::Mappings &mappings;
+ StackedContexts<BindingLayer> bindings;
+
+ CanonicalPathCtx canonical_ctx;
// TODO: Rename
// TODO: Use newtype pattern for Usage and Definition
@@ -219,9 +544,15 @@ public:
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,
- Namespace ns)
+ tl::optional<Rib::Definition>
+ 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
= [this] (const S &seg, NodeId id) {
@@ -232,33 +563,119 @@ public:
switch (ns)
{
case Namespace::Values:
- return values.resolve_path (segments, insert_segment_resolution);
+ return values.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
case Namespace::Types:
- return types.resolve_path (segments, insert_segment_resolution);
+ return types.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
case Namespace::Macros:
- return macros.resolve_path (segments, insert_segment_resolution);
+ return macros.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
case Namespace::Labels:
- return labels.resolve_path (segments, insert_segment_resolution);
+ return labels.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
default:
rust_unreachable ();
}
}
template <typename S, typename... Args>
- tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments,
- Args... ns_args)
+ tl::optional<Rib::Definition>
+ resolve_path (const std::vector<S> &segments, ResolutionMode mode,
+ tl::optional<std::vector<Error> &> collect_errors,
+ Namespace ns_first, Args... ns_args)
{
- std::initializer_list<Namespace> namespaces = {ns_args...};
+ std::initializer_list<Namespace> namespaces = {ns_first, ns_args...};
for (auto ns : namespaces)
{
- if (auto ret = resolve_path (segments, ns))
+ std::vector<Error> collect_errors_inner;
+ if (auto ret = resolve_path (segments, mode, collect_errors_inner, ns))
return ret;
+ if (!collect_errors_inner.empty ())
+ {
+ if (collect_errors.has_value ())
+ {
+ std::move (collect_errors_inner.begin (),
+ collect_errors_inner.end (),
+ std::back_inserter (collect_errors.value ()));
+ }
+ else
+ {
+ for (auto &e : collect_errors_inner)
+ e.emit ();
+ }
+ return tl::nullopt;
+ }
}
return tl::nullopt;
}
+ template <typename S, typename... Args>
+ tl::optional<Rib::Definition>
+ 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)
+ {
+ 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 S, typename... Args>
+ tl::optional<Rib::Definition>
+ resolve_path (const std::vector<S> &path_segments,
+ bool has_opening_scope_resolution, Namespace ns_first,
+ Args... ns_args)
+ {
+ return resolve_path (path_segments, has_opening_scope_resolution,
+ tl::nullopt, ns_first, ns_args...);
+ }
+
+ template <typename S, typename... Args>
+ tl::optional<Rib::Definition>
+ 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 (),
+ std::forward<Args> (args)...);
+ }
+
+ template <typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const AST::PathInExpression &path,
+ Args &&...args)
+ {
+ return resolve_path (path.get_segments (), path.opening_scope_resolution (),
+ std::forward<Args> (args)...);
+ }
+
+ template <typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const AST::TypePath &path,
+ Args &&...args)
+ {
+ return resolve_path (path.get_segments (),
+ path.has_opening_scope_resolution_op (),
+ std::forward<Args> (args)...);
+ }
+
private:
/* Map of "usage" nodes which have been resolved to a "definition" node */
std::map<Usage, Definition> resolved_nodes;
diff --git a/gcc/rust/resolve/rust-resolve-builtins.cc b/gcc/rust/resolve/rust-resolve-builtins.cc
new file mode 100644
index 0000000..b16db9a
--- /dev/null
+++ b/gcc/rust/resolve/rust-resolve-builtins.cc
@@ -0,0 +1,125 @@
+// 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-resolve-builtins.h"
+#include "rust-name-resolution-context.h"
+#include "rust-tyty.h"
+#include "rust-hir-type-check.h"
+
+namespace Rust {
+namespace Resolver2_0 {
+namespace Builtins {
+
+// Use X-macros
+
+#define TYPE_UINT(n, enum_ident) TYPE1 (n, UintType, UintType::enum_ident)
+#define TYPE_INT(n, enum_ident) TYPE1 (n, IntType, IntType::enum_ident)
+
+#define BUILTIN_TYPES \
+ TYPE0 ("bool", BoolType) \
+ TYPE_UINT ("u8", U8) \
+ TYPE_UINT ("u16", U16) \
+ TYPE_UINT ("u32", U32) \
+ TYPE_UINT ("u64", U64) \
+ TYPE_UINT ("u128", U128) \
+ TYPE_INT ("i8", I8) \
+ TYPE_INT ("i16", I16) \
+ TYPE_INT ("i32", I32) \
+ TYPE_INT ("i64", I64) \
+ TYPE_INT ("i128", I128) \
+ TYPE1 ("f32", FloatType, FloatType::F32) \
+ TYPE1 ("f64", FloatType, FloatType::F64) \
+ TYPE0 ("usize", USizeType) \
+ TYPE0 ("isize", ISizeType) \
+ TYPE0 ("char", CharType) \
+ TYPE0 ("str", StrType) \
+ TYPE0 ("!", NeverType)
+
+// Define constants using X macros
+
+#define TYPE0(...) 1 +
+#define TYPE1(...) 1 +
+static constexpr size_t builtin_count = BUILTIN_TYPES 0;
+#undef TYPE0
+#undef TYPE1
+
+#define TYPE0(n, ...) n,
+#define TYPE1(n, ...) n,
+static constexpr const char *builtin_names[] = {BUILTIN_TYPES};
+#undef TYPE0
+#undef TYPE1
+
+static NodeId builtin_node_ids[builtin_count];
+
+void
+setup_lang_prelude (NameResolutionContext &ctx)
+{
+ auto &mappings = Analysis::Mappings::get ();
+
+ // insert into prelude rib
+ ctx.scoped (Rib::Kind::Prelude, 0, [&mappings, &ctx] (void) -> void {
+ for (size_t i = 0; i < builtin_count; i++)
+ {
+ NodeId node_id = mappings.get_next_node_id ();
+ rust_assert (ctx.types.insert (Identifier (builtin_names[i]), node_id));
+ builtin_node_ids[i] = node_id;
+ }
+ });
+}
+
+void
+setup_type_ctx ()
+{
+ auto &mappings = Analysis::Mappings::get ();
+ auto &ty_ctx = *Resolver::TypeCheckContext::get ();
+
+ HirId hir_ids[builtin_count];
+ for (size_t i = 0; i < builtin_count; i++)
+ hir_ids[i] = mappings.get_next_hir_id ();
+
+ TyTy::BaseType *types[builtin_count];
+ {
+ size_t i = 0;
+#define TYPE_BASE(stub) \
+ types[i] = new TyTy::stub; \
+ i++;
+#define TYPE0(n, ty) TYPE_BASE (ty (hir_ids[i]))
+#define TYPE1(n, ty, p1) TYPE_BASE (ty (hir_ids[i], TyTy::p1))
+ BUILTIN_TYPES
+#undef TYPE_BASE
+#undef TYPE0
+#undef TYPE1
+ }
+
+ for (size_t i = 0; i < builtin_count; i++)
+ {
+ NodeId node_id = builtin_node_ids[i];
+ HirId hir_id = hir_ids[i];
+ mappings.insert_node_to_hir (node_id, hir_id);
+ ty_ctx.insert_builtin (hir_id, node_id, types[i]);
+ }
+
+ // handle unit type separately
+ auto *unit_type = TyTy::TupleType::get_unit_type ();
+ ty_ctx.insert_builtin (unit_type->get_ref (), mappings.get_next_node_id (),
+ unit_type);
+}
+
+} // namespace Builtins
+} // namespace Resolver2_0
+} // namespace Rust
diff --git a/gcc/rust/resolve/rust-resolve-builtins.h b/gcc/rust/resolve/rust-resolve-builtins.h
new file mode 100644
index 0000000..e7e1bd2
--- /dev/null
+++ b/gcc/rust/resolve/rust-resolve-builtins.h
@@ -0,0 +1,37 @@
+// 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_RESOLVE_BUILTINS_H
+#define RUST_RESOLVE_BUILTINS_H
+
+namespace Rust {
+namespace Resolver2_0 {
+
+// forward declare
+class NameResolutionContext;
+
+namespace Builtins {
+
+void setup_lang_prelude (NameResolutionContext &ctx);
+void setup_type_ctx ();
+
+} // namespace Builtins
+} // namespace Resolver2_0
+} // namespace Rust
+
+#endif // RUST_RESOLVE_BUILTINS_H
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 8863be7..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,70 +95,32 @@ 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 ();
-
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
TopLevel::visit (AST::Trait &trait)
{
- insert_or_error_out (trait.get_identifier ().as_string (), trait,
- Namespace::Types);
+ insert_or_error_out (trait.get_identifier (), trait, Namespace::Types);
DefaultResolver::visit (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
@@ -188,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);
@@ -208,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
@@ -312,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);
@@ -365,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
@@ -392,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
@@ -421,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 (
@@ -446,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;
@@ -538,6 +492,8 @@ flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths,
{
if (glob.has_path ())
paths.emplace_back (glob.get_path ());
+ else
+ paths.emplace_back (AST::SimplePath ({}, false, glob.get_locus ()));
}
void
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
index 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..99496e6 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);
+LocalVariable 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);
+LocalVariable 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);
+LocalVariable 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);
+LocalVariable 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 0c0ef6e..5965bb4 100644
--- a/gcc/rust/rust-diagnostics.cc
+++ b/gcc/rust/rust-diagnostics.cc
@@ -22,7 +22,7 @@
#include "rust-diagnostics.h"
#include "options.h"
-#include "diagnostic-metadata.h"
+#include "diagnostics/metadata.h"
static std::string
mformat_value ()
@@ -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"
@@ -192,7 +199,7 @@ rust_error_at (const location_t location, const char *fmt, ...)
va_end (ap);
}
-class rust_error_code_rule : public diagnostic_metadata::rule
+class rust_error_code_rule : public diagnostics::metadata::rule
{
public:
rust_error_code_rule (const ErrorCode code) : m_code (code) {}
@@ -237,7 +244,7 @@ rust_be_error_at (const location_t location, const ErrorCode code,
const std::string &errmsg)
{
rich_location gcc_loc (line_table, location);
- diagnostic_metadata m;
+ diagnostics::metadata m;
rust_error_code_rule rule (code);
m.add_rule (rule);
error_meta (&gcc_loc, m, "%s", errmsg.c_str ());
@@ -260,7 +267,7 @@ rust_be_error_at (const rich_location &location, const ErrorCode code,
{
/* TODO: 'error_at' would like a non-'const' 'rich_location *'. */
rich_location &gcc_loc = const_cast<rich_location &> (location);
- diagnostic_metadata m;
+ diagnostics::metadata m;
rust_error_code_rule rule (code);
m.add_rule (rule);
error_meta (&gcc_loc, m, "%s", errmsg.c_str ());
@@ -281,7 +288,7 @@ void
rust_be_error_at (rich_location *richloc, const ErrorCode code,
const std::string &errmsg)
{
- diagnostic_metadata m;
+ diagnostics::metadata m;
rust_error_code_rule rule (code);
m.add_rule (rule);
error_meta (richloc, m, "%s", errmsg.c_str ());
@@ -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 a6e8ea9..750c392 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -61,7 +61,7 @@
tree
Bvariable::get_tree (location_t location) const
{
- if (this->t_ == error_mark_node)
+ if (error_operand_p (this->t_))
return error_mark_node;
TREE_USED (this->t_) = 1;
@@ -83,6 +83,23 @@ Bvariable::error_variable ()
return new Bvariable (error_mark_node);
}
+// Get the tree of a variable for use as an expression
+tree
+LocalVariable::get_tree (location_t location) const
+{
+ if (error_operand_p (t))
+ return error_mark_node;
+
+ TREE_USED (t) = 1;
+ return t;
+}
+
+LocalVariable
+LocalVariable::error_variable ()
+{
+ return LocalVariable (error_mark_node);
+}
+
// This file implements the interface between the Rust frontend proper
// and the gcc IR. This implements specific instantiations of
// abstract classes defined by the Rust frontend proper. The Rust
@@ -91,12 +108,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.
@@ -431,7 +442,7 @@ float_type (int bits)
tree
pointer_type (tree to_type)
{
- if (to_type == error_mark_node)
+ if (error_operand_p (to_type))
return error_mark_node;
tree type = build_pointer_type (to_type);
return type;
@@ -442,7 +453,7 @@ pointer_type (tree to_type)
tree
reference_type (tree to_type)
{
- if (to_type == error_mark_node)
+ if (error_operand_p (to_type))
return error_mark_node;
tree type = build_reference_type (to_type);
return type;
@@ -453,7 +464,7 @@ reference_type (tree to_type)
tree
immutable_type (tree base)
{
- if (base == error_mark_node)
+ if (error_operand_p (base))
return error_mark_node;
tree constified = build_qualified_type (base, TYPE_QUAL_CONST);
return constified;
@@ -472,17 +483,16 @@ function_type (const typed_identifier &receiver,
if (receiver.type != NULL_TREE)
{
tree t = receiver.type;
- if (t == error_mark_node)
+ if (error_operand_p (t))
return error_mark_node;
*pp = tree_cons (NULL_TREE, t, NULL_TREE);
pp = &TREE_CHAIN (*pp);
}
- for (std::vector<typed_identifier>::const_iterator p = parameters.begin ();
- p != parameters.end (); ++p)
+ for (const auto &p : parameters)
{
- tree t = p->type;
- if (t == error_mark_node)
+ tree t = p.type;
+ if (error_operand_p (t))
return error_mark_node;
*pp = tree_cons (NULL_TREE, t, NULL_TREE);
pp = &TREE_CHAIN (*pp);
@@ -502,11 +512,11 @@ function_type (const typed_identifier &receiver,
gcc_assert (result_struct != NULL);
result = result_struct;
}
- if (result == error_mark_node)
+ if (error_operand_p (result))
return error_mark_node;
tree fntype = build_function_type (result, args);
- if (fntype == error_mark_node)
+ if (error_operand_p (fntype))
return error_mark_node;
return build_pointer_type (fntype);
@@ -521,21 +531,16 @@ function_type_variadic (const typed_identifier &receiver,
size_t n = parameters.size () + (receiver.type != NULL_TREE ? 1 : 0);
tree *args = XALLOCAVEC (tree, n);
size_t offs = 0;
+ if (error_operand_p (receiver.type))
+ return error_mark_node;
if (receiver.type != NULL_TREE)
- {
- tree t = receiver.type;
- if (t == error_mark_node)
- return error_mark_node;
-
- args[offs++] = t;
- }
+ args[offs++] = receiver.type;
- for (std::vector<typed_identifier>::const_iterator p = parameters.begin ();
- p != parameters.end (); ++p)
+ for (const auto &p : parameters)
{
- tree t = p->type;
- if (t == error_mark_node)
+ tree t = p.type;
+ if (error_operand_p (t))
return error_mark_node;
args[offs++] = t;
}
@@ -550,11 +555,11 @@ function_type_variadic (const typed_identifier &receiver,
gcc_assert (result_struct != NULL_TREE);
result = result_struct;
}
- if (result == error_mark_node)
+ if (error_operand_p (result))
return error_mark_node;
tree fntype = build_varargs_function_type_array (result, n, args);
- if (fntype == error_mark_node)
+ if (error_operand_p (fntype))
return error_mark_node;
return build_pointer_type (fntype);
@@ -569,7 +574,7 @@ function_ptr_type (tree result_type, const std::vector<tree> &parameters,
for (auto &param : parameters)
{
- if (param == error_mark_node)
+ if (error_operand_p (param))
return error_mark_node;
*pp = tree_cons (NULL_TREE, param, NULL_TREE);
@@ -583,7 +588,7 @@ function_ptr_type (tree result_type, const std::vector<tree> &parameters,
result = void_type_node;
tree fntype = build_function_type (result, args);
- if (fntype == error_mark_node)
+ if (error_operand_p (fntype))
return error_mark_node;
return build_pointer_type (fntype);
@@ -613,14 +618,13 @@ fill_in_fields (tree fill, const std::vector<typed_identifier> &fields,
{
tree field_trees = NULL_TREE;
tree *pp = &field_trees;
- for (std::vector<typed_identifier>::const_iterator p = fields.begin ();
- p != fields.end (); ++p)
+ for (const auto &p : fields)
{
- tree name_tree = get_identifier_from_string (p->name);
- tree type_tree = p->type;
- if (type_tree == error_mark_node)
+ tree name_tree = p.name.as_tree ();
+ tree type_tree = p.type;
+ if (error_operand_p (type_tree))
return error_mark_node;
- tree field = build_decl (p->location, FIELD_DECL, name_tree, type_tree);
+ tree field = build_decl (p.location, FIELD_DECL, name_tree, type_tree);
DECL_CONTEXT (field) = fill;
*pp = field;
pp = &DECL_CHAIN (field);
@@ -652,7 +656,7 @@ array_type (tree element_type, tree length)
tree
fill_in_array (tree fill, tree element_type, tree length_tree)
{
- if (element_type == error_mark_node || length_tree == error_mark_node)
+ if (error_operand_p (element_type) || error_operand_p (length_tree))
return error_mark_node;
gcc_assert (TYPE_SIZE (element_type) != NULL_TREE);
@@ -682,9 +686,9 @@ 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 (type == error_mark_node)
+ if (error_operand_p (type))
return error_mark_node;
// The middle-end expects a basic type to have a name. In Rust every
@@ -695,15 +699,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;
@@ -714,7 +717,7 @@ named_type (const std::string &name, tree type, location_t location)
int64_t
type_size (tree t)
{
- if (t == error_mark_node)
+ if (error_operand_p (t))
return 1;
if (t == void_type_node)
return 0;
@@ -732,7 +735,7 @@ type_size (tree t)
int64_t
type_alignment (tree t)
{
- if (t == error_mark_node)
+ if (error_operand_p (t))
return 1;
return TYPE_ALIGN_UNIT (t);
}
@@ -742,7 +745,7 @@ type_alignment (tree t)
int64_t
type_field_alignment (tree t)
{
- if (t == error_mark_node)
+ if (error_operand_p (t))
return 1;
return rust_field_alignment (t);
}
@@ -752,7 +755,7 @@ type_field_alignment (tree t)
int64_t
type_field_offset (tree struct_tree, size_t index)
{
- if (struct_tree == error_mark_node)
+ if (error_operand_p (struct_tree))
return 0;
gcc_assert (TREE_CODE (struct_tree) == RECORD_TYPE);
tree field = TYPE_FIELDS (struct_tree);
@@ -773,7 +776,7 @@ tree
zero_expression (tree t)
{
tree ret;
- if (t == error_mark_node)
+ if (error_operand_p (t))
ret = error_mark_node;
else
ret = build_zero_cst (t);
@@ -794,7 +797,7 @@ tree
float_constant_expression (tree t, mpfr_t val)
{
tree ret;
- if (t == error_mark_node)
+ if (error_operand_p (t))
return error_mark_node;
REAL_VALUE_TYPE r1;
@@ -832,6 +835,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
@@ -845,8 +854,7 @@ boolean_constant_expression (bool val)
tree
convert_expression (tree type_tree, tree expr_tree, location_t location)
{
- if (type_tree == error_mark_node || expr_tree == error_mark_node
- || TREE_TYPE (expr_tree) == error_mark_node)
+ if (error_operand_p (type_tree) || error_operand_p (expr_tree))
return error_mark_node;
tree ret;
@@ -878,8 +886,7 @@ convert_expression (tree type_tree, tree expr_tree, location_t location)
tree
struct_field_expression (tree struct_tree, size_t index, location_t location)
{
- if (struct_tree == error_mark_node
- || TREE_TYPE (struct_tree) == error_mark_node)
+ if (error_operand_p (struct_tree))
return error_mark_node;
gcc_assert (TREE_CODE (TREE_TYPE (struct_tree)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (struct_tree)) == UNION_TYPE);
@@ -895,7 +902,7 @@ struct_field_expression (tree struct_tree, size_t index, location_t location)
field = DECL_CHAIN (field);
gcc_assert (field != NULL_TREE);
}
- if (TREE_TYPE (field) == error_mark_node)
+ if (error_operand_p (TREE_TYPE (field)))
return error_mark_node;
tree ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (field),
struct_tree, field, NULL_TREE);
@@ -909,7 +916,7 @@ struct_field_expression (tree struct_tree, size_t index, location_t location)
tree
compound_expression (tree stat, tree expr, location_t location)
{
- if (stat == error_mark_node || expr == error_mark_node)
+ if (error_operand_p (stat) || error_operand_p (expr))
return error_mark_node;
tree ret
= fold_build2_loc (location, COMPOUND_EXPR, TREE_TYPE (expr), stat, expr);
@@ -923,8 +930,8 @@ tree
conditional_expression (tree, tree type_tree, tree cond_expr, tree then_expr,
tree else_expr, location_t location)
{
- if (type_tree == error_mark_node || cond_expr == error_mark_node
- || then_expr == error_mark_node || else_expr == error_mark_node)
+ if (error_operand_p (type_tree) || error_operand_p (cond_expr)
+ || error_operand_p (then_expr) || error_operand_p (else_expr))
return error_mark_node;
tree ret = build3_loc (location, COND_EXPR, type_tree, cond_expr, then_expr,
else_expr);
@@ -1021,12 +1028,12 @@ operator_to_tree_code (LazyBooleanOperator op)
}
}
-/* Helper function for deciding if a tree is a floating point node. */
+/* Returns true if the type of EXP is a floating point type.
+ False otherwise. */
bool
-is_floating_point (tree t)
+is_floating_point (tree exp)
{
- auto tree_type = TREE_CODE (TREE_TYPE (t));
- return tree_type == REAL_TYPE || tree_type == COMPLEX_TYPE;
+ return FLOAT_TYPE_P (TREE_TYPE (exp));
}
// Return an expression for the negation operation OP EXPR.
@@ -1035,7 +1042,7 @@ negation_expression (NegationOperator op, tree expr_tree, location_t location)
{
/* Check if the expression is an error, in which case we return an error
expression. */
- if (expr_tree == error_mark_node || TREE_TYPE (expr_tree) == error_mark_node)
+ if (error_operand_p (expr_tree))
return error_mark_node;
/* For negation operators, the resulting type should be the same as its
@@ -1071,9 +1078,15 @@ arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left,
{
/* Check if either expression is an error, in which case we return an error
expression. */
- if (left == error_mark_node || right == error_mark_node)
+ if (error_operand_p (left) || error_operand_p (right))
return error_mark_node;
+ // unwrap the const decls if set
+ if (TREE_CODE (left) == CONST_DECL)
+ left = DECL_INITIAL (left);
+ if (TREE_CODE (right) == CONST_DECL)
+ right = DECL_INITIAL (right);
+
/* We need to determine if we're doing floating point arithmetics of integer
arithmetics. */
bool floating_point = is_floating_point (left);
@@ -1112,6 +1125,7 @@ arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left,
rust_error_at (location, "division by zero");
}
else if (op == ArithmeticOrLogicalOperator::LEFT_SHIFT
+ && TREE_CODE (right) == INTEGER_CST
&& (compare_tree_int (right, TYPE_PRECISION (TREE_TYPE (ret))) >= 0))
{
rust_error_at (location, "left shift count >= width of type");
@@ -1176,7 +1190,7 @@ arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op,
{
/* Check if either expression is an error, in which case we return an error
expression. */
- if (left == error_mark_node || right == error_mark_node)
+ if (error_operand_p (left) || error_operand_p (right))
return error_mark_node;
// FIXME: Add `if (!debug_mode)`
@@ -1216,7 +1230,7 @@ comparison_expression (ComparisonOperator op, tree left_tree, tree right_tree,
{
/* Check if either expression is an error, in which case we return an error
expression. */
- if (left_tree == error_mark_node || right_tree == error_mark_node)
+ if (error_operand_p (left_tree) || error_operand_p (right_tree))
return error_mark_node;
/* For comparison operators, the resulting type should be boolean. */
@@ -1236,7 +1250,7 @@ lazy_boolean_expression (LazyBooleanOperator op, tree left_tree,
{
/* Check if either expression is an error, in which case we return an error
expression. */
- if (left_tree == error_mark_node || right_tree == error_mark_node)
+ if (error_operand_p (left_tree) || error_operand_p (right_tree))
return error_mark_node;
/* For lazy boolean operators, the resulting type should be the same as the
@@ -1257,11 +1271,11 @@ constructor_expression (tree type_tree, bool is_variant,
const std::vector<tree> &vals, int union_index,
location_t location)
{
- if (type_tree == error_mark_node)
+ if (error_operand_p (type_tree))
return error_mark_node;
vec<constructor_elt, va_gc> *init;
- vec_alloc (init, vals.size ());
+ vec_alloc (init, union_index != -1 ? 1 : vals.size ());
tree sink = NULL_TREE;
bool is_constant = true;
@@ -1299,8 +1313,8 @@ constructor_expression (tree type_tree, bool is_variant,
gcc_assert (field != NULL_TREE);
field = DECL_CHAIN (field);
}
- if (TREE_TYPE (field) == error_mark_node || val == error_mark_node
- || TREE_TYPE (val) == error_mark_node)
+
+ if (TREE_TYPE (field) == error_mark_node || error_operand_p (val))
return error_mark_node;
if (int_size_in_bytes (TREE_TYPE (field)) == 0)
@@ -1330,8 +1344,7 @@ constructor_expression (tree type_tree, bool is_variant,
{
gcc_assert (field != NULL_TREE);
tree val = (*p);
- if (TREE_TYPE (field) == error_mark_node || val == error_mark_node
- || TREE_TYPE (val) == error_mark_node)
+ if (TREE_TYPE (field) == error_mark_node || error_operand_p (val))
return error_mark_node;
if (int_size_in_bytes (TREE_TYPE (field)) == 0)
@@ -1370,7 +1383,7 @@ array_constructor_expression (tree type_tree,
const std::vector<tree> &vals,
location_t location)
{
- if (type_tree == error_mark_node)
+ if (error_operand_p (type_tree))
return error_mark_node;
gcc_assert (indexes.size () == vals.size ());
@@ -1387,7 +1400,7 @@ array_constructor_expression (tree type_tree,
tree index = size_int (indexes[i]);
tree val = vals[i];
- if (index == error_mark_node || val == error_mark_node)
+ if (error_operand_p (index) || error_operand_p (val))
return error_mark_node;
if (element_size == 0)
@@ -1491,8 +1504,7 @@ array_initializer (tree fndecl, tree block, tree array_type, tree length,
tree
array_index_expression (tree array_tree, tree index_tree, location_t location)
{
- if (array_tree == error_mark_node || TREE_TYPE (array_tree) == error_mark_node
- || index_tree == error_mark_node)
+ if (error_operand_p (array_tree) || error_operand_p (index_tree))
return error_mark_node;
// A function call that returns a zero sized object will have been
@@ -1509,12 +1521,40 @@ 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,
location_t location)
{
- if (fn == error_mark_node || TREE_TYPE (fn) == error_mark_node)
+ if (error_operand_p (fn))
return error_mark_node;
gcc_assert (FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn)));
@@ -1594,7 +1634,7 @@ tree
init_statement (tree, Bvariable *var, tree init_tree)
{
tree var_tree = var->get_decl ();
- if (var_tree == error_mark_node || init_tree == error_mark_node)
+ if (error_operand_p (var_tree) || error_operand_p (init_tree))
return error_mark_node;
gcc_assert (TREE_CODE (var_tree) == VAR_DECL);
@@ -1625,7 +1665,7 @@ init_statement (tree, Bvariable *var, tree init_tree)
tree
assignment_statement (tree lhs, tree rhs, location_t location)
{
- if (lhs == error_mark_node || rhs == error_mark_node)
+ if (error_operand_p (lhs) || error_operand_p (rhs))
return error_mark_node;
// To avoid problems with GNU ld, we don't make zero-sized
@@ -1650,14 +1690,14 @@ assignment_statement (tree lhs, tree rhs, location_t location)
tree
return_statement (tree fntree, tree val, location_t location)
{
- if (fntree == error_mark_node)
+ if (error_operand_p (fntree))
return error_mark_node;
tree result = DECL_RESULT (fntree);
- if (result == error_mark_node)
+ if (error_operand_p (result))
return error_mark_node;
- if (val == error_mark_node)
+ if (error_operand_p (val))
return error_mark_node;
tree set
@@ -1675,8 +1715,8 @@ tree
exception_handler_statement (tree try_stmt, tree except_stmt, tree finally_stmt,
location_t location)
{
- if (try_stmt == error_mark_node || except_stmt == error_mark_node
- || finally_stmt == error_mark_node)
+ if (error_operand_p (try_stmt) || error_operand_p (except_stmt)
+ || error_operand_p (finally_stmt))
return error_mark_node;
if (except_stmt != NULL_TREE)
@@ -1695,8 +1735,8 @@ tree
if_statement (tree, tree cond_tree, tree then_tree, tree else_tree,
location_t location)
{
- if (cond_tree == error_mark_node || then_tree == error_mark_node
- || else_tree == error_mark_node)
+ if (error_operand_p (cond_tree) || error_operand_p (then_tree)
+ || error_operand_p (else_tree))
return error_mark_node;
tree ret = build3_loc (location, COND_EXPR, void_type_node, cond_tree,
then_tree, else_tree);
@@ -1722,15 +1762,12 @@ exit_expression (tree cond_tree, location_t locus)
tree
compound_statement (tree s1, tree s2)
{
- tree stmt_list = NULL_TREE;
- tree t = s1;
- if (t == error_mark_node)
- return error_mark_node;
- append_to_statement_list (t, &stmt_list);
- t = s2;
- if (t == error_mark_node)
+ if (error_operand_p (s1) || error_operand_p (s2))
return error_mark_node;
- append_to_statement_list (t, &stmt_list);
+
+ tree stmt_list = NULL_TREE;
+ append_to_statement_list (s1, &stmt_list);
+ append_to_statement_list (s2, &stmt_list);
// If neither statement has any side effects, stmt_list can be NULL
// at this point.
@@ -1746,11 +1783,9 @@ tree
statement_list (const std::vector<tree> &statements)
{
tree stmt_list = NULL_TREE;
- for (std::vector<tree>::const_iterator p = statements.begin ();
- p != statements.end (); ++p)
+ for (tree t : statements)
{
- tree t = (*p);
- if (t == error_mark_node)
+ if (error_operand_p (t))
return error_mark_node;
append_to_statement_list (t, &stmt_list);
}
@@ -1802,12 +1837,13 @@ block (tree fndecl, tree enclosing, const std::vector<Bvariable *> &vars,
*pp = block_tree;
}
+ // Chain the variables of the scope together so they are all connected
+ // to the block.
tree *pp = &BLOCK_VARS (block_tree);
- for (std::vector<Bvariable *>::const_iterator pv = vars.begin ();
- pv != vars.end (); ++pv)
+ for (Bvariable *bv : vars)
{
- *pp = (*pv)->get_decl ();
- if (*pp != error_mark_node)
+ *pp = bv->get_decl ();
+ if (!error_operand_p (*pp))
pp = &DECL_CHAIN (*pp);
}
*pp = NULL_TREE;
@@ -1826,11 +1862,9 @@ void
block_add_statements (tree bind_tree, const std::vector<tree> &statements)
{
tree stmt_list = NULL_TREE;
- for (std::vector<tree>::const_iterator p = statements.begin ();
- p != statements.end (); ++p)
+ for (tree s : statements)
{
- tree s = (*p);
- if (s != error_mark_node)
+ if (!error_operand_p (s))
append_to_statement_list (s, &stmt_list);
}
@@ -1886,7 +1920,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);
}
@@ -1908,8 +1943,7 @@ convert_tree (tree type_tree, tree expr_tree, location_t location)
if (type_tree == TREE_TYPE (expr_tree))
return expr_tree;
- if (type_tree == error_mark_node || expr_tree == error_mark_node
- || TREE_TYPE (expr_tree) == error_mark_node)
+ if (error_operand_p (type_tree) || error_operand_p (expr_tree))
return error_mark_node;
if (POINTER_TYPE_P (type_tree) || INTEGRAL_TYPE_P (type_tree)
@@ -1934,11 +1968,11 @@ 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 (type_tree == error_mark_node)
+ if (error_operand_p (type_tree))
return Bvariable::error_variable ();
// The GNU linker does not like dynamic variables with zero size.
@@ -1946,8 +1980,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
@@ -1955,11 +1988,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;
@@ -1977,11 +2010,11 @@ global_variable (const std::string &var_name, const std::string &asm_name,
void
global_variable_set_init (Bvariable *var, tree expr_tree)
{
- if (expr_tree == error_mark_node)
+ if (error_operand_p (expr_tree))
return;
gcc_assert (TREE_CONSTANT (expr_tree));
tree var_decl = var->get_decl ();
- if (var_decl == error_mark_node)
+ if (error_operand_p (var_decl))
return;
DECL_INITIAL (var_decl) = expr_tree;
@@ -1998,14 +2031,13 @@ 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,
+LocalVariable
+local_variable (tree function, GGC::Ident name, tree type_tree,
Bvariable *decl_var, location_t location)
{
- if (type_tree == error_mark_node)
- return Bvariable::error_variable ();
- tree decl = build_decl (location, VAR_DECL, get_identifier_from_string (name),
- type_tree);
+ if (error_operand_p (type_tree))
+ return LocalVariable::error_variable ();
+ tree decl = build_decl (location, VAR_DECL, name.as_tree (), type_tree);
DECL_CONTEXT (decl) = function;
if (decl_var != NULL)
@@ -2014,36 +2046,34 @@ local_variable (tree function, const std::string &name, tree type_tree,
SET_DECL_VALUE_EXPR (decl, decl_var->get_decl ());
}
rust_preserve_from_gc (decl);
- return new Bvariable (decl);
+ return LocalVariable (decl);
}
// Make a function parameter variable.
-Bvariable *
-parameter_variable (tree function, const std::string &name, tree type_tree,
+LocalVariable
+parameter_variable (tree function, GGC::Ident name, tree type_tree,
location_t location)
{
- if (type_tree == error_mark_node)
- return Bvariable::error_variable ();
- tree decl = build_decl (location, PARM_DECL,
- get_identifier_from_string (name), type_tree);
+ if (error_operand_p (type_tree))
+ return LocalVariable::error_variable ();
+ tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree);
DECL_CONTEXT (decl) = function;
DECL_ARG_TYPE (decl) = type_tree;
rust_preserve_from_gc (decl);
- return new Bvariable (decl);
+ return LocalVariable (decl);
}
// Make a static chain variable.
-Bvariable *
-static_chain_variable (tree fndecl, const std::string &name, tree type_tree,
+LocalVariable
+static_chain_variable (tree fndecl, GGC::Ident name, tree type_tree,
location_t location)
{
- if (type_tree == error_mark_node)
- return Bvariable::error_variable ();
- tree decl = build_decl (location, PARM_DECL,
- get_identifier_from_string (name), type_tree);
+ if (error_operand_p (type_tree))
+ return LocalVariable::error_variable ();
+ 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;
@@ -2063,22 +2093,22 @@ static_chain_variable (tree fndecl, const std::string &name, tree type_tree,
DECL_STATIC_CHAIN (fndecl) = 1;
rust_preserve_from_gc (decl);
- return new Bvariable (decl);
+ return LocalVariable (decl);
}
// Make a temporary variable.
-Bvariable *
+LocalVariable
temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree init_tree,
bool is_address_taken, location_t location,
tree *pstatement)
{
gcc_assert (fndecl != NULL_TREE);
- if (type_tree == error_mark_node || init_tree == error_mark_node
- || fndecl == error_mark_node)
+ if (error_operand_p (type_tree) || error_operand_p (init_tree)
+ || error_operand_p (fndecl))
{
*pstatement = error_mark_node;
- return Bvariable::error_variable ();
+ return LocalVariable::error_variable ();
}
tree var;
@@ -2128,16 +2158,16 @@ temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree init_tree,
|| TREE_TYPE (init_tree) == void_type_node))
*pstatement = compound_statement (init_tree, *pstatement);
- return new Bvariable (var);
+ return LocalVariable (var);
}
// 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);
@@ -2150,7 +2180,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;
}
@@ -2189,21 +2219,21 @@ 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 (functype != error_mark_node)
- {
- gcc_assert (FUNCTION_POINTER_TYPE_P (functype));
- functype = TREE_TYPE (functype);
- }
- tree id = get_identifier_from_string (name);
- if (functype == error_mark_node || id == error_mark_node)
+ if (error_operand_p (functype))
+ return error_mark_node;
+
+ gcc_assert (FUNCTION_POINTER_TYPE_P (functype));
+ functype = TREE_TYPE (functype);
+ tree id = name.as_tree ();
+ if (error_operand_p (id))
return error_mark_node;
tree decl = build_decl (location, FUNCTION_DECL, id, functype);
- if (!asm_name.empty ())
- SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
+ if (asm_name.has_value ())
+ SET_DECL_ASSEMBLER_NAME (decl, asm_name->as_tree ());
if ((flags & function_is_declaration) != 0)
DECL_EXTERNAL (decl) = 1;
@@ -2236,8 +2266,8 @@ tree
function_defer_statement (tree function, tree undefer_tree, tree defer_tree,
location_t location)
{
- if (undefer_tree == error_mark_node || defer_tree == error_mark_node
- || function == error_mark_node)
+ if (error_operand_p (undefer_tree) || error_operand_p (defer_tree)
+ || error_operand_p (function))
return error_mark_node;
if (DECL_STRUCT_FUNCTION (function) == NULL)
@@ -2246,7 +2276,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);
@@ -2269,16 +2299,15 @@ bool
function_set_parameters (tree function,
const std::vector<Bvariable *> &param_vars)
{
- if (function == error_mark_node)
+ if (error_operand_p (function))
return false;
tree params = NULL_TREE;
tree *pp = &params;
- for (std::vector<Bvariable *>::const_iterator pv = param_vars.begin ();
- pv != param_vars.end (); ++pv)
+ for (Bvariable *bv : param_vars)
{
- *pp = (*pv)->get_decl ();
- gcc_assert (*pp != error_mark_node);
+ *pp = bv->get_decl ();
+ gcc_assert (!error_operand_p (*pp));
pp = &DECL_CHAIN (*pp);
}
*pp = NULL_TREE;
@@ -2303,23 +2332,19 @@ write_global_definitions (const std::vector<tree> &type_decls,
// Convert all non-erroneous declarations into Gimple form.
size_t i = 0;
- for (std::vector<Bvariable *>::const_iterator p = variable_decls.begin ();
- p != variable_decls.end (); ++p)
+ for (Bvariable *bv : variable_decls)
{
- tree v = (*p)->get_decl ();
- if (v != error_mark_node)
- {
- defs[i] = v;
- rust_preserve_from_gc (defs[i]);
- ++i;
- }
+ tree v = bv->get_decl ();
+ if (error_operand_p (v))
+ continue;
+ defs[i] = v;
+ rust_preserve_from_gc (defs[i]);
+ ++i;
}
- for (std::vector<tree>::const_iterator p = type_decls.begin ();
- p != type_decls.end (); ++p)
+ for (tree type_tree : type_decls)
{
- tree type_tree = (*p);
- if (type_tree != error_mark_node && IS_TYPE_OR_DECL_P (type_tree))
+ if (!error_operand_p (type_tree) && IS_TYPE_OR_DECL_P (type_tree))
{
defs[i] = TYPE_NAME (type_tree);
gcc_assert (defs[i] != NULL);
@@ -2327,21 +2352,18 @@ write_global_definitions (const std::vector<tree> &type_decls,
++i;
}
}
- for (std::vector<tree>::const_iterator p = constant_decls.begin ();
- p != constant_decls.end (); ++p)
+ for (tree t : constant_decls)
{
- if ((*p) != error_mark_node)
+ if (!error_operand_p (t))
{
- defs[i] = (*p);
+ defs[i] = t;
rust_preserve_from_gc (defs[i]);
++i;
}
}
- for (std::vector<tree>::const_iterator p = function_decls.begin ();
- p != function_decls.end (); ++p)
+ for (tree decl : function_decls)
{
- tree decl = (*p);
- if (decl != error_mark_node)
+ if (!error_operand_p (decl))
{
rust_preserve_from_gc (decl);
if (DECL_STRUCT_FUNCTION (decl) == NULL)
@@ -2361,4 +2383,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-gcc.h b/gcc/rust/rust-gcc.h
index b3f0325..1ff7c5b 100644
--- a/gcc/rust/rust-gcc.h
+++ b/gcc/rust/rust-gcc.h
@@ -59,4 +59,28 @@ private:
tree orig_type_;
};
+// like Bvariable, but orig_type_ == nullptr always holds
+// could be any variable which isn't a zero-sized global
+class LocalVariable
+{
+public:
+ LocalVariable (tree t) : t (t) {}
+
+ // Get the tree for use as an expression.
+ tree get_tree (location_t) const;
+
+ // Get the actual decl;
+ tree get_decl () const { return t; }
+
+ // Create an error variable. This is used for cases which should
+ // not occur in a correct program, in order to keep the compilation
+ // going without crashing.
+ static LocalVariable error_variable ();
+
+ operator Bvariable * () const { return new Bvariable (t); }
+
+private:
+ tree t;
+};
+
#endif // RUST_GCC
diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc
index f3a155d..1088845 100644
--- a/gcc/rust/rust-lang.cc
+++ b/gcc/rust/rust-lang.cc
@@ -34,7 +34,6 @@
#include "selftest.h"
#include "rust-cfg-parser.h"
#include "rust-privacy-ctx.h"
-#include "rust-ast-resolve-item.h"
#include "rust-lex.h"
#include "optional.h"
#include "rust-unicode.h"
@@ -51,10 +50,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 +372,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 +399,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 +421,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
@@ -437,7 +441,6 @@ run_rust_tests ()
rust_cfg_parser_test ();
rust_privacy_ctx_test ();
rust_crate_name_validation_test ();
- rust_simple_path_resolve_test ();
}
} // namespace selftest
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 15f21ef..6418118 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -20,14 +20,15 @@
#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"
#include "rust-lex.h"
#include "rust-parse.h"
#include "rust-macro-expand.h"
-#include "rust-ast-resolve.h"
#include "rust-ast-lower.h"
#include "rust-hir-type-check.h"
#include "rust-privacy-check.h"
@@ -44,10 +45,10 @@
#include "rust-imports.h"
#include "rust-extern-crate.h"
#include "rust-attributes.h"
-#include "rust-early-name-resolver.h"
#include "rust-name-resolution-context.h"
#include "rust-early-name-resolver-2.0.h"
#include "rust-late-name-resolver-2.0.h"
+#include "rust-resolve-builtins.h"
#include "rust-cfg-strip.h"
#include "rust-expand-visitor.h"
#include "rust-unicode.h"
@@ -61,11 +62,9 @@
#include "tm.h"
#include "rust-target.h"
-extern bool
-saw_errors (void);
+extern bool saw_errors (void);
-extern Linemap *
-rust_get_linemap ();
+extern Linemap *rust_get_linemap ();
namespace Rust {
@@ -150,9 +149,9 @@ validate_crate_name (const std::string &crate_name, Error &error)
{
if (!(is_alphabetic (c.value) || is_numeric (c.value) || c.value == '_'))
{
- error = Error (UNDEF_LOCATION,
- "invalid character %qs in crate name: %qs",
- c.as_string ().c_str (), crate_name.c_str ());
+ error
+ = Error (UNDEF_LOCATION, "invalid character %qs in crate name: %qs",
+ c.as_string ().c_str (), crate_name.c_str ());
return false;
}
}
@@ -203,14 +202,16 @@ Session::handle_option (
switch (code)
{
case OPT_I:
- case OPT_L: {
+ case OPT_L:
+ {
// TODO: add search path
const std::string p = std::string (arg);
add_search_path (p);
}
break;
- case OPT_frust_extern_: {
+ case OPT_frust_extern_:
+ {
std::string input (arg);
ret = handle_extern_option (input);
}
@@ -251,7 +252,8 @@ Session::handle_option (
Compile::Mangler::set_mangling (flag_rust_mangling);
break;
- case OPT_frust_cfg_: {
+ case OPT_frust_cfg_:
+ {
auto string_arg = std::string (arg);
ret = handle_cfg_option (string_arg);
break;
@@ -419,32 +421,31 @@ Session::handle_crate_name (const char *filename,
{
if (attr.get_path () != "crate_name")
continue;
- if (!attr.has_attr_input ())
+
+ auto msg_str = Analysis::Attributes::extract_string_literal (attr);
+ if (!msg_str.has_value ())
{
rust_error_at (attr.get_locus (),
- "%<crate_name%> accepts one argument");
+ "malformed %<crate_name%> attribute input");
continue;
}
- auto &literal
- = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
- const auto &msg_str = literal.get_literal ().as_string ();
- if (!validate_crate_name (msg_str, error))
+ if (!validate_crate_name (*msg_str, error))
{
error.locus = attr.get_locus ();
error.emit ();
continue;
}
- if (options.crate_name_set_manually && (options.crate_name != msg_str))
+ if (options.crate_name_set_manually && (options.crate_name != *msg_str))
{
rust_error_at (attr.get_locus (),
"%<-frust-crate-name%> and %<#[crate_name]%> are "
"required to match, but %qs does not match %qs",
- options.crate_name.c_str (), msg_str.c_str ());
+ options.crate_name.c_str (), msg_str->c_str ());
}
crate_name_found = true;
- options.set_crate_name (msg_str);
+ options.set_crate_name (*msg_str);
}
options.crate_name_set_manually |= crate_name_found;
@@ -548,10 +549,6 @@ Session::compile_crate (const char *filename)
handle_crate_name (filename, *ast_crate.get ());
// dump options except lexer dump
- if (options.dump_option_enabled (CompileOptions::AST_DUMP_PRETTY))
- {
- dump_ast_pretty (*ast_crate.get ());
- }
if (options.dump_option_enabled (CompileOptions::TARGET_OPTION_DUMP))
{
options.target_data.dump_target_options ();
@@ -560,6 +557,11 @@ Session::compile_crate (const char *filename)
if (saw_errors ())
return;
+ if (options.dump_option_enabled (CompileOptions::AST_DUMP_PRETTY))
+ {
+ dump_ast_pretty (*ast_crate.get ());
+ }
+
// setup the mappings for this AST
CrateNum current_crate = mappings.get_current_crate ();
AST::Crate &parsed_crate
@@ -610,15 +612,12 @@ Session::compile_crate (const char *filename)
if (last_step == CompileOptions::CompileStep::Expansion)
return;
- AST::CollectLangItems ().go (parsed_crate);
- AST::DesugarQuestionMark ().go (parsed_crate);
-
auto name_resolution_ctx = Resolver2_0::NameResolutionContext ();
// expansion pipeline stage
expansion (parsed_crate, name_resolution_ctx);
- AST::DesugarForLoops ().go (parsed_crate);
+ AST::CollectLangItems ().go (parsed_crate);
rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m");
if (options.dump_option_enabled (CompileOptions::EXPANSION_DUMP))
@@ -644,10 +643,7 @@ Session::compile_crate (const char *filename)
return;
// resolution pipeline stage
- if (flag_name_resolution_2_0)
- Resolver2_0::Late (name_resolution_ctx).go (parsed_crate);
- else
- Resolver::NameResolution::Resolve (parsed_crate);
+ Resolver2_0::Late (name_resolution_ctx).go (parsed_crate);
if (options.dump_option_enabled (CompileOptions::RESOLUTION_DUMP))
dump_name_resolution (name_resolution_ctx);
@@ -682,6 +678,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 +726,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);
+ HIR::ReadonlyChecker ().go (hir);
// metadata
bool specified_emit_metadata
@@ -758,8 +754,11 @@ Session::compile_crate (const char *filename)
}
}
+ if (saw_errors ())
+ return;
+
// pass to GCC middle-end
- ctx.write_to_backend ();
+ ctx->write_to_backend ();
}
void
@@ -937,28 +936,23 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx)
MacroExpander expander (crate, cfg, *this);
std::vector<Error> macro_errors;
+ Resolver2_0::Builtins::setup_lang_prelude (ctx);
+
while (!fixed_point_reached && iterations < cfg.recursion_limit)
{
- CfgStrip ().go (crate);
+ CfgStrip (cfg).go (crate);
// Errors might happen during cfg strip pass
- bool visitor_dirty = false;
- if (flag_name_resolution_2_0)
- {
- Resolver2_0::Early early (ctx);
- early.go (crate);
- macro_errors = early.get_macro_resolve_errors ();
- visitor_dirty = early.is_dirty ();
- }
- else
- Resolver::EarlyNameResolver ().go (crate);
+ Resolver2_0::Early early (ctx);
+ early.go (crate);
+ macro_errors = early.get_macro_resolve_errors ();
if (saw_errors ())
break;
ExpandVisitor (expander).go (crate);
- fixed_point_reached = !expander.has_changed () && !visitor_dirty;
+ fixed_point_reached = !expander.has_changed () && !early.is_dirty ();
expander.reset_changed_state ();
iterations++;
@@ -983,6 +977,19 @@ 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
+ Resolver2_0::TopLevel (ctx).go (crate);
+ }
+
// error reporting - check unused macros, get missing fragment specifiers
// build test harness
@@ -1108,8 +1115,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,17 +1183,6 @@ 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);
-
// 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..8cc2b7b 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);
@@ -427,8 +425,7 @@ AutoderefCycle::try_autoderefed (TyTy::BaseType *r)
TyTy::ReferenceType *r1
= new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
Mutability::Imm);
- adjustments.push_back (
- Adjustment (Adjustment::AdjustmentType::IMM_REF, r, r1));
+ adjustments.emplace_back (Adjustment::AdjustmentType::IMM_REF, r, r1);
if (select (*r1))
return true;
@@ -438,8 +435,7 @@ AutoderefCycle::try_autoderefed (TyTy::BaseType *r)
TyTy::ReferenceType *r2
= new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
Mutability::Mut);
- adjustments.push_back (
- Adjustment (Adjustment::AdjustmentType::MUT_REF, r, r2));
+ adjustments.emplace_back (Adjustment::AdjustmentType::MUT_REF, r, r2);
if (select (*r2))
return true;
diff --git a/gcc/rust/typecheck/rust-casts.cc b/gcc/rust/typecheck/rust-casts.cc
index 90bdef1..7d08601 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 ());
@@ -267,16 +277,19 @@ TypeCastRules::cast_rules ()
break;
case TyTy::TypeKind::REF:
+ case TyTy::TypeKind::FNPTR:
case TyTy::TypeKind::POINTER:
switch (to.get_ty ()->get_kind ())
{
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;
+ auto kind = from.get_ty ()->get_kind ();
+ bool from_ptr = kind == TyTy::TypeKind::POINTER
+ || kind == TyTy::TypeKind::FNPTR;
if (from_ptr)
{
return TypeCoercionRules::CoercionResult{
@@ -320,7 +333,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 +370,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..e027d9c 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -61,60 +61,21 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
// see:
// https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs
- // handle never
- // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L155
if (receiver->get_kind () == TyTy::TypeKind::NEVER)
{
- // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
- // type variable, we want `?T` to fallback to `!` if not
- // otherwise constrained. An example where this arises:
- //
- // let _: Option<?T> = Some({ return; });
- //
- // here, we would coerce from `!` to `?T`.
- if (expected->has_substitutions_defined () && !expected->is_concrete ())
- {
- location_t locus = mappings.lookup_location (receiver->get_ref ());
- TyTy::TyVar implicit_var
- = TyTy::TyVar::get_implicit_infer_var (locus);
- try_result = CoercionResult{{}, implicit_var.get_tyty ()};
- return true;
- }
- else
- {
- bool expected_is_infer_var
- = expected->get_kind () == TyTy::TypeKind::INFER;
- bool expected_is_general_infer_var
- = expected_is_infer_var
- && (static_cast<TyTy::InferType *> (expected)->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::GENERAL);
-
- // FIXME this 'expected_is_general_infer_var' case needs to eventually
- // should go away see: compile/never_type_err1.rs
- //
- // I think we need inference obligations to say that yes we have a
- // general inference variable but we add the oligation to the expected
- // type that it could default to '!'
- if (expected_is_general_infer_var)
- try_result = CoercionResult{{}, receiver};
- else
- try_result = CoercionResult{{}, expected->clone ()};
-
- return true;
- }
+ try_result = coerce_never (receiver);
+ return true;
}
// unsize
- bool unsafe_error = false;
- CoercionResult unsize_coercion
- = coerce_unsized (receiver, expected, unsafe_error);
- bool valid_unsize_coercion = !unsize_coercion.is_error ();
- if (valid_unsize_coercion)
+ tl::expected<CoercionResult, CoerceUnsizedError> unsize_coercion
+ = coerce_unsized (receiver, expected);
+ if (unsize_coercion)
{
- try_result = unsize_coercion;
+ try_result = unsize_coercion.value ();
return true;
}
- else if (unsafe_error)
+ else if (unsize_coercion.error () == CoerceUnsizedError::Unsafe)
{
// location_t lhs = mappings.lookup_location (receiver->get_ref ());
// location_t rhs = mappings.lookup_location (expected->get_ref ());
@@ -125,15 +86,16 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
// pointers
switch (expected->get_kind ())
{
- case TyTy::TypeKind::POINTER: {
- TyTy::PointerType *ptr = static_cast<TyTy::PointerType *> (expected);
+ case TyTy::TypeKind::POINTER:
+ {
+ auto *ptr = expected->as<TyTy::PointerType> ();
try_result = coerce_unsafe_ptr (receiver, ptr, ptr->mutability ());
return !try_result.is_error ();
}
- case TyTy::TypeKind::REF: {
- TyTy::ReferenceType *ptr
- = static_cast<TyTy::ReferenceType *> (expected);
+ case TyTy::TypeKind::REF:
+ {
+ auto *ptr = expected->as<TyTy::ReferenceType> ();
try_result
= coerce_borrowed_pointer (receiver, ptr, ptr->mutability ());
return !try_result.is_error ();
@@ -147,7 +109,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 ());
@@ -171,6 +134,44 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
}
TypeCoercionRules::CoercionResult
+TypeCoercionRules::coerce_never (TyTy::BaseType *receiver)
+{
+ // handle never
+ // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L155
+
+ // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
+ // type variable, we want `?T` to fallback to `!` if not
+ // otherwise constrained. An example where this arises:
+ //
+ // let _: Option<?T> = Some({ return; });
+ //
+ // here, we would coerce from `!` to `?T`.
+ if (expected->has_substitutions_defined () && !expected->is_concrete ())
+ {
+ location_t locus = mappings.lookup_location (receiver->get_ref ());
+ TyTy::TyVar implicit_var = TyTy::TyVar::get_implicit_infer_var (locus);
+ return CoercionResult{{}, implicit_var.get_tyty ()};
+ }
+
+ bool expected_is_infer_var = expected->get_kind () == TyTy::TypeKind::INFER;
+ bool expected_is_general_infer_var
+ = expected_is_infer_var
+ && (static_cast<TyTy::InferType *> (expected)->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::GENERAL);
+
+ // FIXME this 'expected_is_general_infer_var' case needs to eventually
+ // should go away see: compile/never_type_err1.rs
+ //
+ // I think we need inference obligations to say that yes we have a
+ // general inference variable but we add the oligation to the expected
+ // type that it could default to '!'
+ if (expected_is_general_infer_var)
+ return CoercionResult{{}, receiver};
+ else
+ return CoercionResult{{}, expected->clone ()};
+}
+
+TypeCoercionRules::CoercionResult
TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver,
TyTy::PointerType *expected,
Mutability to_mutbl)
@@ -182,7 +183,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 +192,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 +269,13 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver,
Mutability from_mutbl = Mutability::Imm;
switch (receiver->get_kind ())
{
- case TyTy::TypeKind::REF: {
- TyTy::ReferenceType *from
- = static_cast<TyTy::ReferenceType *> (receiver);
- from_mutbl = from->mutability ();
+ case TyTy::TypeKind::REF:
+ {
+ from_mutbl = receiver->as<TyTy::ReferenceType> ()->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 (),
@@ -312,9 +313,10 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver,
// &[T; n] or &mut [T; n] -> &[T]
// or &mut [T; n] -> &mut [T]
// or &Concrete -> &Trait, etc.
-TypeCoercionRules::CoercionResult
+tl::expected<TypeCoercionRules::CoercionResult,
+ TypeCoercionRules::CoerceUnsizedError>
TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
- TyTy::BaseType *target, bool &unsafe_error)
+ TyTy::BaseType *target)
{
rust_debug ("coerce_unsized(source={%s}, target={%s})",
source->debug_str ().c_str (), target->debug_str ().c_str ());
@@ -338,11 +340,11 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
Mutability to_mutbl = target_ref->mutability ();
if (!coerceable_mutability (from_mutbl, to_mutbl))
{
- unsafe_error = true;
location_t lhs = mappings.lookup_location (source->get_ref ());
location_t rhs = mappings.lookup_location (target->get_ref ());
mismatched_mutability_error (locus, lhs, rhs);
- return TypeCoercionRules::CoercionResult::get_error ();
+ return tl::unexpected<CoerceUnsizedError> (
+ CoerceUnsizedError::Unsafe);
}
ty_a = source_ref->get_base ();
@@ -350,8 +352,8 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
needs_reborrow = true;
expected_mutability = to_mutbl;
- adjustments.push_back (
- Adjustment (Adjustment::AdjustmentType::INDIRECTION, source_ref, ty_a));
+ adjustments.emplace_back (Adjustment::AdjustmentType::INDIRECTION,
+ source_ref, ty_a);
}
else if (source_is_ref && target_is_ptr)
{
@@ -363,11 +365,11 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
Mutability to_mutbl = target_ref->mutability ();
if (!coerceable_mutability (from_mutbl, to_mutbl))
{
- unsafe_error = true;
location_t lhs = mappings.lookup_location (source->get_ref ());
location_t rhs = mappings.lookup_location (target->get_ref ());
mismatched_mutability_error (locus, lhs, rhs);
- return TypeCoercionRules::CoercionResult::get_error ();
+ return tl::unexpected<CoerceUnsizedError> (
+ CoerceUnsizedError::Unsafe);
}
ty_a = source_ref->get_base ();
@@ -375,8 +377,8 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
needs_reborrow = true;
expected_mutability = to_mutbl;
- adjustments.push_back (
- Adjustment (Adjustment::AdjustmentType::INDIRECTION, source_ref, ty_a));
+ adjustments.emplace_back (Adjustment::AdjustmentType::INDIRECTION,
+ source_ref, ty_a);
}
// FIXME
@@ -393,19 +395,16 @@ 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;
- return TypeCoercionRules::CoercionResult::get_error ();
- }
+ return tl::unexpected<CoerceUnsizedError> (CoerceUnsizedError::Unsafe);
// return the unsize coercion
TyTy::BaseType *result = b->clone ();
// result->set_ref (a->get_ref ());
// append a dyn coercion adjustment
- adjustments.push_back (Adjustment (Adjustment::UNSIZE, a, result));
+ adjustments.emplace_back (Adjustment::UNSIZE, a, result);
// reborrow if needed
if (needs_reborrow)
@@ -418,7 +417,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
Adjustment::AdjustmentType borrow_type
= expected_mutability == Mutability::Imm ? Adjustment::IMM_REF
: Adjustment::MUT_REF;
- adjustments.push_back (Adjustment (borrow_type, result, reborrow));
+ adjustments.emplace_back (borrow_type, result, reborrow);
result = reborrow;
}
@@ -426,7 +425,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
}
adjustments.clear ();
- return TypeCoercionRules::CoercionResult::get_error ();
+ return tl::unexpected<CoerceUnsizedError> (CoerceUnsizedError::Regular);
}
bool
@@ -440,7 +439,8 @@ TypeCoercionRules::select (TyTy::BaseType &autoderefed)
= unify_site_and (autoderefed.get_ref (), TyTy::TyWithLocation (expected),
TyTy::TyWithLocation (&autoderefed),
UNDEF_LOCATION /* locus */, false /*emit_errors*/,
- false /*commit_if_ok*/, true /*infer*/, true /*cleanup*/);
+ !try_flag /*commit_if_ok*/, try_flag /*infer*/,
+ try_flag /*cleanup*/);
bool ok = result->get_kind () != TyTy::TypeKind::ERROR;
if (!ok)
return false;
diff --git a/gcc/rust/typecheck/rust-coercion.h b/gcc/rust/typecheck/rust-coercion.h
index b268966..864f48a 100644
--- a/gcc/rust/typecheck/rust-coercion.h
+++ b/gcc/rust/typecheck/rust-coercion.h
@@ -21,6 +21,7 @@
#include "rust-autoderef.h"
#include "rust-hir-type-check.h"
+#include "expected.h"
namespace Rust {
namespace Resolver {
@@ -28,6 +29,12 @@ namespace Resolver {
class TypeCoercionRules : protected AutoderefCycle
{
public:
+ enum class CoerceUnsizedError
+ {
+ Regular,
+ Unsafe
+ };
+
struct CoercionResult
{
std::vector<Adjustment> adjustments;
@@ -51,6 +58,7 @@ public:
bool allow_autoderef,
bool is_cast_site = false);
+ CoercionResult coerce_never (TyTy::BaseType *receiver);
CoercionResult coerce_unsafe_ptr (TyTy::BaseType *receiver,
TyTy::PointerType *expected,
Mutability mutability);
@@ -59,8 +67,8 @@ public:
TyTy::ReferenceType *expected,
Mutability mutability);
- CoercionResult coerce_unsized (TyTy::BaseType *receiver,
- TyTy::BaseType *expected, bool &unsafe_error);
+ tl::expected<CoercionResult, CoerceUnsizedError>
+ coerce_unsized (TyTy::BaseType *receiver, TyTy::BaseType *expected);
static bool coerceable_mutability (Mutability from_mutbl,
Mutability to_mutbl);
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index c1165e9..296cc44 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -51,6 +51,9 @@ MethodResolver::Select (std::set<MethodCandidate> &candidates,
{
TyTy::BaseType *candidate_type = candidate.candidate.ty;
rust_assert (candidate_type->get_kind () == TyTy::TypeKind::FNDEF);
+ if (candidate_type == nullptr
+ || candidate_type->get_kind () != TyTy::TypeKind::FNDEF)
+ continue;
TyTy::FnType &fn = *static_cast<TyTy::FnType *> (candidate_type);
// match the number of arguments
@@ -102,26 +105,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 ();
@@ -146,11 +139,11 @@ MethodResolver::select (TyTy::BaseType &receiver)
TyTy::BaseType *ty = nullptr;
if (!query_type (func->get_mappings ().get_hirid (), &ty))
return true;
- rust_assert (ty != nullptr);
- if (ty->get_kind () == TyTy::TypeKind::ERROR)
+ if (ty == nullptr || ty->get_kind () == TyTy::TypeKind::ERROR)
+ return true;
+ if (ty->get_kind () != TyTy::TypeKind::FNDEF)
return true;
- rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF);
TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
const TyTy::BaseType *impl_self
= TypeCheckItem::ResolveImplBlockSelf (*impl);
@@ -185,21 +178,24 @@ MethodResolver::select (TyTy::BaseType &receiver)
return true;
}
- inherent_impl_fns.push_back ({func, impl, fnty});
+ inherent_impl_fns.emplace_back (func, impl, fnty);
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 ();
@@ -227,10 +223,11 @@ MethodResolver::select (TyTy::BaseType &receiver)
TyTy::BaseType *ty = nullptr;
if (!query_type (func->get_mappings ().get_hirid (), &ty))
continue;
- if (ty->get_kind () == TyTy::TypeKind::ERROR)
+ if (ty == nullptr || ty->get_kind () == TyTy::TypeKind::ERROR)
+ continue;
+ if (ty->get_kind () != TyTy::TypeKind::FNDEF)
continue;
- rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF);
TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
const TyTy::BaseType *impl_self
= TypeCheckItem::ResolveImplBlockSelf (*impl);
@@ -266,7 +263,7 @@ MethodResolver::select (TyTy::BaseType &receiver)
continue;
}
- inherent_impl_fns.push_back ({func, impl, fnty});
+ impl_candidates.emplace_back (func, impl, fnty);
return true;
}
@@ -289,35 +286,25 @@ MethodResolver::select (TyTy::BaseType &receiver)
return true;
TyTy::BaseType *ty = item_ref->get_tyty ();
- rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF);
+ if (ty == nullptr || ty->get_kind () != TyTy::TypeKind::FNDEF)
+ return true;
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.emplace_back (func, trait, fnty, trait_ref, item_ref);
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)
{
const TyTy::FnType *fn = predicate.fntype;
- rust_assert (fn->is_method ());
+ if (!fn->is_method ())
+ continue;
TyTy::BaseType *fn_self = fn->get_self_type ();
rust_debug ("dot-operator predicate fn_self={%s} can_eq receiver={%s}",
@@ -346,60 +333,34 @@ 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 ());
+ if (!fn->is_method ())
+ continue;
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,15 +379,19 @@ 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 ());
+ if (!fn->is_method ())
+ continue;
TyTy::BaseType *fn_self = fn->get_self_type ();
rust_debug ("dot-operator trait_item fn_self={%s} can_eq receiver={%s}",
@@ -451,10 +416,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,
@@ -463,20 +471,17 @@ MethodResolver::get_predicate_items (
std::vector<predicate_candidate> predicate_items;
for (auto &bound : specified_bounds)
{
- TyTy::TypeBoundPredicateItem lookup
+ tl::optional<TyTy::TypeBoundPredicateItem> lookup
= bound.lookup_associated_item (segment_name.as_string ());
- if (lookup.is_error ())
+ if (!lookup.has_value ())
continue;
- TyTy::BaseType *ty = lookup.get_tyty_for_receiver (&receiver);
+ TyTy::BaseType *ty = lookup->get_tyty_for_receiver (&receiver);
if (ty->get_kind () == TyTy::TypeKind::FNDEF)
{
TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
if (fnty->is_method ())
- {
- predicate_candidate candidate{lookup, fnty};
- predicate_items.push_back (candidate);
- }
+ predicate_items.emplace_back (lookup.value (), fnty);
}
}
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h
index ab95a5a..d2f11d1 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -49,6 +49,10 @@ class MethodResolver : private TypeCheckBase, protected AutoderefCycle
public:
struct predicate_candidate
{
+ predicate_candidate (TyTy::TypeBoundPredicateItem lookup,
+ TyTy::FnType *fntype)
+ : lookup (lookup), fntype (fntype)
+ {}
TyTy::TypeBoundPredicateItem lookup;
TyTy::FnType *fntype;
};
@@ -65,6 +69,34 @@ public:
const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
+ struct impl_item_candidate
+ {
+ impl_item_candidate (HIR::Function *item, HIR::ImplBlock *impl_block,
+ TyTy::FnType *ty)
+ : item (item), impl_block (impl_block), ty (ty)
+ {}
+
+ HIR::Function *item;
+ HIR::ImplBlock *impl_block;
+ TyTy::FnType *ty;
+ };
+
+ struct trait_item_candidate
+ {
+ trait_item_candidate (const HIR::TraitItemFunc *item,
+ const HIR::Trait *trait, TyTy::FnType *ty,
+ const TraitReference *reference,
+ const TraitItemReference *item_ref)
+ : item (item), trait (trait), ty (ty), reference (reference),
+ item_ref (item_ref)
+ {}
+ 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 +109,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..59118e6 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,
@@ -302,11 +302,10 @@ PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item,
if (!query_type (impl_ty_id, &impl_block_ty))
return;
- if (!receiver->can_eq (impl_block_ty, false))
- {
- if (!impl_block_ty->can_eq (receiver, false))
- return;
- }
+ if (!types_compatable (TyTy::TyWithLocation (receiver),
+ TyTy::TyWithLocation (impl_block_ty),
+ impl->get_locus (), false))
+ return;
// lets visit the impl_item
item->accept_vis (*this);
@@ -367,15 +366,15 @@ PathProbeType::process_predicate_for_candidates (
{
const TraitReference *trait_ref = predicate.get ();
- TyTy::TypeBoundPredicateItem item
+ tl::optional<TyTy::TypeBoundPredicateItem> item
= predicate.lookup_associated_item (search.as_string ());
- if (item.is_error ())
+ if (!item.has_value ())
return;
- if (ignore_mandatory_trait_items && item.needs_implementation ())
+ if (ignore_mandatory_trait_items && item->needs_implementation ())
return;
- const TraitItemReference *trait_item_ref = item.get_raw_item ();
+ const TraitItemReference *trait_item_ref = item->get_raw_item ();
PathProbeCandidate::CandidateType candidate_type;
switch (trait_item_ref->get_trait_item_type ())
{
@@ -395,9 +394,9 @@ PathProbeType::process_predicate_for_candidates (
break;
}
- TyTy::BaseType *trait_item_tyty = item.get_raw_item ()->get_tyty ();
+ TyTy::BaseType *trait_item_tyty = item->get_raw_item ()->get_tyty ();
if (receiver->get_kind () != TyTy::DYNAMIC)
- trait_item_tyty = item.get_tyty_for_receiver (receiver);
+ trait_item_tyty = item->get_tyty_for_receiver (receiver);
PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
trait_item_ref,
@@ -425,10 +424,10 @@ PathProbeType::union_bounds (
}
std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_set;
+
for (auto it = mapper.begin (); it != mapper.end (); it++)
- {
- union_set.push_back ({it->second.first, it->second.second});
- }
+ union_set.emplace_back (it->second.first, it->second.second);
+
return union_set;
}
@@ -443,7 +442,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 +450,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 e4a61bd..03121d1 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;
}
@@ -157,7 +142,13 @@ TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
}
auto resolved_item = mappings.lookup_hir_item (hid.value ());
- rust_assert (resolved_item.has_value ());
+ if (!resolved_item.has_value ())
+ {
+ rust_error_at (path.get_locus (),
+ "Failed to resolve trait by looking up hir node");
+ return false;
+ }
+
if (resolved_item.value ()->get_item_kind () != HIR::Item::ItemKind::Trait)
{
rich_location r (line_table, path.get_locus ());
@@ -218,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")
@@ -228,10 +220,11 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
// The one exception is the implicit Self type of a trait
bool apply_sized = !is_self;
auto param_type
- = TypeResolveGenericParam::Resolve (*generic_param, apply_sized);
+ = TypeResolveGenericParam::Resolve (*generic_param, true,
+ apply_sized);
+
context->insert_type (generic_param->get_mappings (), param_type);
- substitutions.push_back (
- TyTy::SubstitutionParamMapping (typaram, param_type));
+ substitutions.emplace_back (typaram, param_type);
if (is_self)
{
@@ -253,17 +246,17 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
// copy the substitition mappings
std::vector<TyTy::SubstitutionParamMapping> self_subst_copy;
+ self_subst_copy.reserve (substitutions.size ());
+
for (auto &sub : substitutions)
self_subst_copy.push_back (sub.clone ());
// They also inherit themselves as a bound this enables a trait item to
// reference other Self::trait_items
- auto self_hrtb
- = TyTy::TypeBoundPredicate (trait_reference->get_mappings ().get_defid (),
- std::move (self_subst_copy),
- BoundPolarity::RegularBound,
- trait_reference->get_locus ());
- specified_bounds.push_back (self_hrtb);
+ specified_bounds.emplace_back (trait_reference->get_mappings ().get_defid (),
+ std::move (self_subst_copy),
+ BoundPolarity::RegularBound,
+ trait_reference->get_locus ());
// look for any
std::vector<TyTy::TypeBoundPredicate> super_traits;
@@ -279,7 +272,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 ();
@@ -296,6 +290,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
{
// make a copy of the substs
std::vector<TyTy::SubstitutionParamMapping> item_subst;
+ item_subst.reserve (substitutions.size ());
+
for (auto &sub : substitutions)
item_subst.push_back (sub.clone ());
@@ -376,7 +372,26 @@ TraitItemReference::resolve_item (HIR::TraitItemType &type)
void
TraitItemReference::resolve_item (HIR::TraitItemConst &constant)
{
- // TODO
+ TyTy::BaseType *ty = nullptr;
+ if (constant.has_type ())
+ ty = TypeCheckType::Resolve (constant.get_type ());
+
+ TyTy::BaseType *expr = nullptr;
+ if (constant.has_expr ())
+ expr = TypeCheckExpr::Resolve (constant.get_expr ());
+
+ bool have_specified_ty = ty != nullptr && !ty->is<TyTy::ErrorType> ();
+ bool have_expr_ty = expr != nullptr && !expr->is<TyTy::ErrorType> ();
+
+ if (have_specified_ty && have_expr_ty)
+ {
+ coercion_site (constant.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (ty,
+ constant.get_type ().get_locus ()),
+ TyTy::TyWithLocation (expr,
+ constant.get_expr ().get_locus ()),
+ constant.get_locus ());
+ }
}
void
@@ -416,11 +431,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 ());
}
@@ -516,15 +547,16 @@ 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);
if (ok && l->get_kind () == TyTy::TypeKind::PARAM)
{
- substitutions.push_back (TyTy::SubstitutionParamMapping (
- static_cast<HIR::TypeParam &> (*generic_param),
- static_cast<TyTy::ParamType *> (l)));
+ substitutions.emplace_back (static_cast<HIR::TypeParam &> (
+ *generic_param),
+ static_cast<TyTy::ParamType *> (l));
}
}
break;
@@ -548,14 +580,13 @@ AssociatedImplTrait::setup_associated_types (
if (p.needs_substitution () && infer)
{
TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
- subst_args.push_back (
- TyTy::SubstitutionArg (&p, infer_var.get_tyty ()));
+ subst_args.emplace_back (&p, infer_var.get_tyty ());
}
else
{
- TyTy::ParamType *param = p.get_param_ty ();
- TyTy::BaseType *resolved = param->destructure ();
- subst_args.push_back (TyTy::SubstitutionArg (&p, resolved));
+ auto param = p.get_param_ty ();
+ auto resolved = param->destructure ();
+ subst_args.emplace_back (&p, resolved);
param_mappings[param->get_symbol ()] = resolved->get_ref ();
}
}
@@ -582,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);
@@ -599,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);
@@ -726,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..392ff20 100644
--- a/gcc/rust/typecheck/rust-hir-type-bounds.h
+++ b/gcc/rust/typecheck/rust-hir-type-bounds.h
@@ -30,21 +30,25 @@ class TypeBoundsProbe : public TypeCheckBase
{
public:
static std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
- Probe (const TyTy::BaseType *receiver);
+ Probe (TyTy::BaseType *receiver);
static bool is_bound_satisfied_for_type (TyTy::BaseType *receiver,
TraitReference *ref);
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);
private:
- TypeBoundsProbe (const TyTy::BaseType *receiver);
+ TypeBoundsProbe (TyTy::BaseType *receiver);
- const TyTy::BaseType *receiver;
+ TyTy::BaseType *receiver;
std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> trait_references;
};
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 34a726c..f878720 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -17,31 +17,48 @@
// <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 (item_kind, item_locus, generic_params,
+ substitutions, is_foreign, abi);
+}
+
static void
walk_types_to_constrain (std::set<HirId> &constrained_symbols,
const TyTy::SubstitutionArgumentMappings &constraints)
{
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_ref ());
constrained_symbols.insert (p->get_ty_ref ());
+
if (p->has_substitutions_defined ())
{
walk_types_to_constrain (constrained_symbols,
@@ -51,12 +68,89 @@ walk_types_to_constrain (std::set<HirId> &constrained_symbols,
}
}
+static void
+walk_type_to_constrain (std::set<HirId> &constrained_symbols, TyTy::BaseType &r)
+{
+ switch (r.get_kind ())
+ {
+ case TyTy::TypeKind::POINTER:
+ {
+ auto &p = static_cast<TyTy::PointerType &> (r);
+ walk_type_to_constrain (constrained_symbols, *p.get_base ());
+ }
+ break;
+ case TyTy::TypeKind::REF:
+ {
+ auto &ref = static_cast<TyTy::ReferenceType &> (r);
+ walk_type_to_constrain (constrained_symbols, *ref.get_base ());
+ }
+ break;
+ case TyTy::TypeKind::ARRAY:
+ {
+ auto &arr = static_cast<TyTy::ArrayType &> (r);
+ walk_type_to_constrain (constrained_symbols, *arr.get_element_type ());
+ }
+ break;
+ case TyTy::TypeKind::FNDEF:
+ {
+ auto &fn = static_cast<TyTy::FnType &> (r);
+ for (auto &param : fn.get_params ())
+ walk_type_to_constrain (constrained_symbols, *param.get_type ());
+ walk_type_to_constrain (constrained_symbols, *fn.get_return_type ());
+ }
+ break;
+ case TyTy::TypeKind::PARAM:
+ {
+ auto &param = static_cast<TyTy::ParamType &> (r);
+ constrained_symbols.insert (param.get_ty_ref ());
+ }
+ break;
+ case TyTy::SLICE:
+ {
+ auto &slice = static_cast<TyTy::SliceType &> (r);
+ walk_type_to_constrain (constrained_symbols,
+ *slice.get_element_type ());
+ }
+ break;
+ case TyTy::FNPTR:
+ {
+ auto &ptr = static_cast<TyTy::FnPtr &> (r);
+ for (auto &param : ptr.get_params ())
+ walk_type_to_constrain (constrained_symbols, *param.get_tyty ());
+ walk_type_to_constrain (constrained_symbols, *ptr.get_return_type ());
+ }
+ break;
+ case TyTy::TUPLE:
+ {
+ auto &tuple = static_cast<TyTy::TupleType &> (r);
+ for (auto &ty : tuple.get_fields ())
+ walk_type_to_constrain (constrained_symbols, *ty.get_tyty ());
+ }
+ break;
+ case TyTy::DYNAMIC:
+ {
+ auto &dyn = static_cast<TyTy::DynamicObjectType &> (r);
+ constrained_symbols.insert (dyn.get_ty_ref ());
+ }
+ break;
+ case TyTy::CLOSURE:
+ {
+ auto &clos = static_cast<TyTy::ClosureType &> (r);
+ walk_type_to_constrain (constrained_symbols, clos.get_parameters ());
+ walk_type_to_constrain (constrained_symbols, *clos.get_return_type ());
+ }
+ break;
+ default:
+ break;
+ }
+}
+
bool
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
@@ -72,21 +166,13 @@ TypeCheckBase::check_for_unconstrained (
HirId ref = p.get_param_ty ()->get_ref ();
symbols_to_constrain.insert (ref);
symbol_to_location.insert ({ref, p.get_param_locus ()});
-
- rust_debug_loc (p.get_param_locus (), "XX constrain THIS");
}
// set up the set of constrained symbols
std::set<HirId> constrained_symbols;
walk_types_to_constrain (constrained_symbols, constraint_a);
walk_types_to_constrain (constrained_symbols, constraint_b);
-
- const auto root = reference->get_root ();
- if (root->get_kind () == TyTy::TypeKind::PARAM)
- {
- const TyTy::ParamType *p = static_cast<const TyTy::ParamType *> (root);
- constrained_symbols.insert (p->get_ty_ref ());
- }
+ walk_type_to_constrain (constrained_symbols, *reference);
// check for unconstrained
bool unconstrained = false;
@@ -114,7 +200,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 ())
@@ -181,7 +268,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 ())
@@ -206,25 +294,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);
@@ -236,7 +328,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. */
@@ -270,10 +363,21 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
crate_num),
UNKNOWN_LOCAL_DEFID);
- TyTy::ArrayType *array
- = new TyTy::ArrayType (array_mapping.get_hirid (), locus,
- *literal_capacity,
- TyTy::TyVar (u8->get_ref ()));
+ auto ctx = Compile::Context::get ();
+ tree capacity = Compile::HIRCompileBase::query_compile_const_expr (
+ ctx, expected_ty, *literal_capacity);
+
+ HirId capacity_expr_id = literal_capacity->get_mappings ().get_hirid ();
+ auto capacity_expr
+ = new TyTy::ConstValueType (capacity, expected_ty, capacity_expr_id,
+ capacity_expr_id);
+ context->insert_type (literal_capacity->get_mappings (),
+ capacity_expr->as_base_type ());
+
+ TyTy::ArrayType *array = new TyTy::ArrayType (
+ array_mapping.get_hirid (), locus,
+ TyTy::TyVar (capacity_expr->as_base_type ()->get_ty_ref ()),
+ TyTy::TyVar (u8->get_ref ()));
context->insert_type (array_mapping, array);
infered = new TyTy::ReferenceType (expr_mappings.get_hirid (),
@@ -298,7 +402,8 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus)
repr.pack = 0;
repr.align = 0;
- // FIXME handle repr types....
+ // Default repr for enums is isize, but we now check for other repr in the
+ // attributes.
bool ok = context->lookup_builtin ("isize", &repr.repr);
rust_assert (ok);
@@ -307,7 +412,7 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus)
bool is_repr = attr.get_path ().as_string () == Values::Attributes::REPR;
if (is_repr && !attr.has_attr_input ())
{
- rust_error_at (attr.get_locus (), "malformed %qs attribute", "repr");
+ rust_error_at (attr.get_locus (), "malformed %<repr%> attribute");
continue;
}
@@ -316,7 +421,11 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus)
const AST::AttrInput &input = attr.get_attr_input ();
bool is_token_tree = input.get_attr_input_type ()
== AST::AttrInput::AttrInputType::TOKEN_TREE;
- rust_assert (is_token_tree);
+ if (!is_token_tree)
+ {
+ rust_error_at (attr.get_locus (), "malformed %<repr%> attribute");
+ continue;
+ }
const auto &option = static_cast<const AST::DelimTokenTree &> (input);
AST::AttrInputMetaItemContainer *meta_items
= option.parse_to_meta_item ();
@@ -343,13 +452,29 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus)
// manually parsing the string "packed(2)" here.
size_t oparen = inline_option.find ('(', 0);
- bool is_pack = false, is_align = false;
+ bool is_pack = false;
+ bool is_align = false;
+ bool is_c = false;
+ bool is_integer = false;
unsigned char value = 1;
if (oparen == std::string::npos)
{
is_pack = inline_option.compare ("packed") == 0;
is_align = inline_option.compare ("align") == 0;
+ is_c = inline_option.compare ("C") == 0;
+ is_integer = (inline_option.compare ("isize") == 0
+ || inline_option.compare ("i8") == 0
+ || inline_option.compare ("i16") == 0
+ || inline_option.compare ("i32") == 0
+ || inline_option.compare ("i64") == 0
+ || inline_option.compare ("i128") == 0
+ || inline_option.compare ("usize") == 0
+ || inline_option.compare ("u8") == 0
+ || inline_option.compare ("u16") == 0
+ || inline_option.compare ("u32") == 0
+ || inline_option.compare ("u64") == 0
+ || inline_option.compare ("u128") == 0);
}
else
@@ -369,9 +494,28 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus)
}
if (is_pack)
- repr.pack = value;
+ {
+ repr.repr_kind = TyTy::ADTType::ReprKind::PACKED;
+ repr.pack = value;
+ }
else if (is_align)
- repr.align = value;
+ {
+ repr.repr_kind = TyTy::ADTType::ReprKind::ALIGN;
+ repr.align = value;
+ }
+ else if (is_c)
+ {
+ repr.repr_kind = TyTy::ADTType::ReprKind::C;
+ }
+ else if (is_integer)
+ {
+ repr.repr_kind = TyTy::ADTType::ReprKind::INT;
+ bool ok = context->lookup_builtin (inline_option, &repr.repr);
+ if (!ok)
+ {
+ rust_error_at (attr.get_locus (), "Invalid repr type");
+ }
+ }
delete meta_items;
@@ -386,32 +530,60 @@ 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)
+ std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
+ ABI abi)
{
for (auto &generic_param : 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 ();
- rust_assert (lifetime.get_lifetime_type ()
- == AST::Lifetime::LifetimeType::NAMED);
context->get_lifetime_resolver ().insert_mapping (
context->intern_lifetime (lifetime));
}
-
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,
+ "foreign items may not have const parameters");
+ }
+
auto &param
= static_cast<HIR::ConstGenericParam &> (*generic_param);
auto specified_type = TypeCheckType::Resolve (param.get_type ());
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 ());
@@ -421,23 +593,69 @@ 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);
+
+ auto default_const_decl
+ = new TyTy::ConstValueType (default_value, specified_type,
+ 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::BaseGeneric *const_decl
+ = new TyTy::ConstParamType (param.get_name (), param.get_locus (),
+ specified_type,
+ 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: {
- auto param_type = TypeResolveGenericParam::Resolve (*generic_param);
+ case HIR::GenericParam::GenericKind::TYPE:
+ {
+ if (is_foreign && abi != Rust::ABI::INTRINSIC)
+ {
+ rust_error_at (generic_param->get_locus (), ErrorCode::E0044,
+ "foreign items may not have type parameters");
+ }
+
+ auto param_type = TypeResolveGenericParam::Resolve (
+ *generic_param, false /*resolve_trait_bounds*/);
context->insert_type (generic_param->get_mappings (), param_type);
- substitutions.push_back (TyTy::SubstitutionParamMapping (
- static_cast<HIR::TypeParam &> (*generic_param), param_type));
+ TyTy::SubstitutionParamMapping p (*generic_param, param_type);
+ substitutions.push_back (p);
}
break;
}
}
+
+ // now walk them to setup any specified type param bounds
+ for (auto &subst : substitutions)
+ {
+ 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);
+ }
}
TyTy::TypeBoundPredicate
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index 8a1bf6f..6430089 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -32,6 +32,12 @@ class TypeCheckBase
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);
+
protected:
TypeCheckBase ();
@@ -41,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);
@@ -56,14 +62,15 @@ 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);
+ std::vector<TyTy::SubstitutionParamMapping> &substitutions,
+ bool is_foreign = false, ABI abi = ABI::RUST);
TyTy::TypeBoundPredicate get_marker_predicate (LangItem::Kind item_type,
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 b7fdc13..1c00fd96 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -16,6 +16,9 @@
// along with GCC; see the file COPYING3. If not see
// <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"
#include "rust-hir-type-check-struct-field.h"
@@ -29,9 +32,10 @@
#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 "rust-tyty.h"
+#include "tree.h"
namespace Rust {
namespace Resolver {
@@ -49,10 +53,32 @@ TypeCheckExpr::Resolve (HIR::Expr &expr)
if (resolver.infered == nullptr)
return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
- auto ref = expr.get_mappings ().get_hirid ();
- resolver.infered->set_ref (ref);
+ if (resolver.infered->get_kind () != TyTy::TypeKind::CONST)
+ {
+ auto ref = expr.get_mappings ().get_hirid ();
+ resolver.infered->set_ref (ref);
+ }
resolver.context->insert_type (expr.get_mappings (), resolver.infered);
+ if (auto fn = resolver.infered->try_as<const TyTy::FnType> ())
+ {
+ if (fn->is_syn_constant ())
+ resolver.infered = fn->get_return_type ();
+ }
+
+ 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;
}
@@ -109,7 +135,13 @@ TypeCheckExpr::visit (HIR::TupleIndexExpr &expr)
}
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (resolved);
- rust_assert (!adt->is_enum ());
+ if (!adt->is_tuple_struct ())
+ {
+ rust_error_at (expr.get_locus (),
+ "expected tuple or tuple struct, found %qs",
+ adt->get_name ().c_str ());
+ return;
+ }
rust_assert (adt->number_of_variants () == 1);
TyTy::VariantDef *variant = adt->get_variants ().at (0);
@@ -144,7 +176,7 @@ TypeCheckExpr::visit (HIR::TupleExpr &expr)
for (auto &elem : expr.get_tuple_elems ())
{
auto field_ty = TypeCheckExpr::Resolve (*elem);
- fields.push_back (TyTy::TyVar (field_ty->get_ref ()));
+ fields.emplace_back (field_ty->get_ref ());
}
infered = new TyTy::TupleType (expr.get_mappings ().get_hirid (),
expr.get_locus (), fields);
@@ -371,7 +403,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,
@@ -379,7 +412,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 ()),
@@ -468,7 +502,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)
@@ -490,7 +525,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)
@@ -609,10 +645,9 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
if (s->is_unit_check_needed () && !resolved->is_unit ())
{
auto unit = TyTy::TupleType::get_unit_type ();
- resolved
- = unify_site (s->get_mappings ().get_hirid (),
- TyTy::TyWithLocation (unit),
- TyTy::TyWithLocation (resolved), s->get_locus ());
+ unify_site (s->get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (unit),
+ TyTy::TyWithLocation (resolved), s->get_locus ());
}
}
@@ -641,6 +676,26 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
}
void
+TypeCheckExpr::visit (HIR::AnonConst &expr)
+{
+ if (!expr.is_deferred ())
+ {
+ infered = TypeCheckExpr::Resolve (expr.get_inner_expr ());
+ return;
+ }
+
+ TyTy::TyVar var
+ = TyTy::TyVar::get_implicit_const_infer_var (expr.get_locus ());
+ infered = var.get_tyty ();
+}
+
+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;
@@ -683,7 +738,7 @@ TypeCheckExpr::visit (HIR::RangeFromToExpr &expr)
// substitute it in
std::vector<TyTy::SubstitutionArg> subst_mappings;
const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
- subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified));
+ subst_mappings.emplace_back (param_ref, unified);
TyTy::SubstitutionArgumentMappings subst (
subst_mappings, {}, adt->get_substitution_arguments ().get_regions (),
@@ -727,7 +782,7 @@ TypeCheckExpr::visit (HIR::RangeFromExpr &expr)
// substitute it in
std::vector<TyTy::SubstitutionArg> subst_mappings;
const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
- subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty));
+ subst_mappings.emplace_back (param_ref, from_ty);
TyTy::SubstitutionArgumentMappings subst (
subst_mappings, {}, adt->get_substitution_arguments ().get_regions (),
@@ -771,7 +826,7 @@ TypeCheckExpr::visit (HIR::RangeToExpr &expr)
// substitute it in
std::vector<TyTy::SubstitutionArg> subst_mappings;
const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
- subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty));
+ subst_mappings.emplace_back (param_ref, from_ty);
TyTy::SubstitutionArgumentMappings subst (
subst_mappings, {}, adt->get_substitution_arguments ().get_regions (),
@@ -788,38 +843,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;
@@ -835,13 +897,39 @@ 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 ();
}
void
+TypeCheckExpr::visit (HIR::LlvmInlineAsm &expr)
+{
+ for (auto &i : expr.inputs)
+ TypeCheckExpr::Resolve (*i.expr);
+
+ for (auto &o : expr.outputs)
+ TypeCheckExpr::Resolve (*o.expr);
+
+ // Black box hint is unit type
+ infered = TyTy::TupleType::get_unit_type ();
+}
+
+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;
@@ -911,7 +999,7 @@ TypeCheckExpr::visit (HIR::RangeFromToInclExpr &expr)
// substitute it in
std::vector<TyTy::SubstitutionArg> subst_mappings;
const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
- subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified));
+ subst_mappings.emplace_back (param_ref, unified);
TyTy::SubstitutionArgumentMappings subst (
subst_mappings, {}, adt->get_substitution_arguments ().get_regions (),
@@ -945,7 +1033,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)
{
@@ -981,8 +1072,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 ());
}
@@ -992,35 +1082,44 @@ 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 ());
+ if (capacity_expr_ty->is<TyTy::ErrorType> ())
+ return;
- 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 ());
+ auto result = 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 ());
+ if (result->is<TyTy::ErrorType> ())
+ return;
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);
@@ -1053,17 +1152,35 @@ 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);
+
+ // Create ConstValueType with ref == ty_ref (both pointing to capacity_expr)
+ // ty_ref gets updated during substitution via set_ty_ref()
+ HirId capacity_expr_id = capacity_expr->get_mappings ().get_hirid ();
+ auto const_type
+ = new TyTy::ConstValueType (capacity_value, expected_ty, capacity_expr_id,
+ capacity_expr_id);
+
+ // Insert the ConstValueType at its ref
+ context->insert_type (capacity_expr->get_mappings (),
+ const_type->as_base_type ());
+
+ infered
+ = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), expr.get_locus (),
+ TyTy::TyVar (
+ const_type->as_base_type ()->get_ty_ref ()),
+ TyTy::TyVar (element_type->get_ref ()));
}
// empty struct
@@ -1127,33 +1244,119 @@ TypeCheckExpr::visit (HIR::FieldAccessExpr &expr)
bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT;
if (!is_valid_type)
{
- rust_error_at (expr.get_locus (),
- "expected algebraic data type got: [%s]",
- struct_base->as_string ().c_str ());
+ rust_error_at (expr.get_locus (), "expected algebraic data type got %qs",
+ struct_base->get_name ().c_str ());
return;
}
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (struct_base);
- rust_assert (!adt->is_enum ());
- rust_assert (adt->number_of_variants () == 1);
-
+ rust_assert (adt->number_of_variants () > 0);
TyTy::VariantDef *vaiant = adt->get_variants ().at (0);
TyTy::StructFieldType *lookup = nullptr;
bool found = vaiant->lookup_field (expr.get_field_name ().as_string (),
&lookup, nullptr);
- if (!found)
+ if (!found || adt->is_enum ())
{
- rust_error_at (expr.get_locus (), ErrorCode::E0609,
- "no field %qs on type %qs",
+ rich_location r (line_table, expr.get_locus ());
+ r.add_range (expr.get_field_name ().get_locus ());
+ rust_error_at (r, ErrorCode::E0609, "no field %qs on type %qs",
expr.get_field_name ().as_string ().c_str (),
- adt->as_string ().c_str ());
+ adt->get_name ().c_str ());
return;
}
infered = lookup->get_field_type ();
}
+bool
+is_default_fn (const MethodCandidate &candidate)
+{
+ if (candidate.candidate.is_impl_candidate ())
+ {
+ auto *item = candidate.candidate.item.impl.impl_item;
+
+ if (item->get_impl_item_type () == HIR::ImplItem::FUNCTION)
+ {
+ auto &fn = static_cast<HIR::Function &> (*item);
+
+ return fn.is_default ();
+ }
+ }
+
+ return false;
+}
+
+void
+emit_ambiguous_resolution_error (HIR::MethodCallExpr &expr,
+ std::set<MethodCandidate> &candidates)
+{
+ rich_location r (line_table, expr.get_method_name ().get_locus ());
+ std::string rich_msg = "multiple "
+ + expr.get_method_name ().get_segment ().as_string ()
+ + " found";
+
+ // We have to filter out default candidates
+ for (auto &c : candidates)
+ if (!is_default_fn (c))
+ r.add_range (c.candidate.locus);
+
+ r.add_fixit_replace (rich_msg.c_str ());
+
+ rust_error_at (r, ErrorCode::E0592, "duplicate definitions with name %qs",
+ expr.get_method_name ().get_segment ().as_string ().c_str ());
+}
+
+// We are allowed to have multiple candidates if they are all specializable
+// functions or if all of them except one are specializable functions.
+// In the later case, we just return a valid candidate without erroring out
+// about ambiguity. If there are two or more specialized functions, then we
+// error out.
+//
+// FIXME: The first case is not handled at the moment, so we error out
+tl::optional<const MethodCandidate &>
+handle_multiple_candidates (HIR::MethodCallExpr &expr,
+ std::set<MethodCandidate> &candidates)
+{
+ auto all_default = true;
+ tl::optional<const MethodCandidate &> found = tl::nullopt;
+
+ for (auto &c : candidates)
+ {
+ if (!is_default_fn (c))
+ {
+ all_default = false;
+
+ // We haven't found a final candidate yet, so we can select
+ // this one. However, if we already have a candidate, then
+ // that means there are multiple non-default candidates - we
+ // must error out
+ if (!found)
+ {
+ found = c;
+ }
+ else
+ {
+ emit_ambiguous_resolution_error (expr, candidates);
+ return tl::nullopt;
+ }
+ }
+ }
+
+ // None of the candidates were a non-default (specialized) function, so we
+ // error out
+ if (all_default)
+ {
+ rust_sorry_at (expr.get_locus (),
+ "cannot resolve method calls to non-specialized methods "
+ "(all function candidates are %qs)",
+ "default");
+ return tl::nullopt;
+ }
+
+ return found;
+}
+
void
TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
{
@@ -1181,34 +1384,25 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
return;
}
- if (candidates.size () > 1)
- {
- rich_location r (line_table, expr.get_method_name ().get_locus ());
- std::string rich_msg
- = "multiple " + expr.get_method_name ().get_segment ().as_string ()
- + " found";
+ tl::optional<const MethodCandidate &> candidate = *candidates.begin ();
- for (auto &c : candidates)
- r.add_range (c.candidate.locus);
+ if (candidates.size () > 1)
+ candidate = handle_multiple_candidates (expr, candidates);
- r.add_fixit_replace (rich_msg.c_str ());
+ if (!candidate)
+ return;
- rust_error_at (
- r, ErrorCode::E0592, "duplicate definitions with name %qs",
- expr.get_method_name ().get_segment ().as_string ().c_str ());
- return;
- }
+ auto found_candidate = *candidate;
- auto candidate = *candidates.begin ();
rust_debug_loc (expr.get_method_name ().get_locus (),
"resolved method to: {%u} {%s} with [%lu] adjustments",
- candidate.candidate.ty->get_ref (),
- candidate.candidate.ty->debug_str ().c_str (),
- (unsigned long) candidate.adjustments.size ());
+ found_candidate.candidate.ty->get_ref (),
+ found_candidate.candidate.ty->debug_str ().c_str (),
+ (unsigned long) found_candidate.adjustments.size ());
// Get the adjusted self
Adjuster adj (receiver_tyty);
- TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
+ TyTy::BaseType *adjusted_self = adj.adjust_type (found_candidate.adjustments);
rust_debug ("receiver: %s adjusted self %s",
receiver_tyty->debug_str ().c_str (),
adjusted_self->debug_str ().c_str ());
@@ -1219,10 +1413,10 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
HirId autoderef_mappings_id
= expr.get_receiver ().get_mappings ().get_hirid ();
context->insert_autoderef_mappings (autoderef_mappings_id,
- std::move (candidate.adjustments));
+ std::move (found_candidate.adjustments));
- PathProbeCandidate &resolved_candidate = candidate.candidate;
- TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
+ PathProbeCandidate &resolved_candidate = found_candidate.candidate;
+ TyTy::BaseType *lookup_tyty = found_candidate.candidate.ty;
NodeId resolved_node_id
= resolved_candidate.is_impl_candidate ()
? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
@@ -1249,8 +1443,8 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
fn->prepare_higher_ranked_bounds ();
rust_debug_loc (expr.get_locus (), "resolved method call to: {%u} {%s}",
- candidate.candidate.ty->get_ref (),
- candidate.candidate.ty->debug_str ().c_str ());
+ found_candidate.candidate.ty->get_ref (),
+ found_candidate.candidate.ty->debug_str ().c_str ());
if (resolved_candidate.is_impl_candidate ())
{
@@ -1316,26 +1510,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;
@@ -1463,6 +1642,15 @@ TypeCheckExpr::visit (HIR::BorrowExpr &expr)
}
}
+ if (expr.is_raw_borrow ())
+ {
+ infered = new TyTy::PointerType (expr.get_mappings ().get_hirid (),
+ TyTy::TyVar (resolved_base->get_ref ()),
+ expr.get_mut ());
+
+ return;
+ }
+
infered = new TyTy::ReferenceType (expr.get_mappings ().get_hirid (),
TyTy::TyVar (resolved_base->get_ref ()),
expr.get_mut ());
@@ -1601,16 +1789,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 ()};
+
+ if (context->have_function_context ())
+ {
+ TypeCheckContextItem current_context = context->peek_context ();
+ TyTy::FnType *current_context_fndecl
+ = current_context.get_context_type ();
- // get from parent context
- std::vector<TyTy::SubstitutionParamMapping> subst_refs
- = current_context_fndecl->clone_substs ();
+ 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 ())
@@ -1662,19 +1856,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);
@@ -1722,10 +1909,10 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr)
// auto resolve because the hir id's match
,
expr.get_locus ());
- args.get_type_args ().push_back (std::unique_ptr<HIR::Type> (implicit_tuple));
+ args.get_type_args ().emplace_back (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});
@@ -1744,7 +1931,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 ();
@@ -1788,15 +1984,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.emplace_back (&self_param_mapping, lhs);
+
+ if (rhs != nullptr)
+ {
+ rust_assert (trait_subst.size () == 2);
+ auto &rhs_param_mapping = trait_subst[1];
+ mappings.emplace_back (&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
@@ -1824,24 +2054,6 @@ TypeCheckExpr::resolve_operator_overload (
rust_debug ("is_impl_item_candidate: %s",
resolved_candidate.is_impl_candidate () ? "true" : "false");
- if (resolved_candidate.is_impl_candidate ())
- {
- auto infer_arguments = TyTy::SubstitutionArgumentMappings::error ();
- HIR::ImplBlock &impl = *resolved_candidate.item.impl.parent;
- TyTy::BaseType *impl_self_infer
- = TypeCheckItem::ResolveImplBlockSelfWithInference (impl,
- expr.get_locus (),
- &infer_arguments);
- if (impl_self_infer->get_kind () == TyTy::TypeKind::ERROR)
- {
- return false;
- }
- if (!infer_arguments.is_empty ())
- {
- lookup = SubstMapperInternal::Resolve (lookup, infer_arguments);
- }
- }
-
// in the case where we resolve to a trait bound we have to be careful we are
// able to do so there is a case where we are currently resolving the deref
// operator overload function which is generic and this might resolve to the
@@ -1939,19 +2151,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;
@@ -1961,16 +2165,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;
@@ -1993,6 +2194,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 ("");
@@ -2086,7 +2315,7 @@ TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr,
for (auto &arg : expr.get_arguments ())
{
TyTy::BaseType *a = TypeCheckExpr::Resolve (*arg);
- call_args.push_back (TyTy::TyVar (a->get_ref ()));
+ call_args.emplace_back (a->get_ref ());
}
// crate implicit tuple
@@ -2099,9 +2328,8 @@ TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr,
context->insert_implicit_type (implicit_arg_id, tuple);
std::vector<TyTy::Argument> args;
- TyTy::Argument a (mapping, tuple,
- expr.get_locus () /*FIXME is there a better location*/);
- args.push_back (std::move (a));
+ args.emplace_back (mapping, tuple,
+ expr.get_locus () /*FIXME is there a better location*/);
TyTy::BaseType *function_ret_tyty
= TyTy::TypeCheckMethodCallExpr::go (fn, expr.get_mappings (), args,
@@ -2119,32 +2347,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;
@@ -2156,7 +2367,12 @@ bool
TypeCheckExpr::validate_arithmetic_type (
const TyTy::BaseType *tyty, HIR::ArithmeticOrLogicalExpr::ExprType expr_type)
{
- const TyTy::BaseType *type = tyty->destructure ();
+ auto type = tyty->destructure ();
+ if (type->get_kind () == TyTy::TypeKind::CONST)
+ {
+ auto base_const = type->as_const_type ();
+ type = base_const->get_specified_type ();
+ }
// https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators
// this will change later when traits are added
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 2a0022c..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;
@@ -70,6 +78,8 @@ public:
void visit (HIR::WhileLoopExpr &expr) override;
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 {}
@@ -106,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 a5ae54b..8df8a18 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,44 +70,10 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function)
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (function.has_generics ())
{
- for (auto &generic_param : function.get_generic_params ())
- {
- switch (generic_param.get ()->get_kind ())
- {
- case HIR::GenericParam::GenericKind::LIFETIME:
- context->intern_and_insert_lifetime (
- static_cast<HIR::LifetimeParam &> (*generic_param)
- .get_lifetime ());
- // TODO: handle bounds
- break;
- case HIR::GenericParam::GenericKind::CONST:
- // FIXME: Skipping Lifetime and Const completely until better
- // handling.
- if (parent.get_abi () != Rust::ABI::INTRINSIC)
- {
- rust_error_at (function.get_locus (), ErrorCode::E0044,
- "foreign items may not have const parameters");
- }
- break;
-
- case HIR::GenericParam::GenericKind::TYPE: {
- if (parent.get_abi () != Rust::ABI::INTRINSIC)
- {
- rust_error_at (
- function.get_locus (), ErrorCode::E0044,
- "foreign items may not have type parameters");
- }
- auto param_type
- = TypeResolveGenericParam::Resolve (*generic_param);
- context->insert_type (generic_param->get_mappings (),
- param_type);
-
- substitutions.push_back (TyTy::SubstitutionParamMapping (
- static_cast<HIR::TypeParam &> (*generic_param), param_type));
- }
- break;
- }
- }
+ resolve_generic_params (HIR::Item::ItemKind::Function,
+ function.get_locus (),
+ function.get_generic_params (), substitutions,
+ true /*is_foreign*/, parent.get_abi ());
}
TyTy::RegionConstraints region_constraints;
@@ -158,7 +121,7 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function)
UNDEF_LOCATION, false, Mutability::Imm,
std::unique_ptr<HIR::Pattern> (nullptr)));
- params.push_back (TyTy::FnParam (std::move (param_pattern), param_tyty));
+ params.emplace_back (std::move (param_pattern), param_tyty);
context->insert_type (param.get_mappings (), param_tyty);
@@ -200,128 +163,7 @@ void
TypeCheckTopLevelExternItem::visit (HIR::ExternalTypeItem &type)
{
rust_sorry_at (type.get_locus (), "extern types are not supported yet");
- // auto binder_pin = context->push_clean_lifetime_resolver ();
-
- // std::vector<TyTy::SubstitutionParamMapping> substitutions;
- // if (function.has_generics ())
- // {
- // for (auto &generic_param : function.get_generic_params ())
- // {
- // switch (generic_param.get ()->get_kind ())
- // {
- // case HIR::GenericParam::GenericKind::LIFETIME:
- // context->intern_and_insert_lifetime (
- // static_cast<HIR::LifetimeParam &> (*generic_param)
- // .get_lifetime ());
- // // TODO: handle bounds
- // break;
- // case HIR::GenericParam::GenericKind::CONST:
- // // FIXME: Skipping Lifetime and Const completely until better
- // // handling.
- // break;
-
- // case HIR::GenericParam::GenericKind::TYPE: {
- // auto param_type
- // = TypeResolveGenericParam::Resolve (generic_param.get ());
- // context->insert_type (generic_param->get_mappings (),
- // param_type);
-
- // substitutions.push_back (TyTy::SubstitutionParamMapping (
- // static_cast<HIR::TypeParam &> (*generic_param), param_type));
- // }
- // break;
- // }
- // }
- // }
-
- // TyTy::RegionConstraints region_constraints;
- // if (function.has_where_clause ())
- // {
- // for (auto &where_clause_item : function.get_where_clause ().get_items
- // ())
- // {
- // ResolveWhereClauseItem::Resolve (*where_clause_item.get (),
- // region_constraints);
- // }
- // }
-
- // TyTy::BaseType *ret_type = nullptr;
- // if (!function.has_return_type ())
- // ret_type
- // = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid
- // ());
- // else
- // {
- // auto resolved
- // = TypeCheckType::Resolve (function.get_return_type ().get ());
- // if (resolved == nullptr)
- // {
- // rust_error_at (function.get_locus (),
- // "failed to resolve return type");
- // return;
- // }
-
- // ret_type = resolved->clone ();
- // ret_type->set_ref (
- // function.get_return_type ()->get_mappings ().get_hirid ());
- // }
-
- // std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
- // for (auto &param : function.get_function_params ())
- // {
- // // get the name as well required for later on
- // auto param_tyty = TypeCheckType::Resolve (param.get_type ().get ());
-
- // // these are implicit mappings and not used
- // auto crate_num = mappings->get_current_crate ();
- // Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id
- // (),
- // mappings->get_next_hir_id (crate_num),
- // UNKNOWN_LOCAL_DEFID);
-
- // HIR::IdentifierPattern *param_pattern
- // = new HIR::IdentifierPattern (mapping, param.get_param_name (),
- // UNDEF_LOCATION, false, Mutability::Imm,
- // std::unique_ptr<HIR::Pattern> (nullptr));
-
- // params.push_back (
- // std::pair<HIR::Pattern *, TyTy::BaseType *> (param_pattern,
- // param_tyty));
-
- // context->insert_type (param.get_mappings (), param_tyty);
-
- // // FIXME do we need error checking for patterns here?
- // // see https://github.com/Rust-GCC/gccrs/issues/995
- // }
-
- // uint8_t flags = TyTy::FnType::FNTYPE_IS_EXTERN_FLAG;
- // if (function.is_variadic ())
- // {
- // flags |= TyTy::FnType::FNTYPE_IS_VARADIC_FLAG;
- // if (parent.get_abi () != Rust::ABI::C)
- // {
- // rust_error_at (
- // function.get_locus (), ErrorCode::E0045,
- // "C-variadic function must have C or cdecl calling convention");
- // }
- // }
-
- // RustIdent ident{
- // CanonicalPath::new_seg (function.get_mappings ().get_nodeid (),
- // function.get_item_name ().as_string ()),
- // function.get_locus ()};
-
- // auto fnType = new TyTy::FnType (
- // function.get_mappings ().get_hirid (),
- // function.get_mappings ().get_defid (),
- // function.get_item_name ().as_string (), ident, flags, parent.get_abi (),
- // std::move (params), ret_type, std::move (substitutions),
- // TyTy::SubstitutionArgumentMappings::empty (
- // context->get_lifetime_resolver ().get_num_bound_regions ()),
- // region_constraints);
-
- // context->insert_type (function.get_mappings (), fnType);
- // resolved = fnType;
+ // TODO
}
TypeCheckImplItem::TypeCheckImplItem (
@@ -360,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 ())
@@ -399,7 +243,7 @@ TypeCheckImplItem::visit (HIR::Function &function)
// add the synthetic self param at the front, this is a placeholder for
// compilation to know parameter names. The types are ignored but we
// reuse the HIR identifier pattern which requires it
- HIR::SelfParam &self_param = function.get_self_param ();
+ HIR::SelfParam &self_param = function.get_self_param_unchecked ();
// FIXME: which location should be used for Rust::Identifier for `self`?
std::unique_ptr<HIR::Pattern> self_pattern
= std::make_unique<HIR::IdentifierPattern> (
@@ -423,14 +267,23 @@ TypeCheckImplItem::visit (HIR::Function &function)
self_type = self->clone ();
break;
- case HIR::SelfParam::IMM_REF: {
- auto region = context->lookup_and_resolve_lifetime (
- self_param.get_lifetime ());
- if (!region.has_value ())
+ case HIR::SelfParam::IMM_REF:
+ {
+ tl::optional<TyTy::Region> region;
+ if (self_param.has_lifetime ())
{
- rust_inform (self_param.get_locus (),
- "failed to resolve lifetime");
- region = TyTy::Region::make_anonymous (); // FIXME
+ region = context->lookup_and_resolve_lifetime (
+ self_param.get_lifetime ());
+ if (!region.has_value ())
+ {
+ rust_inform (self_param.get_locus (),
+ "failed to resolve lifetime");
+ return;
+ }
+ }
+ else
+ {
+ region = TyTy::Region::make_anonymous ();
}
self_type = new TyTy::ReferenceType (
self_param.get_mappings ().get_hirid (),
@@ -439,14 +292,23 @@ TypeCheckImplItem::visit (HIR::Function &function)
}
break;
- case HIR::SelfParam::MUT_REF: {
- auto region = context->lookup_and_resolve_lifetime (
- self_param.get_lifetime ());
- if (!region.has_value ())
+ case HIR::SelfParam::MUT_REF:
+ {
+ tl::optional<TyTy::Region> region;
+ if (self_param.has_lifetime ())
+ {
+ region = context->lookup_and_resolve_lifetime (
+ self_param.get_lifetime ());
+ if (!region.has_value ())
+ {
+ rust_error_at (self_param.get_locus (),
+ "failed to resolve lifetime");
+ return;
+ }
+ }
+ else
{
- rust_error_at (self_param.get_locus (),
- "failed to resolve lifetime");
- return;
+ region = TyTy::Region::make_anonymous ();
}
self_type = new TyTy::ReferenceType (
self_param.get_mappings ().get_hirid (),
@@ -462,7 +324,7 @@ TypeCheckImplItem::visit (HIR::Function &function)
}
context->insert_type (self_param.get_mappings (), self_type);
- params.push_back (TyTy::FnParam (std::move (self_pattern), self_type));
+ params.emplace_back (std::move (self_pattern), self_type);
}
for (auto &param : function.get_function_params ())
@@ -473,29 +335,17 @@ TypeCheckImplItem::visit (HIR::Function &function)
context->insert_type (param.get_mappings (), param_tyty);
TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
- params.push_back (
- TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty));
+ params.emplace_back (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 (),
@@ -541,8 +391,32 @@ TypeCheckImplItem::visit (HIR::ConstantItem &constant)
TyTy::TyWithLocation (type, constant.get_type ().get_locus ()),
TyTy::TyWithLocation (expr_type, constant.get_expr ().get_locus ()),
constant.get_locus ());
- context->insert_type (constant.get_mappings (), unified);
- result = unified;
+
+ if (substitutions.empty ())
+ {
+ context->insert_type (constant.get_mappings (), unified);
+ result = unified;
+ return;
+ }
+
+ // special case when this is a generic constant
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (constant.get_mappings ().get_nodeid ());
+ RustIdent ident{canonical_path, constant.get_locus ()};
+ auto fnType = new TyTy::FnType (
+ constant.get_mappings ().get_hirid (),
+ constant.get_mappings ().get_defid (),
+ constant.get_identifier ().as_string (), ident,
+ TyTy::FnType::FNTYPE_IS_SYN_CONST_FLAG, ABI::RUST, {}, unified,
+ std::move (substitutions),
+ TyTy::SubstitutionArgumentMappings::empty (
+ context->get_lifetime_resolver ().get_num_bound_regions ()),
+ {});
+
+ context->insert_type (constant.get_mappings (), fnType);
+ result = fnType;
}
void
@@ -551,7 +425,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 ());
@@ -618,8 +493,8 @@ TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant)
}
// get the item from the predicate
- resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item);
- rust_assert (!resolved_trait_item.is_error ());
+ resolved_trait_item
+ = trait_reference.lookup_associated_item (raw_trait_item).value ();
// merge the attributes
const HIR::TraitItem *hir_trait_item
@@ -635,16 +510,21 @@ 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 ());
}
}
void
TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type)
{
+ auto binder_pin = context->push_lifetime_binder ();
+
+ if (type.has_generics ())
+ resolve_generic_params (HIR::Item::ItemKind::TypeAlias, type.get_locus (),
+ type.get_generic_params (), substitutions);
+
// normal resolution of the item
TyTy::BaseType *lookup
= TypeCheckImplItem::Resolve (parent, type, self, substitutions);
@@ -669,8 +549,8 @@ TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type)
}
// get the item from the predicate
- resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item);
- rust_assert (!resolved_trait_item.is_error ());
+ resolved_trait_item
+ = trait_reference.lookup_associated_item (raw_trait_item).value ();
// merge the attributes
const HIR::TraitItem *hir_trait_item
@@ -686,10 +566,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
@@ -709,6 +588,8 @@ TypeCheckImplItemWithTrait::visit (HIR::Function &function)
// normal resolution of the item
TyTy::BaseType *lookup
= TypeCheckImplItem::Resolve (parent, function, self, substitutions);
+ if (lookup == nullptr)
+ return;
// map the impl item to the associated trait item
const auto tref = trait_reference.get ();
@@ -729,8 +610,8 @@ TypeCheckImplItemWithTrait::visit (HIR::Function &function)
}
// get the item from the predicate
- resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item);
- rust_assert (!resolved_trait_item.is_error ());
+ resolved_trait_item
+ = trait_reference.lookup_associated_item (raw_trait_item).value ();
// merge the attributes
const HIR::TraitItem *hir_trait_item
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index 9774921..ee5c4e9 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 {
@@ -114,17 +112,27 @@ TypeCheckItem::ResolveImplBlockSelfWithInference (
std::vector<TyTy::SubstitutionArg> args;
for (auto &p : substitutions)
{
- if (p.needs_substitution ())
+ auto param = p.get_param_ty ();
+ if (!p.needs_substitution ())
{
- TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
- args.push_back (TyTy::SubstitutionArg (&p, infer_var.get_tyty ()));
+ auto resolved = param->destructure ();
+ args.emplace_back (&p, resolved);
+
+ continue;
+ }
+
+ TyTy::BaseType *argument = nullptr;
+ if (param->get_kind () == TyTy::TypeKind::CONST)
+ {
+ auto i = TyTy::TyVar::get_implicit_const_infer_var (locus);
+ argument = i.get_tyty ();
}
else
{
- TyTy::ParamType *param = p.get_param_ty ();
- TyTy::BaseType *resolved = param->destructure ();
- args.push_back (TyTy::SubstitutionArg (&p, resolved));
+ auto i = TyTy::TyVar::get_implicit_infer_var (locus);
+ argument = i.get_tyty ();
}
+ args.emplace_back (&p, argument);
}
// create argument mappings
@@ -170,7 +178,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 +205,11 @@ TypeCheckItem::visit (HIR::TupleStruct &struct_decl)
// get the path
- auto path = CanonicalPath::create_empty ();
-
- // FIXME: HACK: ARTHUR: Disgusting
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ 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 +251,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 +274,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 +319,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 ();
@@ -355,26 +338,26 @@ TypeCheckItem::visit (HIR::Enum &enum_decl)
variants.push_back (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 (
- enum_decl.get_mappings ().get_nodeid ());
- }
- else
+ // Check for zero-variant enum compatibility
+ if (enum_decl.is_zero_variant ())
{
- canonical_path = mappings.lookup_canonical_path (
- enum_decl.get_mappings ().get_nodeid ());
+ if (repr.repr_kind == TyTy::ADTType::ReprKind::INT
+ || repr.repr_kind == TyTy::ADTType::ReprKind::C)
+ {
+ rust_error_at (enum_decl.get_locus (),
+ "unsupported representation for zero-variant enum");
+ return;
+ }
}
- rust_assert (canonical_path.has_value ());
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- RustIdent ident{*canonical_path, enum_decl.get_locus ()};
+ // 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 ()};
// multi variant ADT
auto *type
@@ -397,7 +380,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 ())
@@ -419,26 +403,14 @@ TypeCheckItem::visit (HIR::Union &union_decl)
ty_variant->get_field_type ());
}
- // get the path
- 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 (
- union_decl.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = mappings.lookup_canonical_path (
- union_decl.get_mappings ().get_nodeid ());
- }
-
- 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;
@@ -557,8 +529,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 ())
@@ -591,28 +564,15 @@ TypeCheckItem::visit (HIR::Function &function)
auto param_tyty = TypeCheckType::Resolve (param.get_type ());
context->insert_type (param.get_mappings (), param_tyty);
TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
- params.push_back (
- TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty));
+ params.emplace_back (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 ()};
@@ -637,6 +597,38 @@ TypeCheckItem::visit (HIR::Function &function)
context->switch_to_fn_body ();
auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ());
+ // emit check for
+ // error[E0121]: the type placeholder `_` is not allowed within types on item
+ const auto placeholder = ret_type->contains_infer ();
+ if (placeholder != nullptr && function.has_return_type ())
+ {
+ // FIXME
+ // this will be a great place for the Default Hir Visitor we want to
+ // grab the locations of the placeholders (HIR::InferredType) their
+ // location, for now maybe we can use their hirid to lookup the location
+ location_t placeholder_locus
+ = mappings.lookup_location (placeholder->get_ref ());
+ location_t type_locus = function.get_return_type ().get_locus ();
+ rich_location r (line_table, placeholder_locus);
+
+ bool have_expected_type
+ = block_expr_ty != nullptr && !block_expr_ty->is<TyTy::ErrorType> ();
+ if (!have_expected_type)
+ {
+ r.add_range (type_locus);
+ }
+ else
+ {
+ std::string fixit
+ = "replace with the correct type " + block_expr_ty->get_name ();
+ r.add_fixit_replace (type_locus, fixit.c_str ());
+ }
+
+ rust_error_at (r, ErrorCode::E0121,
+ "the type placeholder %<_%> is not allowed within types "
+ "on item signatures");
+ }
+
location_t fn_return_locus = function.has_function_return_type ()
? function.get_return_type ().get_locus ()
: function.get_locus ();
@@ -701,13 +693,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 1fe39aae..ffa0990 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -77,9 +77,9 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
// lookup the associated item from the specified bound
HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
HIR::PathIdentSegment item_seg_identifier = item_seg.get_segment ();
- TyTy::TypeBoundPredicateItem item
+ tl::optional<TyTy::TypeBoundPredicateItem> item
= specified_bound.lookup_associated_item (item_seg_identifier.as_string ());
- if (item.is_error ())
+ if (!item.has_value ())
{
rust_error_at (item_seg.get_locus (), "unknown associated item");
return;
@@ -116,9 +116,9 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
// and we dont need to worry if the trait item is actually implemented or
// not because this will have already been validated as part of the trait
// impl block
- infered = item.get_tyty_for_receiver (root);
+ infered = item->get_tyty_for_receiver (root);
root_resolved_node_id
- = item.get_raw_item ()->get_mappings ().get_nodeid ();
+ = item->get_raw_item ()->get_mappings ().get_nodeid ();
}
else
{
@@ -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)
{
@@ -336,7 +319,7 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
TyTy::BaseType *lookup = nullptr;
if (!query_type (ref, &lookup))
{
- if (is_root)
+ if (is_root || root_tyty == nullptr)
{
rust_error_at (expr.get_locus (), ErrorCode::E0425,
"cannot find value %qs in this scope",
@@ -534,9 +517,8 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
const auto &predicate
= impl_block_ty->lookup_predicate (trait_ref.get_defid ());
if (!predicate.is_error ())
- impl_block_ty
- = associated->setup_associated_types (prev_segment, predicate,
- nullptr, false);
+ associated->setup_associated_types (prev_segment, predicate,
+ nullptr, false);
}
}
@@ -561,33 +543,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 3f9557a..7dae303 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -21,9 +21,8 @@
#include "rust-hir-type-check-expr.h"
#include "rust-type-util.h"
#include "rust-immutable-name-resolution-context.h"
-
-// for flag_name_resolution_2_0
-#include "options.h"
+#include "rust-tyty.h"
+#include "tree.h"
namespace Rust {
namespace Resolver {
@@ -54,23 +53,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;
@@ -173,19 +162,32 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
infered = pattern_ty;
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered);
- rust_assert (adt->number_of_variants () > 0);
- TyTy::VariantDef *variant = adt->get_variants ().at (0);
+ TyTy::VariantDef *variant = nullptr;
if (adt->is_enum ())
{
HirId variant_id = UNKNOWN_HIRID;
bool ok = context->lookup_variant_definition (
pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
- rust_assert (ok);
+ if (!ok)
+ {
+ rust_error_at (
+ pattern.get_locus (), ErrorCode::E0532,
+ "expected tuple struct or tuple variant, found enum %qs",
+ pattern_ty->get_name ().c_str ());
+ return;
+ }
ok = adt->lookup_variant_by_id (variant_id, &variant);
rust_assert (ok);
}
+ else
+ {
+ rust_assert (adt->number_of_variants () > 0);
+ variant = adt->get_variants ().at (0);
+ }
+
+ rust_assert (variant != nullptr);
// error[E0532]: expected tuple struct or tuple variant, found struct
// variant `Foo::D`, E0532 by rustc 1.49.0 , E0164 by rustc 1.71.0
@@ -213,31 +215,144 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
auto &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case HIR::TupleStructItems::RANGED: {
- // TODO
- rust_unreachable ();
+ case HIR::TupleStructItems::HAS_REST:
+ {
+ HIR::TupleStructItemsHasRest &items_has_rest
+ = static_cast<HIR::TupleStructItemsHasRest &> (items);
+ auto &lower_patterns = items_has_rest.get_lower_patterns ();
+ auto &upper_patterns = items_has_rest.get_upper_patterns ();
+ size_t pattern_min_cap
+ = lower_patterns.size () + upper_patterns.size ();
+ if (variant->num_fields () < pattern_min_cap)
+ {
+ if (!lower_patterns.empty ())
+ {
+ // TODO initialize rich_locus with loc of ADT definition instead
+ rich_location rich_locus (line_table,
+ lower_patterns[0]->get_locus ());
+ for (auto &pattern : lower_patterns)
+ {
+ if (pattern == lower_patterns[0])
+ continue;
+ rich_locus.add_range (pattern->get_locus (),
+ SHOW_RANGE_WITH_CARET);
+ }
+ for (auto &pattern : upper_patterns)
+ {
+ rich_locus.add_range (pattern->get_locus (),
+ SHOW_RANGE_WITH_CARET);
+ }
+ rust_error_at (rich_locus, ErrorCode::E0023,
+ "this pattern has %lu %s but the corresponding "
+ "tuple variant has %lu %s",
+ (unsigned long) (pattern_min_cap),
+ pattern_min_cap == 1 ? "field" : "fields",
+ (unsigned long) variant->num_fields (),
+ variant->num_fields () == 1 ? "field"
+ : "fields");
+ }
+ else
+ {
+ // TODO initialize rich_locus with loc of ADT definition instead
+ rich_location rich_locus (line_table,
+ upper_patterns[0]->get_locus ());
+ for (auto &pattern : upper_patterns)
+ {
+ if (pattern == upper_patterns[0])
+ continue;
+ rich_locus.add_range (pattern->get_locus (),
+ SHOW_RANGE_WITH_CARET);
+ }
+ rust_error_at (rich_locus, ErrorCode::E0023,
+ "this pattern has %lu %s but the corresponding "
+ "tuple variant has %lu %s",
+ (unsigned long) (pattern_min_cap),
+ pattern_min_cap == 1 ? "field" : "fields",
+ (unsigned long) variant->num_fields (),
+ variant->num_fields () == 1 ? "field"
+ : "fields");
+ }
+ // we continue on to try and setup the types as best we can for
+ // type checking
+ }
+
+ // iterate the fields manually to set them up
+ size_t i = 0;
+ for (auto &pattern : lower_patterns)
+ {
+ if (i >= variant->num_fields ())
+ break;
+
+ TyTy::StructFieldType *field = variant->get_field_at_index (i++);
+ TyTy::BaseType *fty = field->get_field_type ();
+
+ // setup the type on this pattern type
+ context->insert_type (pattern->get_mappings (), fty);
+ TypeCheckPattern::Resolve (*pattern, fty);
+ }
+
+ i = variant->num_fields () - upper_patterns.size ();
+ for (auto &pattern : upper_patterns)
+ {
+ if (i >= variant->num_fields ())
+ break;
+
+ TyTy::StructFieldType *field = variant->get_field_at_index (i++);
+ TyTy::BaseType *fty = field->get_field_type ();
+
+ // setup the type on this pattern type
+ context->insert_type (pattern->get_mappings (), fty);
+ TypeCheckPattern::Resolve (*pattern, fty);
+ }
}
break;
- case HIR::TupleStructItems::MULTIPLE: {
- HIR::TupleStructItemsNoRange &items_no_range
- = static_cast<HIR::TupleStructItemsNoRange &> (items);
+ case HIR::TupleStructItems::NO_REST:
+ {
+ HIR::TupleStructItemsNoRest &items_no_rest
+ = static_cast<HIR::TupleStructItemsNoRest &> (items);
+ auto &patterns = items_no_rest.get_patterns ();
- if (items_no_range.get_patterns ().size () != variant->num_fields ())
+ if (patterns.size () != variant->num_fields ())
{
- rust_error_at (
- pattern.get_locus (), ErrorCode::E0023,
- "this pattern has %lu fields but the corresponding "
- "tuple variant has %lu field",
- (unsigned long) items_no_range.get_patterns ().size (),
- (unsigned long) variant->num_fields ());
+ if (patterns.empty ())
+ {
+ rust_error_at (pattern.get_locus (), ErrorCode::E0023,
+ "this pattern has %lu %s but the corresponding "
+ "tuple variant has %lu %s",
+ (unsigned long) patterns.size (),
+ patterns.size () == 1 ? "field" : "fields",
+ (unsigned long) variant->num_fields (),
+ variant->num_fields () == 1 ? "field"
+ : "fields");
+ }
+ else
+ {
+ rich_location rich_locus (line_table,
+ patterns[0]->get_locus ());
+ for (auto &pattern : items_no_rest.get_patterns ())
+ {
+ if (pattern == patterns[0])
+ continue;
+ rich_locus.add_range (pattern->get_locus (),
+ SHOW_RANGE_WITH_CARET);
+ }
+ rust_error_at (rich_locus, ErrorCode::E0023,
+ "this pattern has %lu %s but the corresponding "
+ "tuple variant has %lu %s",
+ (unsigned long) patterns.size (),
+ patterns.size () == 1 ? "field" : "fields",
+ (unsigned long) variant->num_fields (),
+ variant->num_fields () == 1 ? "field"
+ : "fields");
+ }
// we continue on to try and setup the types as best we can for
// type checking
}
// iterate the fields and set them up, I wish we had ZIP
size_t i = 0;
- for (auto &pattern : items_no_range.get_patterns ())
+ for (auto &pattern : items_no_rest.get_patterns ())
{
if (i >= variant->num_fields ())
break;
@@ -277,7 +392,15 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
infered = pattern_ty;
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered);
- rust_assert (adt->number_of_variants () > 0);
+ if (adt->number_of_variants () == 0)
+ {
+ HIR::PathInExpression &path = pattern.get_path ();
+ const AST::SimplePath &sp = path.as_simple_path ();
+ rust_error_at (pattern.get_locus (), ErrorCode::E0574,
+ "expected struct, variant or union type, found enum %qs",
+ sp.as_string ().c_str ());
+ return;
+ }
TyTy::VariantDef *variant = adt->get_variants ().at (0);
if (adt->is_enum ())
@@ -285,7 +408,16 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
HirId variant_id = UNKNOWN_HIRID;
bool ok = context->lookup_variant_definition (
pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
- rust_assert (ok);
+ if (!ok)
+ {
+ HIR::PathInExpression &path = pattern.get_path ();
+ const AST::SimplePath &sp = path.as_simple_path ();
+ rust_error_at (
+ pattern.get_locus (), ErrorCode::E0574,
+ "expected struct, variant or union type, found enum %qs",
+ sp.as_string ().c_str ());
+ return;
+ }
ok = adt->lookup_variant_by_id (variant_id, &variant);
rust_assert (ok);
@@ -293,7 +425,30 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
// error[E0532]: expected tuple struct or tuple variant, found struct
// variant `Foo::D`
- if (variant->get_variant_type () != TyTy::VariantDef::VariantType::STRUCT)
+ bool error_E0532 = false;
+ if (variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE)
+ {
+ // Tuple structs can still be matched with struct patterns via index
+ // numbers e.g. Foo {0: a, .., 3: b}, so check whether the fields are of
+ // type TUPLE_PAT. Throw E0532 if not.
+ auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
+ for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
+ {
+ if (field->get_item_type ()
+ != HIR::StructPatternField::ItemType::TUPLE_PAT)
+ {
+ error_E0532 = true;
+ break;
+ }
+ }
+ }
+ else if (variant->get_variant_type ()
+ != TyTy::VariantDef::VariantType::STRUCT)
+ {
+ error_E0532 = true;
+ }
+
+ if (error_E0532)
{
std::string variant_type
= TyTy::VariantDef::variant_type_string (variant->get_variant_type ());
@@ -316,13 +471,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);
@@ -341,7 +498,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);
@@ -380,7 +538,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)
@@ -397,7 +556,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
// Expects enum struct or struct struct.
// error[E0027]: pattern does not mention fields `x`, `y`
// error[E0026]: variant `Foo::D` does not have a field named `b`
- if (named_fields.size () != variant->num_fields ())
+ if (!pattern.get_struct_pattern_elems ().has_rest ()
+ && named_fields.size () != variant->num_fields ())
{
std::map<std::string, bool> missing_names;
@@ -440,25 +600,27 @@ void
TypeCheckPattern::visit (HIR::TuplePattern &pattern)
{
std::unique_ptr<HIR::TuplePatternItems> items;
- switch (pattern.get_items ().get_item_type ())
+
+ // Check whether parent is tuple
+ auto resolved_parent = parent->destructure ();
+ if (resolved_parent->get_kind () != TyTy::TUPLE)
{
- case HIR::TuplePatternItems::ItemType::MULTIPLE: {
- auto &ref = static_cast<HIR::TuplePatternItemsMultiple &> (
- pattern.get_items ());
+ 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);
- 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;
- }
+ switch (pattern.get_items ().get_item_type ())
+ {
+ case HIR::TuplePatternItems::ItemType::NO_REST:
+ {
+ auto &ref
+ = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ());
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 (),
@@ -474,19 +636,70 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern)
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 ()));
+ pattern_elems.emplace_back (elem->get_ref ());
}
infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (),
pattern.get_locus (), pattern_elems);
}
break;
- case HIR::TuplePatternItems::ItemType::RANGED: {
- // HIR::TuplePatternItemsRanged &ref
- // = *static_cast<HIR::TuplePatternItemsRanged *> (
- // pattern.get_items ().get ());
- // TODO
- rust_unreachable ();
+ case HIR::TuplePatternItems::ItemType::HAS_REST:
+ {
+ HIR::TuplePatternItemsHasRest &ref
+ = static_cast<HIR::TuplePatternItemsHasRest &> (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);
+ // continue and attempt to resolve individual items in the pattern
+ }
+
+ // Resolve lower patterns
+ std::vector<TyTy::TyVar> pattern_elems;
+ size_t nlower_items_to_resolve
+ = std::min (lower.size (), par.get_fields ().size ());
+ for (size_t i = 0; i < nlower_items_to_resolve; i++)
+ {
+ auto &p = lower[i];
+ TyTy::BaseType *par_type = par.get_field (i);
+
+ TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
+ pattern_elems.emplace_back (elem->get_ref ());
+ }
+
+ if (lower.size () > par.get_fields ().size ())
+ break;
+
+ // Pad pattern_elems until needing to resolve upper patterns
+ size_t rest_end
+ = std::max (par.get_fields ().size () - upper.size (), lower.size ());
+ for (size_t i = lower.size (); i < rest_end; i++)
+ {
+ TyTy::BaseType *par_type = par.get_field (i);
+ pattern_elems.emplace_back (par_type->get_ref ());
+ }
+
+ size_t nupper_items_to_resolve
+ = std::min (upper.size (),
+ par.get_fields ().size () - pattern_elems.size ());
+ // Resolve upper patterns
+ for (size_t i = 0; i < nupper_items_to_resolve; 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.emplace_back (elem->get_ref ());
+ }
+
+ infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (),
+ pattern.get_locus (), pattern_elems);
}
break;
}
@@ -495,8 +708,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
@@ -521,6 +744,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;
@@ -563,8 +791,150 @@ 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 = error_mark_node;
+ if (capacity->get_kind () != TyTy::TypeKind::CONST)
+ {
+ // Error case - capacity is not a const type
+ break;
+ }
+
+ auto *capacity_const = capacity->as_const_type ();
+ switch (capacity_const->const_kind ())
+ {
+ case TyTy::BaseConstType::ConstKind::Value:
+ {
+ const auto &const_value
+ = *static_cast<TyTy::ConstValueType *> (capacity);
+ cap = const_value.get_value ();
+ }
+ break;
+
+ case TyTy::BaseConstType::ConstKind::Decl:
+ case TyTy::BaseConstType::ConstKind::Infer:
+ case TyTy::BaseConstType::ConstKind::Error:
+ cap = error_mark_node;
+ break;
+ }
+
+ 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 ();
+
+ // size check during compile time
+ switch (pattern.get_items ().get_item_type ())
+ {
+ case HIR::SlicePatternItems::ItemType::NO_REST:
+ {
+ auto &ref = static_cast<HIR::SlicePatternItemsNoRest &> (
+ pattern.get_items ());
+ if (cap_wi != ref.get_patterns ().size ())
+ {
+ rust_error_at (
+ pattern.get_locus (), ErrorCode::E0527,
+ "pattern requires %lu elements but array has %lu",
+ (unsigned long) ref.get_patterns ().size (),
+ (unsigned long) cap_wi);
+ break;
+ }
+ }
+ break;
+ case HIR::SlicePatternItems::ItemType::HAS_REST:
+ {
+ auto &ref = static_cast<HIR::SlicePatternItemsHasRest &> (
+ pattern.get_items ());
+ auto pattern_min_cap = ref.get_lower_patterns ().size ()
+ + ref.get_upper_patterns ().size ();
+
+ if (cap_wi < pattern_min_cap)
+ {
+ rust_error_at (pattern.get_locus (), ErrorCode::E0528,
+ "pattern requires at least %lu elements but "
+ "array has %lu",
+ (unsigned long) pattern_min_cap,
+ (unsigned long) cap_wi);
+ break;
+ }
+ }
+ 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
+ switch (pattern.get_items ().get_item_type ())
+ {
+ case HIR::SlicePatternItems::ItemType::NO_REST:
+ {
+ auto &ref
+ = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ());
+ for (const auto &pattern_member : ref.get_patterns ())
+ {
+ TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
+ }
+ break;
+ }
+ case HIR::SlicePatternItems::ItemType::HAS_REST:
+ {
+ auto &ref
+ = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
+ for (const auto &pattern_member : ref.get_lower_patterns ())
+ {
+ TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
+ }
+ for (const auto &pattern_member : ref.get_upper_patterns ())
+ {
+ TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
+ }
+ break;
+ }
+ }
}
void
@@ -591,7 +961,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 ();
@@ -600,14 +971,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 ());
@@ -677,6 +1050,11 @@ ClosureParamInfer::visit (HIR::WildcardPattern &pattern)
void
ClosureParamInfer::visit (HIR::IdentifierPattern &pattern)
{
+ if (pattern.has_subpattern ())
+ {
+ ClosureParamInfer::Resolve (pattern.get_subpattern ());
+ }
+
HirId id = pattern.get_mappings ().get_hirid ();
infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
TyTy::InferType::TypeHint::Default (),
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-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
index 800f7ca..7e3a57a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
@@ -60,6 +60,9 @@ private:
TyTy::BaseType *resolved_field_value_expr;
std::set<std::string> fields_assigned;
std::map<size_t, HIR::StructExprField *> adtFieldIndexToField;
+
+ // parent
+ HIR::Expr &parent;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
index 40c42b2..eb44279 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
@@ -28,7 +28,7 @@ TypeCheckStructExpr::TypeCheckStructExpr (HIR::Expr &e)
: TypeCheckBase (),
resolved (new TyTy::ErrorType (e.get_mappings ().get_hirid ())),
struct_path_resolved (nullptr),
- variant (&TyTy::VariantDef::get_error_node ())
+ variant (&TyTy::VariantDef::get_error_node ()), parent (e)
{}
TyTy::BaseType *
@@ -65,7 +65,7 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
if (base_unify->get_kind () != struct_path_ty->get_kind ())
{
- rust_fatal_error (
+ rust_error_at (
struct_expr.get_struct_base ().get_base ().get_locus (),
"incompatible types for base struct reference");
return;
@@ -82,7 +82,16 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
bool ok = context->lookup_variant_definition (
struct_expr.get_struct_name ().get_mappings ().get_hirid (),
&variant_id);
- rust_assert (ok);
+ if (!ok)
+ {
+ rich_location r (line_table, struct_expr.get_locus ());
+ r.add_range (struct_expr.get_struct_name ().get_locus ());
+ rust_error_at (
+ struct_expr.get_struct_name ().get_locus (), ErrorCode::E0574,
+ "expected a struct, variant or union type, found enum %qs",
+ struct_path_resolved->get_name ().c_str ());
+ return;
+ }
ok = struct_path_resolved->lookup_variant_by_id (variant_id, &variant);
rust_assert (ok);
@@ -118,29 +127,14 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
break;
}
- if (!ok)
- {
- return;
- }
-
- if (resolved_field_value_expr == nullptr)
- {
- rust_fatal_error (field->get_locus (),
- "failed to resolve type for field");
- ok = false;
- break;
- }
-
- context->insert_type (field->get_mappings (), resolved_field_value_expr);
+ if (ok)
+ context->insert_type (field->get_mappings (),
+ resolved_field_value_expr);
}
- // something failed setting up the fields
+ // something failed setting up the fields and error's emitted
if (!ok)
- {
- rust_error_at (struct_expr.get_locus (),
- "constructor type resolution failure");
- return;
- }
+ return;
// check the arguments are all assigned and fix up the ordering
std::vector<std::string> missing_field_names;
@@ -220,8 +214,7 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
rust_assert (ok);
adtFieldIndexToField[field_index] = implicit_field;
- struct_expr.get_fields ().push_back (
- std::unique_ptr<HIR::StructExprField> (implicit_field));
+ struct_expr.get_fields ().emplace_back (implicit_field);
}
}
}
@@ -251,11 +244,11 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
field.release ();
std::vector<std::unique_ptr<HIR::StructExprField> > ordered_fields;
+ ordered_fields.reserve (adtFieldIndexToField.size ());
+
for (size_t i = 0; i < adtFieldIndexToField.size (); i++)
- {
- ordered_fields.push_back (
- std::unique_ptr<HIR::StructExprField> (adtFieldIndexToField[i]));
- }
+ ordered_fields.emplace_back (adtFieldIndexToField[i]);
+
struct_expr.set_fields_as_owner (std::move (ordered_fields));
}
@@ -271,8 +264,11 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
&field_index);
if (!ok)
{
- rust_error_at (field.get_locus (), "unknown field");
- return true;
+ rich_location r (line_table, parent.get_locus ());
+ r.add_range (field.get_locus ());
+ rust_error_at (r, ErrorCode::E0560, "unknown field %qs",
+ field.field_name.as_string ().c_str ());
+ return false;
}
auto it = adtFieldIndexToField.find (field_index);
@@ -317,8 +313,11 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
bool ok = variant->lookup_field (field_name, &field_type, &field_index);
if (!ok)
{
- rust_error_at (field.get_locus (), "unknown field");
- return true;
+ rich_location r (line_table, parent.get_locus ());
+ r.add_range (field.get_locus ());
+ rust_error_at (r, ErrorCode::E0560, "unknown field %qs",
+ field_name.c_str ());
+ return false;
}
auto it = adtFieldIndexToField.find (field_index);
@@ -329,8 +328,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 +361,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 54f50ec..ca7ef47 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 {
@@ -96,15 +97,20 @@ TypeCheckType::visit (HIR::BareFunctionType &fntype)
}
std::vector<TyTy::TyVar> params;
+ params.reserve (fntype.get_function_params ().size ());
+
for (auto &param : fntype.get_function_params ())
{
TyTy::BaseType *ptype = TypeCheckType::Resolve (param.get_type ());
- params.push_back (TyTy::TyVar (ptype->get_ref ()));
+ params.emplace_back (ptype->get_ref ());
}
- translated = new TyTy::FnPtr (fntype.get_mappings ().get_hirid (),
- fntype.get_locus (), std::move (params),
- TyTy::TyVar (return_type->get_ref ()));
+ translated
+ = new TyTy::FnPtr (fntype.get_mappings ().get_hirid (), fntype.get_locus (),
+ std::move (params),
+ TyTy::TyVar (return_type->get_ref ()),
+ fntype.get_function_qualifiers ().get_abi (),
+ fntype.get_function_qualifiers ().get_unsafety ());
}
void
@@ -117,10 +123,12 @@ TypeCheckType::visit (HIR::TupleType &tuple)
}
std::vector<TyTy::TyVar> fields;
+ fields.reserve (tuple.get_elems ().size ());
+
for (auto &elem : tuple.get_elems ())
{
auto field_ty = TypeCheckType::Resolve (*elem);
- fields.push_back (TyTy::TyVar (field_ty->get_ref ()));
+ fields.emplace_back (field_ty->get_ref ());
}
translated = new TyTy::TupleType (tuple.get_mappings ().get_hirid (),
@@ -206,9 +214,9 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
// lookup the associated item from the specified bound
HIR::TypePathSegment &item_seg = path.get_associated_segment ();
HIR::PathIdentSegment item_seg_identifier = item_seg.get_ident_segment ();
- TyTy::TypeBoundPredicateItem item
+ tl::optional<TyTy::TypeBoundPredicateItem> item
= specified_bound.lookup_associated_item (item_seg_identifier.as_string ());
- if (item.is_error ())
+ if (!item.has_value ())
{
std::string item_seg_ident_name, rich_msg;
item_seg_ident_name = qual_path_type.get_trait ().as_string ();
@@ -260,7 +268,7 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
// and we dont need to worry if the trait item is actually implemented or
// not because this will have already been validated as part of the trait
// impl block
- translated = item.get_tyty_for_receiver (root);
+ translated = item->get_tyty_for_receiver (root);
}
else
{
@@ -335,19 +343,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.
@@ -417,8 +419,13 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
TyTy::BaseType *lookup = nullptr;
if (!query_type (ref, &lookup))
{
- if (is_root)
- return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
+ if (is_root || root_tyty == nullptr)
+ {
+ rust_error_at (seg->get_locus (),
+ "failed to resolve type path segment: %qs",
+ seg->as_string ().c_str ());
+ return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
+ }
return root_tyty;
}
@@ -544,8 +551,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;
@@ -573,6 +579,7 @@ TypeCheckType::resolve_segments (
ignore_mandatory_trait_items);
if (candidates.size () == 0)
{
+ prev_segment->debug ();
rust_error_at (
seg->get_locus (),
"failed to resolve path segment using an impl Probe");
@@ -689,6 +696,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;
@@ -696,18 +704,48 @@ TypeCheckType::visit (HIR::ArrayType &type)
TyTy::BaseType *expected_ty = nullptr;
bool ok = context->lookup_builtin ("usize", &expected_ty);
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::BaseConstType *const_type = nullptr;
+ if (capacity_type->get_kind () == TyTy::TypeKind::CONST)
+ {
+ const_type = capacity_type->as_const_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_specified_type (),
+ type.get_size_expr ().get_locus ()),
+ type.get_size_expr ().get_locus ());
+ }
+ else
+ {
+ HirId size_id = type.get_size_expr ().get_mappings ().get_hirid ();
+ TyTy::BaseType *result
+ = unify_site (size_id, TyTy::TyWithLocation (expected_ty),
+ TyTy::TyWithLocation (capacity_type,
+ type.get_size_expr ().get_locus ()),
+ type.get_size_expr ().get_locus ());
+
+ if (result->is<TyTy::ErrorType> ())
+ const_type = new TyTy::ConstErrorType (expected_ty, size_id, size_id);
+ else
+ {
+ 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::ConstValueType (capacity_expr, expected_ty,
+ size_id, size_id);
+ context->insert_type (type.get_size_expr ().get_mappings (),
+ const_type->as_base_type ());
+ }
+ }
+
+ translated
+ = new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (),
+ TyTy::TyVar (
+ const_type->as_base_type ()->get_ref ()),
+ TyTy::TyVar (element_type->get_ref ()));
}
void
@@ -797,9 +835,10 @@ TypeCheckType::visit (HIR::ImplTraitType &type)
}
TyTy::ParamType *
-TypeResolveGenericParam::Resolve (HIR::GenericParam &param, bool apply_sized)
+TypeResolveGenericParam::Resolve (HIR::GenericParam &param,
+ bool resolve_trait_bounds, bool apply_sized)
{
- TypeResolveGenericParam resolver (apply_sized);
+ TypeResolveGenericParam resolver (apply_sized, resolve_trait_bounds);
switch (param.get_kind ())
{
case HIR::GenericParam::GenericKind::TYPE:
@@ -818,6 +857,14 @@ TypeResolveGenericParam::Resolve (HIR::GenericParam &param, bool apply_sized)
}
void
+TypeResolveGenericParam::ApplyAnyTraitBounds (HIR::TypeParam &param,
+ TyTy::ParamType *pty)
+{
+ TypeResolveGenericParam resolver (true, true);
+ resolver.apply_trait_bounds (param, pty);
+}
+
+void
TypeResolveGenericParam::visit (HIR::LifetimeParam &param)
{
// nothing to do
@@ -835,6 +882,18 @@ 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 (), {});
+
+ if (resolve_trait_bounds)
+ apply_trait_bounds (param, resolved);
+}
+
+void
+TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam &param,
+ TyTy::ParamType *pty)
+{
std::unique_ptr<HIR::Type> implicit_self_bound = nullptr;
if (param.has_type_param_bounds ())
{
@@ -844,7 +903,7 @@ TypeResolveGenericParam::visit (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);
@@ -865,8 +924,6 @@ TypeResolveGenericParam::visit (HIR::TypeParam &param)
//
// We can only do this when we are not resolving the implicit Self for Sized
// itself
- rust_debug_loc (param.get_locus (), "apply_sized: %s",
- apply_sized ? "true" : "false");
if (apply_sized)
{
TyTy::TypeBoundPredicate sized_predicate
@@ -882,7 +939,8 @@ TypeResolveGenericParam::visit (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 (
@@ -894,7 +952,8 @@ TypeResolveGenericParam::visit (HIR::TypeParam &param)
{
switch (predicate.get_polarity ())
{
- case BoundPolarity::AntiBound: {
+ case BoundPolarity::AntiBound:
+ {
bool found = predicates.find (predicate.get_id ())
!= predicates.end ();
if (found)
@@ -911,7 +970,8 @@ TypeResolveGenericParam::visit (HIR::TypeParam &param)
}
break;
- default: {
+ default:
+ {
if (predicates.find (predicate.get_id ())
== predicates.end ())
{
@@ -941,10 +1001,8 @@ TypeResolveGenericParam::visit (HIR::TypeParam &param)
}
}
- resolved = new TyTy::ParamType (param.get_type_representation ().as_string (),
- param.get_locus (),
- param.get_mappings ().get_hirid (), param,
- specified_bounds);
+ // inherit them
+ pty->inherit_bounds (specified_bounds);
}
void
@@ -1009,7 +1067,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
@@ -1018,7 +1077,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 ());
@@ -1047,23 +1107,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-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h
index fc272e6..cc991b6 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -91,20 +91,27 @@ class TypeResolveGenericParam : public TypeCheckBase
{
public:
static TyTy::ParamType *Resolve (HIR::GenericParam &param,
+ bool resolve_trait_bounds = true,
bool apply_sized = true);
+ static void ApplyAnyTraitBounds (HIR::TypeParam &param, TyTy::ParamType *pty);
+
protected:
void visit (HIR::TypeParam &param);
void visit (HIR::LifetimeParam &param);
void visit (HIR::ConstGenericParam &param);
+ void apply_trait_bounds (HIR::TypeParam &param, TyTy::ParamType *pty);
+
private:
- TypeResolveGenericParam (bool apply_sized)
- : TypeCheckBase (), resolved (nullptr), apply_sized (apply_sized)
+ TypeResolveGenericParam (bool apply_sized, bool resolve_trait_bounds)
+ : TypeCheckBase (), resolved (nullptr), apply_sized (apply_sized),
+ resolve_trait_bounds (resolve_trait_bounds)
{}
TyTy::ParamType *resolved;
bool apply_sized;
+ bool resolve_trait_bounds;
};
class ResolveWhereClauseItem : public TypeCheckBase
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index a198ad3..3215f434 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,36 +161,11 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
HIR::TraitFunctionDecl &function = fn.get_decl ();
if (function.has_generics ())
{
- for (auto &generic_param : function.get_generic_params ())
- {
- switch (generic_param.get ()->get_kind ())
- {
- case HIR::GenericParam::GenericKind::LIFETIME: {
- auto lifetime_param
- = static_cast<HIR::LifetimeParam &> (*generic_param);
-
- context->intern_and_insert_lifetime (
- lifetime_param.get_lifetime ());
- // TODO: Handle lifetime bounds
- }
- break;
- case HIR::GenericParam::GenericKind::CONST:
- // FIXME: Skipping Lifetime and Const completely until better
- // handling.
- break;
-
- case HIR::GenericParam::GenericKind::TYPE: {
- auto param_type
- = TypeResolveGenericParam::Resolve (*generic_param);
- context->insert_type (generic_param->get_mappings (),
- param_type);
-
- substitutions.push_back (TyTy::SubstitutionParamMapping (
- static_cast<HIR::TypeParam &> (*generic_param), param_type));
- }
- break;
- }
- }
+ TypeCheckBase::ResolveGenericParams (HIR::Item::ItemKind::Function,
+ fn.get_locus (),
+ function.get_generic_params (),
+ substitutions, false /*is_foreign*/,
+ ABI::RUST);
}
if (function.has_where_clause ())
@@ -235,7 +206,7 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
// add the synthetic self param at the front, this is a placeholder
// for compilation to know parameter names. The types are ignored
// but we reuse the HIR identifier pattern which requires it
- HIR::SelfParam &self_param = function.get_self ();
+ HIR::SelfParam &self_param = function.get_self_unchecked ();
std::unique_ptr<HIR::Pattern> self_pattern
= std::make_unique<HIR::IdentifierPattern> (HIR::IdentifierPattern (
mapping, {"self"}, self_param.get_locus (), self_param.is_ref (),
@@ -258,26 +229,28 @@ 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
: Mutability::Mut;
rust_assert (self_param.has_lifetime ());
+ auto region = TyTy::Region::make_anonymous ();
auto maybe_region = context->lookup_and_resolve_lifetime (
self_param.get_lifetime ());
-
- if (!maybe_region.has_value ())
+ if (maybe_region.has_value ())
+ region = maybe_region.value ();
+ else
{
rust_error_at (self_param.get_locus (),
"failed to resolve lifetime");
- return get_error ();
}
+
self_type = new TyTy::ReferenceType (
self_param.get_mappings ().get_hirid (),
- TyTy::TyVar (self->get_ref ()), mutability,
- maybe_region.value ());
+ TyTy::TyVar (self->get_ref ()), mutability, region);
}
break;
@@ -288,7 +261,7 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
}
context->insert_type (self_param.get_mappings (), self_type);
- params.push_back (TyTy::FnParam (std::move (self_pattern), self_type));
+ params.emplace_back (std::move (self_pattern), self_type);
}
for (auto &param : function.get_function_params ())
@@ -298,30 +271,17 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
context->insert_type (param.get_mappings (), param_tyty);
TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
// FIXME: Should we take the name ? Use a shared pointer instead ?
- params.push_back (
- TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty));
+ params.emplace_back (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 212ab3f..238ede4 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.cc
+++ b/gcc/rust/typecheck/rust-substitution-mapper.cc
@@ -34,6 +34,15 @@ SubstMapper::Resolve (TyTy::BaseType *base, location_t locus,
HIR::GenericArgs *generics,
const std::vector<TyTy::Region> &regions)
{
+ if (!valid_type (base))
+ {
+ rich_location r (line_table, locus);
+ r.add_fixit_remove (generics->get_locus ());
+ rust_error_at (r, ErrorCode::E0109,
+ "generic arguments are not allowed for this type");
+ return base;
+ }
+
SubstMapper mapper (base->get_ref (), generics, regions, locus);
base->accept_vis (mapper);
rust_assert (mapper.resolved != nullptr);
@@ -47,6 +56,17 @@ SubstMapper::InferSubst (TyTy::BaseType *base, location_t locus)
}
bool
+SubstMapper::valid_type (TyTy::BaseType *base)
+{
+ bool is_fn = base->is<TyTy::FnType> ();
+ bool is_adt = base->is<TyTy::ADTType> ();
+ bool is_placeholder = base->is<TyTy::PlaceholderType> ();
+ bool is_projection = base->is<TyTy::ProjectionType> ();
+
+ return is_fn || is_adt || is_placeholder || is_projection;
+}
+
+bool
SubstMapper::have_generic_args () const
{
return generics != nullptr;
@@ -103,7 +123,12 @@ SubstMapper::visit (TyTy::ADTType &type)
void
SubstMapper::visit (TyTy::PlaceholderType &type)
{
- rust_assert (type.can_resolve ());
+ if (!type.can_resolve ())
+ {
+ resolved = &type;
+ return;
+ }
+
resolved = SubstMapper::Resolve (type.resolve (), locus, generics, regions);
}
@@ -243,6 +268,30 @@ SubstMapperInternal::visit (TyTy::ParamType &type)
}
void
+SubstMapperInternal::visit (TyTy::ConstParamType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
+SubstMapperInternal::visit (TyTy::ConstValueType &type)
+{
+ resolved = type.clone ();
+}
+
+void
+SubstMapperInternal::visit (TyTy::ConstInferType &type)
+{
+ resolved = type.clone ();
+}
+
+void
+SubstMapperInternal::visit (TyTy::ConstErrorType &type)
+{
+ resolved = type.clone ();
+}
+
+void
SubstMapperInternal::visit (TyTy::PlaceholderType &type)
{
rust_assert (type.can_resolve ());
@@ -279,15 +328,15 @@ SubstMapperInternal::visit (TyTy::SliceType &type)
{
resolved = type.handle_substitions (mappings);
}
-
-// nothing to do for these
void
-SubstMapperInternal::visit (TyTy::InferType &type)
+SubstMapperInternal::visit (TyTy::FnPtr &type)
{
- resolved = type.clone ();
+ resolved = type.handle_substitions (mappings);
}
+
+// nothing to do for these
void
-SubstMapperInternal::visit (TyTy::FnPtr &type)
+SubstMapperInternal::visit (TyTy::InferType &type)
{
resolved = type.clone ();
}
@@ -349,7 +398,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 bc54f56..98f9e72 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -37,6 +37,8 @@ public:
bool have_generic_args () const;
+ static bool valid_type (TyTy::BaseType *base);
+
void visit (TyTy::FnType &type) override;
void visit (TyTy::ADTType &type) override;
void visit (TyTy::PlaceholderType &type) override;
@@ -59,6 +61,10 @@ 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::ConstParamType &) override { rust_unreachable (); }
+ void visit (TyTy::ConstValueType &) override { rust_unreachable (); }
+ void visit (TyTy::ConstInferType &) override { rust_unreachable (); }
+ void visit (TyTy::ConstErrorType &) override { rust_unreachable (); }
void visit (TyTy::StrType &) override { rust_unreachable (); }
void visit (TyTy::NeverType &) override { rust_unreachable (); }
void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); }
@@ -90,6 +96,10 @@ public:
void visit (TyTy::ReferenceType &type) override;
void visit (TyTy::PointerType &type) override;
void visit (TyTy::ParamType &type) override;
+ void visit (TyTy::ConstParamType &type) override;
+ void visit (TyTy::ConstValueType &type) override;
+ void visit (TyTy::ConstInferType &type) override;
+ void visit (TyTy::ConstErrorType &type) override;
void visit (TyTy::PlaceholderType &type) override;
void visit (TyTy::ProjectionType &type) override;
void visit (TyTy::ClosureType &type) override;
@@ -143,12 +153,16 @@ 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::ConstParamType &) override { rust_unreachable (); }
+ void visit (TyTy::ConstValueType &) override { rust_unreachable (); }
+ void visit (TyTy::ConstInferType &) override { rust_unreachable (); }
+ void visit (TyTy::ConstErrorType &) override { rust_unreachable (); }
void visit (TyTy::StrType &) override { rust_unreachable (); }
void visit (TyTy::NeverType &) override { rust_unreachable (); }
void visit (TyTy::PlaceholderType &) override { rust_unreachable (); }
void visit (TyTy::ProjectionType &) override { rust_unreachable (); }
void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); }
- void visit (TyTy::OpaqueType &type) override { rust_unreachable (); }
+ void visit (TyTy::OpaqueType &) override { rust_unreachable (); }
private:
SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver);
@@ -183,12 +197,16 @@ public:
void visit (const TyTy::ReferenceType &) override {}
void visit (const TyTy::PointerType &) override {}
void visit (const TyTy::ParamType &) override {}
+ void visit (const TyTy::ConstParamType &) override {}
+ void visit (const TyTy::ConstValueType &) override {}
+ void visit (const TyTy::ConstInferType &) override {}
+ void visit (const TyTy::ConstErrorType &) 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 4abfbae..a6b9966 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -22,10 +22,14 @@
#include "rust-hir-type-check-implitem.h"
#include "rust-hir-type-check-item.h"
#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"
+#include "rust-immutable-name-resolution-context.h"
+#include "options.h"
namespace Rust {
namespace Resolver {
@@ -36,12 +40,12 @@ query_type (HirId reference, TyTy::BaseType **result)
auto &mappings = Analysis::Mappings::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
@@ -91,6 +95,34 @@ query_type (HirId reference, TyTy::BaseType **result)
HIR::ImplBlock *impl = impl_block_by_type.value ();
rust_debug_loc (impl->get_locus (), "resolved impl block type {%u} to",
reference);
+
+ // this could be recursive to the root type
+ if (impl->has_type ())
+ {
+ HIR::Type &ty = impl->get_type ();
+ NodeId ref_node_id = UNKNOWN_NODEID;
+ NodeId ast_node_id = ty.get_mappings ().get_nodeid ();
+
+ 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;
+ });
+
+ if (ref_node_id != UNKNOWN_NODEID)
+ {
+ tl::optional<HirId> hid
+ = mappings.lookup_node_to_hir (ref_node_id);
+ if (hid.has_value () && context->query_in_progress (hid.value ()))
+ {
+ context->query_completed (reference);
+ return false;
+ }
+ }
+ }
+
*result = TypeCheckItem::ResolveImplBlockSelf (*impl);
context->query_completed (reference);
return true;
@@ -120,11 +152,12 @@ query_type (HirId reference, TyTy::BaseType **result)
bool
types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- location_t unify_locus, bool emit_errors)
+ location_t unify_locus, bool emit_errors, bool check_bounds)
{
TyTy::BaseType *result
= unify_site_and (UNKNOWN_HIRID, lhs, rhs, unify_locus, emit_errors,
- false /*commit*/, true /*infer*/, true /*cleanup*/);
+ false /*commit*/, true /*infer*/, true /*cleanup*/,
+ check_bounds);
return result->get_kind () != TyTy::TypeKind::ERROR;
}
@@ -141,31 +174,44 @@ unify_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
std::vector<UnifyRules::CommitSite> commits;
std::vector<UnifyRules::InferenceSite> infers;
return UnifyRules::Resolve (lhs, rhs, unify_locus, true /*commit*/,
- true /*emit_error*/, false /*infer*/, commits,
- infers);
+ true /*emit_error*/, false /*infer*/,
+ true /*check_bounds*/, commits, infers);
}
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)
+ bool implicit_infer_vars, bool cleanup, bool check_bounds)
{
TypeCheckContext &context = *TypeCheckContext::get ();
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 check_bounds %s "
+ "id={%u} expected={%s} expr={%s}",
+ commit_if_ok ? "true" : "false",
+ implicit_infer_vars ? "true" : "false",
+ check_bounds ? "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;
TyTy::BaseType *result
= UnifyRules::Resolve (lhs, rhs, unify_locus, false /*commit inline*/,
- emit_errors, implicit_infer_vars, commits, infers);
+ emit_errors, implicit_infer_vars, check_bounds,
+ 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)
@@ -175,17 +221,18 @@ unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
}
else if (cleanup)
{
- // FIXME
- // reset the get_next_hir_id
-
for (auto &i : infers)
{
- i.param->set_ref (i.pref);
- i.param->set_ty_ref (i.ptyref);
+ if (i.param != nullptr)
+ {
+ i.param->set_ref (i.pref);
+ i.param->set_ty_ref (i.ptyref);
+ }
// remove the inference variable
context.clear_type (i.infer);
- delete i.infer;
+ // FIXME: Don't delete - result might point to this
+ // delete i.infer;
}
}
return result;
@@ -282,7 +329,7 @@ cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to,
AssociatedImplTrait *
lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound,
- const TyTy::BaseType *binding, bool *ambigious)
+ TyTy::BaseType *binding, bool *ambigious)
{
auto context = TypeCheckContext::get ();
diff --git a/gcc/rust/typecheck/rust-type-util.h b/gcc/rust/typecheck/rust-type-util.h
index 03874a4..7f4a94e 100644
--- a/gcc/rust/typecheck/rust-type-util.h
+++ b/gcc/rust/typecheck/rust-type-util.h
@@ -25,37 +25,35 @@
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,
+ bool check_bounds = true);
-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, bool check_bounds = true);
-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,
- const TyTy::BaseType *binding,
+ TyTy::BaseType *binding,
bool *ambigious = nullptr);
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc
index f02e484..3419ef6 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 {
@@ -153,7 +154,7 @@ void
TypeCheckContext::push_return_type (TypeCheckContextItem item,
TyTy::BaseType *return_type)
{
- return_type_stack.push_back ({std::move (item), return_type});
+ return_type_stack.emplace_back (std::move (item), return_type);
}
void
@@ -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 ())
@@ -308,12 +310,13 @@ TypeCheckContext::insert_associated_impl_mapping (
associated_traits_to_impls[trait_id] = {};
}
- associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id});
+ associated_traits_to_impls[trait_id].emplace_back (impl_type, impl_id);
}
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;
@@ -514,7 +551,16 @@ TypeCheckContext::lookup_lifetime (const HIR::Lifetime &lifetime) const
{
if (lifetime.get_lifetime_type () == AST::Lifetime::NAMED)
{
- rust_assert (lifetime.get_name () != "static");
+ if (lifetime.get_name () == "static")
+ {
+ rich_location r (line_table, lifetime.get_locus ());
+ r.add_fixit_insert_after (lifetime.get_locus (),
+ "static is a reserved lifetime name");
+ rust_error_at (r, ErrorCode::E0262,
+ "invalid lifetime parameter name: %qs",
+ lifetime.get_name ().c_str ());
+ return tl::nullopt;
+ }
const auto name = lifetime.get_name ();
auto it = lifetime_name_interner.find (name);
if (it == lifetime_name_interner.end ())
@@ -565,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..a59de99 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -26,12 +26,12 @@
namespace Rust {
namespace Resolver {
-TypeBoundsProbe::TypeBoundsProbe (const TyTy::BaseType *receiver)
+TypeBoundsProbe::TypeBoundsProbe (TyTy::BaseType *receiver)
: TypeCheckBase (), receiver (receiver)
{}
std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
-TypeBoundsProbe::Probe (const TyTy::BaseType *receiver)
+TypeBoundsProbe::Probe (TyTy::BaseType *receiver)
{
TypeBoundsProbe probe (receiver);
probe.scan ();
@@ -61,6 +61,35 @@ 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;
+
+ 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 (!types_compatable (TyTy::TyWithLocation (receiver),
+ TyTy::TyWithLocation (impl_type), impl->get_locus (),
+ false /*emit_errors*/, false /*check-bounds*/))
+ return true;
+
+ possible_trait_paths.emplace_back (&impl->get_trait_ref (), impl);
+ return true;
+}
+
void
TypeBoundsProbe::scan ()
{
@@ -68,31 +97,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)
@@ -101,11 +106,11 @@ TypeBoundsProbe::scan ()
TraitReference *trait_ref = TraitResolver::Resolve (*trait_path);
if (!trait_ref->is_error ())
- trait_references.push_back ({trait_ref, path.second});
+ trait_references.emplace_back (trait_ref, path.second);
}
// marker traits...
- assemble_sized_builtin ();
+ assemble_marker_builtins ();
// add auto trait bounds
for (auto *auto_trait : mappings.get_auto_traits ())
@@ -113,7 +118,7 @@ TypeBoundsProbe::scan ()
}
void
-TypeBoundsProbe::assemble_sized_builtin ()
+TypeBoundsProbe::assemble_marker_builtins ()
{
const TyTy::BaseType *raw = receiver->destructure ();
@@ -132,7 +137,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 +144,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 +152,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 +169,7 @@ TypeBoundsProbe::assemble_sized_builtin ()
assemble_builtin_candidate (LangItem::Kind::SIZED);
break;
+ case TyTy::CONST:
case TyTy::DYNAMIC:
case TyTy::ERROR:
break;
@@ -169,7 +181,7 @@ TypeBoundsProbe::add_trait_bound (HIR::Trait *trait)
{
auto trait_ref = TraitResolver::Resolve (*trait);
- trait_references.push_back ({trait_ref, mappings.lookup_builtin_marker ()});
+ trait_references.emplace_back (trait_ref, mappings.lookup_builtin_marker ());
}
void
@@ -206,7 +218,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 +238,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 +264,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 ();
@@ -288,11 +302,9 @@ TypeCheckBase::get_predicate_from_bound (
std::vector<HIR::GenericArgsBinding> bindings;
location_t output_locus = fn.get_return_type ().get_locus ();
- HIR::GenericArgsBinding binding (Identifier (
- trait_item->trait_identifier ()),
- fn.get_return_type ().clone_type (),
- output_locus);
- bindings.push_back (std::move (binding));
+ bindings.emplace_back (Identifier (trait_item->trait_identifier ()),
+ fn.get_return_type ().clone_type (),
+ output_locus);
args = HIR::GenericArgs ({} /* lifetimes */,
std::move (inputs) /* type_args*/,
@@ -327,7 +339,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 (),
@@ -449,8 +462,8 @@ TypeBoundPredicate::operator= (const TypeBoundPredicate &other)
{
TyTy::BaseType *argument
= m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone ();
- SubstitutionArg c (&substitutions.at (i++), argument);
- copied_arg_mappings.push_back (std::move (c));
+
+ copied_arg_mappings.emplace_back (&substitutions.at (i++), argument);
}
used_arguments
@@ -508,7 +521,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 +543,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
@@ -554,10 +571,13 @@ TypeBoundPredicate::apply_argument_mappings (
std::string identifier = it.first;
TyTy::BaseType *type = it.second;
- TypeBoundPredicateItem item = lookup_associated_item (identifier);
- rust_assert (!item.is_error ());
+ tl::optional<TypeBoundPredicateItem> item
+ = lookup_associated_item (identifier);
+
+ if (!item.has_value ())
+ continue;
- const auto item_ref = item.get_raw_item ();
+ const auto item_ref = item->get_raw_item ();
item_ref->associated_type_set (type);
}
@@ -566,7 +586,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);
}
}
@@ -578,7 +598,7 @@ TypeBoundPredicate::contains_item (const std::string &search) const
return trait_ref->lookup_trait_item (search, &trait_item_ref);
}
-TypeBoundPredicateItem
+tl::optional<TypeBoundPredicateItem>
TypeBoundPredicate::lookup_associated_item (const std::string &search) const
{
auto trait_ref = get ();
@@ -590,11 +610,11 @@ TypeBoundPredicate::lookup_associated_item (const std::string &search) const
for (auto &super_trait : super_traits)
{
auto lookup = super_trait.lookup_associated_item (search);
- if (!lookup.is_error ())
+ if (lookup.has_value ())
return lookup;
}
- return TypeBoundPredicateItem::error ();
+ return tl::nullopt;
}
TypeBoundPredicateItem::TypeBoundPredicateItem (
@@ -635,7 +655,7 @@ TypeBoundPredicateItem::get_parent () const
return &parent;
}
-TypeBoundPredicateItem
+tl::optional<TypeBoundPredicateItem>
TypeBoundPredicate::lookup_associated_item (
const Resolver::TraitItemReference *ref) const
{
@@ -668,8 +688,7 @@ TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
TyTy::BaseType *argument
= is_implicit_self ? receiver->clone () : mapping.get_tyty ();
- SubstitutionArg arg (mapping.get_param_mapping (), argument);
- adjusted_mappings.push_back (std::move (arg));
+ adjusted_mappings.emplace_back (mapping.get_param_mapping (), argument);
}
SubstitutionArgumentMappings adjusted (adjusted_mappings, {},
@@ -699,7 +718,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);
@@ -712,10 +731,11 @@ TypeBoundPredicate::handle_substitions (
std::string identifier = it.first;
TyTy::BaseType *type = it.second;
- TypeBoundPredicateItem item = lookup_associated_item (identifier);
- if (!item.is_error ())
+ tl::optional<TypeBoundPredicateItem> item
+ = lookup_associated_item (identifier);
+ if (item.has_value ())
{
- const auto item_ref = item.get_raw_item ();
+ const auto item_ref = item->get_raw_item ();
item_ref->associated_type_set (type);
}
}
@@ -746,33 +766,51 @@ 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
TypeBoundPredicate::lookup_associated_type (const std::string &search)
{
- TypeBoundPredicateItem item = lookup_associated_item (search);
+ tl::optional<TypeBoundPredicateItem> item = lookup_associated_item (search);
// only need to check that it is infact an associated type because other
// wise if it was not found it will just be an error node anyway
- if (!item.is_error ())
+ if (item.has_value ())
{
- const auto raw = item.get_raw_item ();
+ const auto raw = item->get_raw_item ();
if (raw->get_trait_item_type ()
!= Resolver::TraitItemReference::TraitItemType::TYPE)
return TypeBoundPredicateItem::error ();
}
- return item;
+ return item.value ();
}
std::vector<TypeBoundPredicateItem>
@@ -786,10 +824,7 @@ TypeBoundPredicate::get_associated_type_items ()
= trait_item.get_trait_item_type ()
== Resolver::TraitItemReference::TraitItemType::TYPE;
if (is_associated_type)
- {
- TypeBoundPredicateItem item (*this, &trait_item);
- items.push_back (std::move (item));
- }
+ items.emplace_back (*this, &trait_item);
}
return items;
}
@@ -808,21 +843,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-bounds.h b/gcc/rust/typecheck/rust-tyty-bounds.h
deleted file mode 100644
index 6392af1..0000000
--- a/gcc/rust/typecheck/rust-tyty-bounds.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_TYTY_BOUNDS_H
-#define RUST_TYTY_BOUNDS_H
-
-#include "rust-location.h"
-#include "rust-mapping-common.h"
-
-namespace Rust {
-
-namespace Resolver {
-class TraitReference;
-class TraitItemReference;
-class AssociatedImplTrait;
-} // namespace Resolver
-
-namespace TyTy {
-
-class BaseType;
-class TypeBoundPredicate;
-class TypeBoundsMappings
-{
-protected:
- TypeBoundsMappings (std::vector<TypeBoundPredicate> specified_bounds);
-
-public:
- std::vector<TypeBoundPredicate> &get_specified_bounds ();
-
- const std::vector<TypeBoundPredicate> &get_specified_bounds () const;
-
- TypeBoundPredicate lookup_predicate (DefId id);
-
- size_t num_specified_bounds () const;
-
- std::string raw_bounds_as_string () const;
-
- std::string bounds_as_string () const;
-
- std::string raw_bounds_as_name () const;
-
-protected:
- void add_bound (TypeBoundPredicate predicate);
-
- std::vector<TypeBoundPredicate> specified_bounds;
-};
-
-} // namespace TyTy
-} // namespace Rust
-
-#endif // RUST_TYTY_BOUNDS_H
diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc
index 2e0830e..e82e618 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -59,7 +59,7 @@ TypeCheckCallExpr::visit (ADTType &type)
if (variant.get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
{
rust_error_at (
- call.get_locus (), ErrorCode::E0423,
+ call.get_locus (), ErrorCode::E0618,
"expected function, tuple struct or tuple variant, found struct %qs",
type.get_name ().c_str ());
return;
@@ -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
@@ -322,8 +327,8 @@ TypeCheckMethodCallExpr::go (FnType *ref, HIR::MethodCallExpr &call,
return new ErrorType (ref->get_ref ());
}
- Argument a (arg->get_mappings (), argument_expr_tyty, arg->get_locus ());
- args.push_back (std::move (a));
+ args.emplace_back (arg->get_mappings (), argument_expr_tyty,
+ arg->get_locus ());
}
TypeCheckMethodCallExpr checker (call.get_mappings (), args,
diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h
index c42fdcd..025a1ad 100644
--- a/gcc/rust/typecheck/rust-tyty-call.h
+++ b/gcc/rust/typecheck/rust-tyty-call.h
@@ -60,8 +60,12 @@ public:
void visit (PlaceholderType &) override { rust_unreachable (); }
void visit (ProjectionType &) override { rust_unreachable (); }
void visit (DynamicObjectType &) override { rust_unreachable (); }
- void visit (ClosureType &type) override { rust_unreachable (); }
- void visit (OpaqueType &type) override { rust_unreachable (); }
+ void visit (ClosureType &) override { rust_unreachable (); }
+ void visit (OpaqueType &) override { rust_unreachable (); }
+ void visit (ConstParamType &) override { rust_unreachable (); }
+ void visit (ConstValueType &) override { rust_unreachable (); }
+ void visit (ConstInferType &) override { rust_unreachable (); }
+ void visit (ConstErrorType &) 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
deleted file mode 100644
index c897c13..0000000
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ /dev/null
@@ -1,1610 +0,0 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_TYTY_CMP_H
-#define RUST_TYTY_CMP_H
-
-#include "rust-diagnostics.h"
-#include "rust-tyty.h"
-#include "rust-tyty-visitor.h"
-#include "rust-hir-map.h"
-#include "rust-hir-type-check.h"
-
-namespace Rust {
-namespace TyTy {
-
-class BaseCmp : public TyConstVisitor
-{
-public:
- virtual bool can_eq (const BaseType *other)
- {
- if (other->get_kind () == TypeKind::PARAM)
- {
- const ParamType *p = static_cast<const ParamType *> (other);
- other = p->resolve ();
- }
- if (other->get_kind () == TypeKind::PLACEHOLDER)
- {
- const PlaceholderType *p = static_cast<const PlaceholderType *> (other);
- if (p->can_resolve ())
- {
- other = p->resolve ();
- }
- }
- if (other->get_kind () == TypeKind::PROJECTION)
- {
- const ProjectionType *p = static_cast<const ProjectionType *> (other);
- other = p->get ();
- }
-
- other->accept_vis (*this);
- return ok;
- }
-
- virtual void visit (const TupleType &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 ());
- }
- }
-
- virtual void visit (const ADTType &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 ());
- }
- }
-
- virtual void visit (const InferType &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 ());
- }
- }
-
- virtual void visit (const FnType &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 ());
- }
- }
-
- virtual void visit (const FnPtr &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 ());
- }
- }
-
- virtual void visit (const ArrayType &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 ());
- }
- }
-
- virtual void visit (const SliceType &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 ());
- }
- }
-
- virtual void visit (const BoolType &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 ());
- }
- }
-
- virtual void visit (const IntType &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 ());
- }
- }
-
- virtual void visit (const UintType &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 ());
- }
- }
-
- virtual void visit (const USizeType &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 ());
- }
- }
-
- virtual void visit (const ISizeType &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 ());
- }
- }
-
- virtual void visit (const FloatType &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 ());
- }
- }
-
- virtual void visit (const ErrorType &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 ());
- }
- }
-
- virtual void visit (const CharType &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 ());
- }
- }
-
- virtual void visit (const ReferenceType &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 ());
- }
- }
-
- virtual void visit (const PointerType &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 ());
- }
- }
-
- virtual void visit (const StrType &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 ());
- }
- }
-
- virtual void visit (const NeverType &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 ());
- }
- }
-
- virtual void visit (const ProjectionType &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 ());
- }
- }
-
- virtual void visit (const PlaceholderType &type) override
- {
- // it is ok for types to can eq to a placeholder
- ok = true;
- }
-
- virtual void visit (const ParamType &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 ());
- }
- }
-
- virtual void visit (const DynamicObjectType &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 ());
- }
- }
-
- virtual void visit (const ClosureType &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 ());
- }
- }
-
- virtual void visit (const OpaqueType &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 ()),
- context (Resolver::TypeCheckContext::get ()), ok (false),
- emit_error_flag (emit_errors)
- {}
-
- Analysis::Mappings &mappings;
- Resolver::TypeCheckContext *context;
-
- bool ok;
- bool emit_error_flag;
-
-private:
- /* Returns a pointer to the ty that created this rule. */
- virtual const BaseType *get_base () const = 0;
-};
-
-class InferCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- InferCmp (const InferType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const BoolType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const IntType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const UintType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const USizeType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const ISizeType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const FloatType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const ArrayType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const SliceType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const ADTType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const TupleType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const InferType &type) override
- {
- switch (base->get_infer_kind ())
- {
- case InferType::InferTypeKind::GENERAL:
- ok = true;
- return;
-
- case InferType::InferTypeKind::INTEGRAL: {
- if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
- {
- ok = true;
- return;
- }
- else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
- {
- ok = true;
- return;
- }
- }
- break;
-
- case InferType::InferTypeKind::FLOAT: {
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- ok = true;
- return;
- }
- else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
- {
- ok = true;
- return;
- }
- }
- break;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const CharType &type) override
- {
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
- }
-
- void visit (const ReferenceType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const PointerType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const ParamType &) override { ok = true; }
-
- void visit (const DynamicObjectType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
- void visit (const ClosureType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- ok = true;
- return;
- }
-
- BaseCmp::visit (type);
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const InferType *base;
-};
-
-class FnCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- FnCmp (const FnType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const InferType &type) override
- {
- ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL;
- }
-
- void visit (const FnType &type) override
- {
- if (base->num_params () != type.num_params ())
- {
- BaseCmp::visit (type);
- return;
- }
-
- for (size_t i = 0; i < base->num_params (); i++)
- {
- auto a = base->param_at (i).get_type ();
- auto b = type.param_at (i).get_type ();
-
- if (!a->can_eq (b, emit_error_flag))
- {
- emit_error_flag = false;
- BaseCmp::visit (type);
- return;
- }
- }
-
- if (!base->get_return_type ()->can_eq (type.get_return_type (),
- emit_error_flag))
- {
- emit_error_flag = false;
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const FnType *base;
-};
-
-class FnptrCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- FnptrCmp (const FnPtr *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
- void visit (const FnPtr &type) override
- {
- if (base->num_params () != type.num_params ())
- {
- BaseCmp::visit (type);
- return;
- }
-
- auto this_ret_type = base->get_return_type ();
- auto other_ret_type = type.get_return_type ();
- if (!this_ret_type->can_eq (other_ret_type, emit_error_flag))
- {
- BaseCmp::visit (type);
- return;
- }
-
- for (size_t i = 0; i < base->num_params (); i++)
- {
- auto this_param = base->get_param_type_at (i);
- auto other_param = type.get_param_type_at (i);
- if (!this_param->can_eq (other_param, emit_error_flag))
- {
- BaseCmp::visit (type);
- return;
- }
- }
-
- ok = true;
- }
-
- void visit (const FnType &type) override
- {
- if (base->num_params () != type.num_params ())
- {
- BaseCmp::visit (type);
- return;
- }
-
- auto this_ret_type = base->get_return_type ();
- auto other_ret_type = type.get_return_type ();
- if (!this_ret_type->can_eq (other_ret_type, emit_error_flag))
- {
- BaseCmp::visit (type);
- return;
- }
-
- for (size_t i = 0; i < base->num_params (); i++)
- {
- auto this_param = base->get_param_type_at (i);
- auto other_param = type.param_at (i).get_type ();
- if (!this_param->can_eq (other_param, emit_error_flag))
- {
- BaseCmp::visit (type);
- return;
- }
- }
-
- ok = true;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const FnPtr *base;
-};
-
-class ClosureCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- ClosureCmp (const ClosureType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
- void visit (const ClosureType &type) override
- {
- if (base->get_def_id () != type.get_def_id ())
- {
- BaseCmp::visit (type);
- return;
- }
-
- if (!base->get_parameters ().can_eq (&type.get_parameters (), false))
- {
- BaseCmp::visit (type);
- return;
- }
-
- if (!base->get_result_type ().can_eq (&type.get_result_type (), false))
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const ClosureType *base;
-};
-
-class ArrayCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- ArrayCmp (const ArrayType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const ArrayType &type) override
- {
- // check base type
- const BaseType *base_element = base->get_element_type ();
- const BaseType *other_element = type.get_element_type ();
- if (!base_element->can_eq (other_element, emit_error_flag))
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
- void visit (const InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const ArrayType *base;
-};
-
-class SliceCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- SliceCmp (const SliceType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const SliceType &type) override
- {
- // check base type
- const BaseType *base_element = base->get_element_type ();
- const BaseType *other_element = type.get_element_type ();
- if (!base_element->can_eq (other_element, emit_error_flag))
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
- void visit (const InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const SliceType *base;
-};
-
-class BoolCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- BoolCmp (const BoolType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const BoolType &type) override { ok = true; }
-
- void visit (const InferType &type) override
- {
- ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const BoolType *base;
-};
-
-class IntCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- IntCmp (const IntType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const InferType &type) override
- {
- ok = type.get_infer_kind () != InferType::InferTypeKind::FLOAT;
- }
-
- void visit (const IntType &type) override
- {
- ok = type.get_int_kind () == base->get_int_kind ();
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const IntType *base;
-};
-
-class UintCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- UintCmp (const UintType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const InferType &type) override
- {
- ok = type.get_infer_kind () != InferType::InferTypeKind::FLOAT;
- }
-
- void visit (const UintType &type) override
- {
- ok = type.get_uint_kind () == base->get_uint_kind ();
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const UintType *base;
-};
-
-class FloatCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- FloatCmp (const FloatType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const InferType &type) override
- {
- ok = type.get_infer_kind () != InferType::InferTypeKind::INTEGRAL;
- }
-
- void visit (const FloatType &type) override
- {
- ok = type.get_float_kind () == base->get_float_kind ();
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const FloatType *base;
-};
-
-class ADTCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- ADTCmp (const ADTType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const ADTType &type) override
- {
- if (base->get_adt_kind () != type.get_adt_kind ())
- {
- BaseCmp::visit (type);
- return;
- }
-
- if (base->get_identifier ().compare (type.get_identifier ()) != 0)
- {
- BaseCmp::visit (type);
- return;
- }
-
- if (base->number_of_variants () != type.number_of_variants ())
- {
- BaseCmp::visit (type);
- return;
- }
-
- for (size_t i = 0; i < type.number_of_variants (); ++i)
- {
- TyTy::VariantDef *a = base->get_variants ().at (i);
- TyTy::VariantDef *b = type.get_variants ().at (i);
-
- if (a->num_fields () != b->num_fields ())
- {
- BaseCmp::visit (type);
- return;
- }
-
- for (size_t j = 0; j < a->num_fields (); j++)
- {
- TyTy::StructFieldType *base_field = a->get_field_at_index (j);
- TyTy::StructFieldType *other_field = b->get_field_at_index (j);
-
- TyTy::BaseType *this_field_ty = base_field->get_field_type ();
- TyTy::BaseType *other_field_ty = other_field->get_field_type ();
-
- if (!this_field_ty->can_eq (other_field_ty, emit_error_flag))
- {
- BaseCmp::visit (type);
- return;
- }
- }
- }
-
- ok = true;
- }
-
- void visit (const InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const ADTType *base;
-};
-
-class TupleCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- TupleCmp (const TupleType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const TupleType &type) override
- {
- if (base->num_fields () != type.num_fields ())
- {
- BaseCmp::visit (type);
- return;
- }
-
- for (size_t i = 0; i < base->num_fields (); i++)
- {
- BaseType *bo = base->get_field (i);
- BaseType *fo = type.get_field (i);
-
- if (!bo->can_eq (fo, emit_error_flag))
- {
- BaseCmp::visit (type);
- return;
- }
- }
-
- ok = true;
- }
-
- void visit (const InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const TupleType *base;
-};
-
-class USizeCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- USizeCmp (const USizeType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const InferType &type) override
- {
- ok = type.get_infer_kind () != InferType::InferTypeKind::FLOAT;
- }
-
- void visit (const USizeType &type) override { ok = true; }
-
-private:
- const BaseType *get_base () const override { return base; }
- const USizeType *base;
-};
-
-class ISizeCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- ISizeCmp (const ISizeType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const InferType &type) override
- {
- ok = type.get_infer_kind () != InferType::InferTypeKind::FLOAT;
- }
-
- void visit (const ISizeType &type) override { ok = true; }
-
-private:
- const BaseType *get_base () const override { return base; }
- const ISizeType *base;
-};
-
-class CharCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- CharCmp (const CharType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const InferType &type) override
- {
- ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL;
- }
-
- void visit (const CharType &type) override { ok = true; }
-
-private:
- const BaseType *get_base () const override { return base; }
- const CharType *base;
-};
-
-class ReferenceCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- ReferenceCmp (const ReferenceType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const ReferenceType &type) override
- {
- auto base_type = base->get_base ();
- auto other_base_type = type.get_base ();
-
- bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
- if (!mutability_ok)
- {
- BaseCmp::visit (type);
- return;
- }
-
- if (!base_type->can_eq (other_base_type, emit_error_flag))
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
- void visit (const InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const ReferenceType *base;
-};
-
-class PointerCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- PointerCmp (const PointerType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const PointerType &type) override
- {
- auto base_type = base->get_base ();
- auto other_base_type = type.get_base ();
-
- bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
- if (!mutability_ok)
- {
- BaseCmp::visit (type);
- return;
- }
-
- if (!base_type->can_eq (other_base_type, emit_error_flag))
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
- void visit (const InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const PointerType *base;
-};
-
-class ParamCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- ParamCmp (const ParamType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- // param types are a placeholder we shouldn't have cases where we unify
- // against it. eg: struct foo<T> { a: T }; When we invoke it we can do either:
- //
- // foo<i32>{ a: 123 }.
- // Then this enforces the i32 type to be referenced on the
- // field via an hirid.
- //
- // rust also allows for a = foo{a:123}; Where we can use an Inference Variable
- // to handle the typing of the struct
- bool can_eq (const BaseType *other) override
- {
- if (!base->can_resolve ())
- return BaseCmp::can_eq (other);
-
- auto lookup = base->resolve ();
- return lookup->can_eq (other, emit_error_flag);
- }
-
- // imagine the case where we have:
- // struct Foo<T>(T);
- // Then we declare a generic impl block
- // impl <X>Foo<X> { ... }
- // both of these types are compatible so we mostly care about the number of
- // generic arguments
- void visit (const ParamType &) override { ok = true; }
-
- void visit (const TupleType &) override { ok = true; }
-
- void visit (const InferType &) override { ok = true; }
-
- void visit (const FnType &) override { ok = true; }
-
- void visit (const FnPtr &) override { ok = true; }
-
- void visit (const ADTType &) override { ok = true; }
-
- void visit (const ArrayType &) override { ok = true; }
-
- void visit (const SliceType &) override { ok = true; }
-
- void visit (const BoolType &) override { ok = true; }
-
- void visit (const IntType &) override { ok = true; }
-
- void visit (const UintType &) override { ok = true; }
-
- void visit (const USizeType &) override { ok = true; }
-
- void visit (const ISizeType &) override { ok = true; }
-
- void visit (const FloatType &) override { ok = true; }
-
- void visit (const CharType &) override { ok = true; }
-
- void visit (const ReferenceType &) override { ok = true; }
-
- void visit (const PointerType &) override { ok = true; }
-
- void visit (const StrType &) override { ok = true; }
-
- void visit (const NeverType &) override { ok = true; }
-
- void visit (const DynamicObjectType &) override { ok = true; }
-
- void visit (const PlaceholderType &type) override
- {
- ok = base->get_symbol ().compare (type.get_symbol ()) == 0;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const ParamType *base;
-};
-
-class StrCmp : public BaseCmp
-{
- // FIXME we will need a enum for the StrType like ByteBuf etc..
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- StrCmp (const StrType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const StrType &type) override { ok = true; }
-
- void visit (const InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const StrType *base;
-};
-
-class NeverCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- NeverCmp (const NeverType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const NeverType &type) override { ok = true; }
-
- void visit (const InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCmp::visit (type);
- return;
- }
-
- ok = true;
- }
-
-private:
- const BaseType *get_base () const override { return base; }
- const NeverType *base;
-};
-
-class PlaceholderCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- PlaceholderCmp (const PlaceholderType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- bool can_eq (const BaseType *other) override
- {
- if (!base->can_resolve ())
- return BaseCmp::can_eq (other);
-
- BaseType *lookup = base->resolve ();
- return lookup->can_eq (other, emit_error_flag);
- }
-
- void visit (const TupleType &) override { ok = true; }
-
- void visit (const ADTType &) override { ok = true; }
-
- void visit (const InferType &) override { ok = true; }
-
- void visit (const FnType &) override { ok = true; }
-
- void visit (const FnPtr &) override { ok = true; }
-
- void visit (const ArrayType &) override { ok = true; }
-
- void visit (const BoolType &) override { ok = true; }
-
- void visit (const IntType &) override { ok = true; }
-
- void visit (const UintType &) override { ok = true; }
-
- void visit (const USizeType &) override { ok = true; }
-
- void visit (const ISizeType &) override { ok = true; }
-
- void visit (const FloatType &) override { ok = true; }
-
- void visit (const ErrorType &) override { ok = true; }
-
- void visit (const CharType &) override { ok = true; }
-
- void visit (const ReferenceType &) override { ok = true; }
-
- void visit (const ParamType &) override { ok = true; }
-
- void visit (const StrType &) override { ok = true; }
-
- void visit (const NeverType &) override { ok = true; }
-
- void visit (const SliceType &) override { ok = true; }
-
-private:
- const BaseType *get_base () const override { return base; }
-
- const PlaceholderType *base;
-};
-
-class DynamicCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- DynamicCmp (const DynamicObjectType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- void visit (const DynamicObjectType &type) override
- {
- if (base->num_specified_bounds () != type.num_specified_bounds ())
- {
- BaseCmp::visit (type);
- return;
- }
-
- location_t ref_locus = mappings.lookup_location (type.get_ref ());
- ok = base->bounds_compatible (type, ref_locus, false);
- }
-
-private:
- const BaseType *get_base () const override { return base; }
-
- const DynamicObjectType *base;
-};
-
-class OpaqueCmp : public BaseCmp
-{
- using Rust::TyTy::BaseCmp::visit;
-
-public:
- OpaqueCmp (const OpaqueType *base, bool emit_errors)
- : BaseCmp (base, emit_errors), base (base)
- {}
-
- // TODO
-
-private:
- const BaseType *get_base () const override { return base; }
-
- const OpaqueType *base;
-};
-
-} // namespace TyTy
-} // namespace Rust
-
-#endif // RUST_TYTY_CMP_H
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index 95f18b9..e82e8a3 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 (
- const HIR::TypeParam &generic, ParamType *param)
+SubstitutionParamMapping::SubstitutionParamMapping (HIR::GenericParam &generic,
+ BaseGeneric *param)
: generic (generic), param (param)
{}
@@ -50,23 +54,29 @@ SubstitutionParamMapping::as_string () const
SubstitutionParamMapping
SubstitutionParamMapping::clone () const
{
- return SubstitutionParamMapping (generic,
- static_cast<ParamType *> (param->clone ()));
+ return SubstitutionParamMapping (generic, static_cast<BaseGeneric *> (
+ param->clone ()));
}
-ParamType *
+BaseGeneric *
SubstitutionParamMapping::get_param_ty ()
{
return param;
}
-const ParamType *
+const BaseGeneric *
SubstitutionParamMapping::get_param_ty () const
{
return param;
}
-const HIR::TypeParam &
+HIR::GenericParam &
+SubstitutionParamMapping::get_generic_param ()
+{
+ return generic;
+}
+
+const HIR::GenericParam &
SubstitutionParamMapping::get_generic_param () const
{
return generic;
@@ -78,6 +88,12 @@ 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,26 @@ 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)
{
+ rust_assert (param->get_kind () == TyTy::TypeKind::CONST);
+ auto *const_type = type.as_const_type ();
+ if (const_type->const_kind () == TyTy::BaseConstType::ConstKind::Decl)
+ param = static_cast<BaseGeneric *> (type.clone ());
+ else
+ param->set_ty_ref (type.get_ref ());
+ }
+ 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 +193,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 +239,6 @@ SubstitutionArg::operator= (const SubstitutionArg &other)
}
BaseType *
-SubstitutionArg::get_tyty ()
-{
- return argument;
-}
-
-const BaseType *
SubstitutionArg::get_tyty () const
{
return argument;
@@ -208,7 +250,7 @@ SubstitutionArg::get_param_mapping () const
return param;
}
-const ParamType *
+const BaseGeneric *
SubstitutionArg::get_param_ty () const
{
return original_param;
@@ -313,11 +355,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;
@@ -517,6 +559,7 @@ std::vector<SubstitutionParamMapping>
SubstitutionRef::clone_substs () const
{
std::vector<SubstitutionParamMapping> clone;
+ clone.reserve (substitutions.size ());
for (auto &sub : substitutions)
clone.push_back (sub.clone ());
@@ -618,7 +661,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 +708,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 +728,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,9 +755,125 @@ 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->get_kind () != TyTy::TypeKind::CONST)
+ {
+ 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 ();
+ }
+ }
+
+ mappings.emplace_back (&param_mapping, resolved);
+ offs++;
+ }
+
+ 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->get_kind () == TyTy::TypeKind::CONST);
+ const auto const_param
+ = static_cast<const TyTy::ConstParamType *> (base_generic);
+ auto specified_type = const_param->get_specified_type ();
+
+ // validate this const generic is of the correct type
+ TyTy::BaseType *coereced_type = nullptr;
+ if (expr_type->get_kind () == TyTy::TypeKind::CONST)
+ {
+ auto const_expr_type = expr_type->as_const_type ();
+ auto const_value_type = const_expr_type->get_specified_type ();
+ coereced_type
+ = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (specified_type),
+ TyTy::TyWithLocation (const_value_type,
+ expr.get_locus ()),
+ arg.get_locus ());
+ }
+ else
+ {
+ 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 == nullptr || coereced_type->is<ErrorType> ())
+ return SubstitutionArgumentMappings::error ();
+
+ TyTy::BaseType *const_value_ty = nullptr;
+ if (expr_type->get_kind () == TyTy::TypeKind::CONST)
+ const_value_ty = expr_type;
+ else
+ {
+ // const fold it if available
+ auto ctx = Compile::Context::get ();
+ tree folded
+ = Compile::HIRCompileBase::query_compile_const_expr (ctx,
+ coereced_type,
+ expr);
+
+ if (folded == error_mark_node)
+ {
+ rich_location r (line_table, arg.get_locus ());
+ r.add_range (expr.get_locus ());
+ rust_error_at (r, "failed to resolve const expression");
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ // Use a fresh HirId to avoid conflicts with the expr's type
+ auto &global_mappings = Analysis::Mappings::get ();
+ HirId const_value_id = global_mappings.get_next_hir_id ();
+ const_value_ty
+ = new TyTy::ConstValueType (folded, coereced_type, const_value_id,
+ const_value_id, {});
+
+ // Insert the ConstValueType into the context so it can be looked up
+ auto context = Resolver::TypeCheckContext::get ();
+ context->insert_type (
+ Analysis::NodeMapping (0, 0, const_value_ty->get_ref (), 0),
+ const_value_ty);
+ }
+
+ mappings.emplace_back (&param_mapping, const_value_ty);
offs++;
- mappings.push_back (std::move (subst_arg));
}
// we must need to fill out defaults
@@ -734,8 +903,7 @@ SubstitutionRef::get_mappings_from_generic_args (
return SubstitutionArgumentMappings::error ();
}
- SubstitutionArg subst_arg (&param, resolved);
- mappings.push_back (std::move (subst_arg));
+ mappings.emplace_back (&param, resolved);
}
}
@@ -754,24 +922,31 @@ 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 ();
if (have_mapping)
{
- args.push_back (SubstitutionArg (&p, it->second));
+ args.emplace_back (&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 ()));
+ args.emplace_back (&p, infer_var.get_tyty ());
+ argument_mappings[symbol] = infer_var.get_tyty ();
+ }
+ else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
+ {
+ TyVar infer_var = TyVar::get_implicit_const_infer_var (locus);
+ args.emplace_back (&p, infer_var.get_tyty ());
argument_mappings[symbol] = infer_var.get_tyty ();
}
}
else
{
- args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
+ args.emplace_back (&p, p.get_param_ty ()->resolve ());
}
}
@@ -817,10 +992,7 @@ SubstitutionRef::adjust_mappings_for_this (
bool ok = !arg.is_error ();
if (ok || (trait_mode && i == 0))
- {
- SubstitutionArg adjusted (&subst, arg.get_tyty ());
- resolved_mappings.push_back (std::move (adjusted));
- }
+ resolved_mappings.emplace_back (&subst, arg.get_tyty ());
}
if (resolved_mappings.empty ())
@@ -864,10 +1036,7 @@ SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings)
bool ok = !arg.is_error ();
if (ok)
- {
- SubstitutionArg adjusted (&subst, arg.get_tyty ());
- resolved_mappings.push_back (std::move (adjusted));
- }
+ resolved_mappings.emplace_back (&subst, arg.get_tyty ());
}
return !resolved_mappings.empty ();
@@ -888,10 +1057,7 @@ SubstitutionRef::solve_mappings_from_receiver_for_self (
SubstitutionArg &arg = mappings.get_mappings ().at (i);
if (param_mapping.needs_substitution ())
- {
- SubstitutionArg adjusted (&param_mapping, arg.get_tyty ());
- resolved_mappings.push_back (std::move (adjusted));
- }
+ resolved_mappings.emplace_back (&param_mapping, arg.get_tyty ());
}
return SubstitutionArgumentMappings (resolved_mappings,
@@ -905,7 +1071,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,12 +1085,11 @@ 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;
- const TyTy::BaseType *binding = pty->resolve ();
+ TyTy::BaseType *binding = pty->resolve ();
if (binding->get_kind () == TyTy::TypeKind::PARAM)
continue;
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h
index 3f0b912..d09e180 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -22,14 +22,15 @@
#include "rust-system.h"
#include "rust-location.h"
#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 +45,24 @@ class SubstitutionArgumentMappings;
class SubstitutionParamMapping
{
public:
- SubstitutionParamMapping (const 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;
- const HIR::TypeParam &get_generic_param () const;
+ 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 +79,8 @@ public:
bool need_substitution () const;
private:
- const HIR::TypeParam &generic;
- ParamType *param;
+ HIR::GenericParam &generic;
+ BaseGeneric *param;
};
/**
@@ -147,13 +150,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 +166,7 @@ public:
private:
const SubstitutionParamMapping *param;
- const ParamType *original_param;
+ const BaseGeneric *original_param;
BaseType *argument;
};
@@ -205,7 +206,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..b780eaa 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 {
@@ -28,7 +30,8 @@ TyVar::TyVar (HirId ref) : ref (ref)
auto context = Resolver::TypeCheckContext::get ();
BaseType *lookup = nullptr;
bool ok = context->lookup_type (ref, &lookup);
- rust_assert (ok);
+ if (!ok || lookup == nullptr || lookup->get_kind () == TypeKind::ERROR)
+ return;
}
BaseType *
@@ -37,7 +40,8 @@ TyVar::get_tyty () const
auto context = Resolver::TypeCheckContext::get ();
BaseType *lookup = nullptr;
bool ok = context->lookup_type (ref, &lookup);
- rust_assert (ok);
+ if (!ok || lookup == nullptr)
+ return nullptr;
return lookup;
}
@@ -47,14 +51,28 @@ 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 (location_t locus, TyVar *implicit_type)
+{
+ auto &mappings = Analysis::Mappings::get ();
+ auto context = Resolver::TypeCheckContext::get ();
+
+ TyVar it = (implicit_type != nullptr) ? *implicit_type
+ : get_implicit_infer_var (locus);
+ HirId next = mappings.get_next_hir_id ();
+ auto infer = new ConstInferType (it.get_tyty (), next, next, {});
+
+ context->insert_implicit_type (infer->get_ref (), infer);
mappings.insert_location (infer->get_ref (), locus);
return TyVar (infer->get_ref ());
@@ -80,7 +98,10 @@ TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst)
TyVar
TyVar::clone () const
{
- TyTy::BaseType *c = get_tyty ()->clone ();
+ TyTy::BaseType *base = get_tyty ();
+ if (base == nullptr || base->get_kind () == TypeKind::ERROR)
+ return TyVar::get_implicit_infer_var (UNKNOWN_LOCATION);
+ TyTy::BaseType *c = base->clone ();
return TyVar (c->get_ref ());
}
@@ -90,6 +111,10 @@ TyVar::monomorphized_clone () const
auto &mappings = Analysis::Mappings::get ();
auto context = Resolver::TypeCheckContext::get ();
+ TyTy::BaseType *base = get_tyty ();
+ if (base == nullptr || base->get_kind () == TypeKind::ERROR)
+ return TyVar::get_implicit_infer_var (UNKNOWN_LOCATION);
+
// this needs a new hirid
TyTy::BaseType *c = get_tyty ()->monomorphized_clone ();
c->set_ref (mappings.get_next_hir_id ());
diff --git a/gcc/rust/typecheck/rust-tyty-util.h b/gcc/rust/typecheck/rust-tyty-util.h
index cbb3e8e..b132487 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 (location_t locus,
+ TyVar *implicit_type = nullptr);
+
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..b7ca5e1 100644
--- a/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
+++ b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
@@ -47,6 +47,10 @@ struct Term
/** Variance constraint of a type parameter. */
struct Constraint
{
+ Constraint (SolutionIndex target_index, Term *term)
+ : target_index (target_index), term (term)
+ {}
+
SolutionIndex target_index;
Term *term;
};
@@ -170,6 +174,11 @@ public:
}
void visit (OpaqueType &type) override {}
+
+ void visit (TyTy::ConstParamType &) override {}
+ void visit (TyTy::ConstValueType &) override {}
+ void visit (TyTy::ConstInferType &) override {}
+ void visit (TyTy::ConstErrorType &) 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 1aba576..d640d55 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++;
@@ -238,9 +236,8 @@ GenericTyVisitorCtx::process_type (ADTType &ty)
first_lifetime = lookup_or_add_type (ty.get_orig_ref ());
first_type = first_lifetime + ty.get_used_arguments ().get_regions ().size ();
- for (const auto &param : ty.get_substs ())
- param_names.push_back (
- param.get_generic_param ().get_type_representation ().as_string ());
+ for (auto &param : ty.get_substs ())
+ param_names.push_back (param.get_type_representation ().as_string ());
for (const auto &variant : ty.get_variants ())
{
@@ -324,6 +321,8 @@ GenericTyPerCrateCtx::query_generic_variance (const ADTType &type)
auto num_types = type.get_num_type_params ();
std::vector<Variance> result;
+ result.reserve (num_lifetimes + num_types);
+
for (size_t i = 0; i < num_lifetimes + num_types; ++i)
{
result.push_back (solutions[solution_index.value () + i]);
@@ -413,7 +412,7 @@ GenericTyVisitorCtx::add_constraint (SolutionIndex index, Term term)
}
else
{
- ctx.constraints.push_back ({index, new Term (term)});
+ ctx.constraints.emplace_back (index, new Term (term));
}
}
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..f7f3665e 100644
--- a/gcc/rust/typecheck/rust-tyty-visitor.h
+++ b/gcc/rust/typecheck/rust-tyty-visitor.h
@@ -45,6 +45,10 @@ public:
virtual void visit (ReferenceType &type) = 0;
virtual void visit (PointerType &type) = 0;
virtual void visit (ParamType &type) = 0;
+ virtual void visit (ConstParamType &type) = 0;
+ virtual void visit (ConstValueType &type) = 0;
+ virtual void visit (ConstInferType &type) = 0;
+ virtual void visit (ConstErrorType &type) = 0;
virtual void visit (StrType &type) = 0;
virtual void visit (NeverType &type) = 0;
virtual void visit (PlaceholderType &type) = 0;
@@ -75,6 +79,10 @@ 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 ConstParamType &type) = 0;
+ virtual void visit (const ConstValueType &type) = 0;
+ virtual void visit (const ConstInferType &type) = 0;
+ virtual void visit (const ConstErrorType &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 efad5f6..5386b72 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -16,23 +16,23 @@
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+#include "rust-system.h"
#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"
-#include "rust-linemap.h"
-
+#include "rust-type-util.h"
+#include "rust-hir-type-bounds.h"
#include "rust-substitution-mapper.h"
#include "rust-hir-trait-reference.h"
#include "rust-hir-trait-resolve.h"
-#include "rust-tyty-cmp.h"
-#include "rust-type-util.h"
-#include "rust-hir-type-bounds.h"
+#include "tree-pretty-print.h"
+#include "optional.h"
#include "options.h"
-#include "rust-system.h"
+#include "tree.h"
+#include "fold-const.h"
namespace Rust {
namespace TyTy {
@@ -114,6 +114,9 @@ TypeKindFormat::to_string (TypeKind kind)
case TypeKind::OPAQUE:
return "Opaque";
+ case TypeKind::CONST:
+ return "Const";
+
case TypeKind::ERROR:
return "ERROR";
}
@@ -223,6 +226,7 @@ BaseType::is_unit () const
case OPAQUE:
case STR:
case DYNAMIC:
+ case CONST:
case ERROR:
return false;
@@ -230,11 +234,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;
@@ -283,8 +289,7 @@ BaseType::get_locus () const
// FIXME this is missing locus
bool
-BaseType::satisfies_bound (const TypeBoundPredicate &predicate,
- bool emit_error) const
+BaseType::satisfies_bound (const TypeBoundPredicate &predicate, bool emit_error)
{
const Resolver::TraitReference *query = predicate.get ();
for (const auto &bound : specified_bounds)
@@ -339,41 +344,20 @@ BaseType::satisfies_bound (const TypeBoundPredicate &predicate,
return false;
std::string item_name = item->get_impl_item_name ();
- TypeBoundPredicateItem lookup
+ tl::optional<TypeBoundPredicateItem> lookup
= predicate.lookup_associated_item (item_name);
- if (lookup.is_error ())
+ if (!lookup.has_value ())
return false;
- const auto *item_ref = lookup.get_raw_item ();
+ const auto *item_ref = lookup->get_raw_item ();
TyTy::BaseType *bound_ty = item_ref->get_tyty ();
- // compare the types
- if (!bound_ty->can_eq (impl_item_ty, false))
- {
- if (!impl_item_ty->can_eq (bound_ty, false))
- {
- if (emit_error)
- {
- rich_location r (line_table,
- mappings.lookup_location (get_ref ()));
- r.add_range (predicate.get_locus ());
- r.add_range (mappings.lookup_location (i.get_hirid ()));
-
- std::string rich_msg
- = "expected " + bound_ty->destructure ()->get_name ()
- + ", found "
- + impl_item_ty->destructure ()->get_name ();
- r.add_fixit_replace (rich_msg.c_str ());
-
- rust_error_at (
- r, ErrorCode::E0271,
- "type mismatch, expected %qs but got %qs",
- bound_ty->destructure ()->get_name ().c_str (),
- impl_item_ty->destructure ()->get_name ().c_str ());
- }
- return false;
- }
- }
+ if (!Resolver::types_compatable (
+ TyTy::TyWithLocation (bound_ty, predicate.get_locus ()),
+ TyTy::TyWithLocation (impl_item_ty, item->get_locus ()),
+ mappings.lookup_location (get_ref ()), false /*emit-error*/,
+ false /*check-bounds*/))
+ return false;
}
return true;
@@ -383,8 +367,7 @@ BaseType::satisfies_bound (const TypeBoundPredicate &predicate,
}
bool
-BaseType::bounds_compatible (const BaseType &other, location_t locus,
- bool emit_error) const
+BaseType::bounds_compatible (BaseType &other, location_t locus, bool emit_error)
{
std::vector<std::reference_wrapper<const TypeBoundPredicate>>
unsatisfied_bounds;
@@ -438,11 +421,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> ())
{
@@ -490,6 +472,23 @@ BaseType::destructure ()
x = pr;
}
+ else if (x->get_kind () == TypeKind::CONST)
+ {
+ auto p = x->as_const_type ();
+ if (p->const_kind () == BaseConstType::ConstKind::Decl)
+ {
+ auto decl = static_cast<ConstParamType *> (p);
+ auto pr = decl->resolve ();
+ if (pr == x)
+ return pr;
+
+ x = pr;
+ }
+ else
+ {
+ return x;
+ }
+ }
else if (auto p = x->try_as<PlaceholderType> ())
{
if (!p->can_resolve ())
@@ -535,6 +534,23 @@ BaseType::destructure () const
x = pr;
}
+ else if (x->get_kind () == TypeKind::CONST)
+ {
+ auto p = x->as_const_type ();
+ if (p->const_kind () == BaseConstType::ConstKind::Decl)
+ {
+ auto decl = static_cast<const ConstParamType *> (p);
+ auto pr = decl->resolve ();
+ if (pr == x)
+ return pr;
+
+ x = pr;
+ }
+ else
+ {
+ return x;
+ }
+ }
else if (auto p = x->try_as<const PlaceholderType> ())
{
if (!p->can_resolve ())
@@ -546,17 +562,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 +588,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_var (), elm,
arr->get_combined_refs ());
}
else if (auto slice = x->try_as<const SliceType> ())
@@ -629,8 +642,8 @@ BaseType::monomorphized_clone () const
TyVar retty = fn->get_var_return_type ().monomorphized_clone ();
return new FnPtr (fn->get_ref (), fn->get_ty_ref (), ident.locus,
- std::move (cloned_params), retty,
- fn->get_combined_refs ());
+ std::move (cloned_params), retty, fn->get_abi (),
+ fn->get_unsafety (), fn->get_combined_refs ());
}
else if (auto adt = x->try_as<const ADTType> ())
{
@@ -682,6 +695,91 @@ BaseType::debug () const
debug_str ().c_str ());
}
+const TyTy::BaseType *
+BaseType::contains_infer () const
+{
+ const TyTy::BaseType *x = destructure ();
+
+ if (auto fn = x->try_as<const FnType> ())
+ {
+ for (const auto &param : fn->get_params ())
+ {
+ auto infer = param.get_type ()->contains_infer ();
+ if (infer)
+ return infer;
+ }
+ return fn->get_return_type ()->contains_infer ();
+ }
+ else if (auto fn = x->try_as<const FnPtr> ())
+ {
+ for (const auto &param : fn->get_params ())
+ {
+ auto infer = param.get_tyty ()->contains_infer ();
+ if (infer)
+ return infer;
+ }
+ return fn->get_return_type ()->contains_infer ();
+ }
+ else if (auto adt = x->try_as<const ADTType> ())
+ {
+ for (auto &variant : adt->get_variants ())
+ {
+ bool is_num_variant
+ = variant->get_variant_type () == VariantDef::VariantType::NUM;
+ if (is_num_variant)
+ continue;
+
+ for (auto &field : variant->get_fields ())
+ {
+ const BaseType *field_type = field->get_field_type ();
+ auto infer = (field_type->contains_infer ());
+ if (infer)
+ return infer;
+ }
+ }
+ return nullptr;
+ }
+ else if (auto arr = x->try_as<const ArrayType> ())
+ {
+ return arr->get_element_type ()->contains_infer ();
+ }
+ else if (auto slice = x->try_as<const SliceType> ())
+ {
+ return slice->get_element_type ()->contains_infer ();
+ }
+ else if (auto ptr = x->try_as<const PointerType> ())
+ {
+ return ptr->get_base ()->contains_infer ();
+ }
+ else if (auto ref = x->try_as<const ReferenceType> ())
+ {
+ return ref->get_base ()->contains_infer ();
+ }
+ else if (auto tuple = x->try_as<const TupleType> ())
+ {
+ for (size_t i = 0; i < tuple->num_fields (); i++)
+ {
+ auto infer = (tuple->get_field (i)->contains_infer ());
+ if (infer)
+ return infer;
+ }
+ return nullptr;
+ }
+ else if (auto closure = x->try_as<const ClosureType> ())
+ {
+ auto infer = (closure->get_parameters ().contains_infer ());
+ if (infer)
+ return infer;
+ return closure->get_result_type ().contains_infer ();
+ }
+ else if (x->is<InferType> ())
+ {
+ return x;
+ }
+
+ return nullptr;
+}
+
bool
BaseType::is_concrete () const
{
@@ -691,6 +789,14 @@ BaseType::is_concrete () const
{
return false;
}
+ else if (x->get_kind () == TyTy::TypeKind::CONST)
+ {
+ auto p = x->as_const_type ();
+ if (p->const_kind () == BaseConstType::ConstKind::Decl)
+ return false;
+
+ return true;
+ }
// placeholder is a special case for this case when it is not resolvable
// it means we its just an empty placeholder associated type which is
// concrete
@@ -739,7 +845,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> ())
{
@@ -783,7 +890,7 @@ BaseType::is_concrete () const
bool
BaseType::has_substitutions_defined () const
{
- const TyTy::BaseType *x = destructure ();
+ const auto x = this;
switch (x->get_kind ())
{
case INFER:
@@ -806,31 +913,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);
@@ -868,31 +980,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);
@@ -911,28 +1028,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 ();
@@ -1001,13 +1122,6 @@ InferType::as_string () const
return "<infer::error>";
}
-bool
-InferType::can_eq (const BaseType *other, bool emit_errors) const
-{
- InferCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
BaseType *
InferType::clone () const
{
@@ -1055,13 +1169,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;
@@ -1184,7 +1300,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;
@@ -1209,7 +1326,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;
@@ -1234,7 +1352,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 ();
@@ -1293,12 +1412,6 @@ ErrorType::as_string () const
return "<tyty::error>";
}
-bool
-ErrorType::can_eq (const BaseType *other, bool emit_errors) const
-{
- return get_kind () == other->get_kind ();
-}
-
BaseType *
ErrorType::clone () const
{
@@ -1683,13 +1796,6 @@ ADTType::as_string () const
}
bool
-ADTType::can_eq (const BaseType *other, bool emit_errors) const
-{
- ADTCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
-bool
ADTType::is_equal (const BaseType &other) const
{
if (get_kind () != other.get_kind ())
@@ -1715,11 +1821,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;
}
}
@@ -1907,7 +2011,7 @@ TupleType::get_name () const
std::string fields_buffer;
for (const TyVar &field : get_fields ())
{
- fields_buffer += field.get_tyty ()->as_string ();
+ fields_buffer += field.get_tyty ()->get_name ();
bool has_next = (i + 1) < get_fields ().size ();
fields_buffer += has_next ? ", " : "";
i++;
@@ -1922,13 +2026,6 @@ TupleType::get_field (size_t index) const
}
bool
-TupleType::can_eq (const BaseType *other, bool emit_errors) const
-{
- TupleCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
-bool
TupleType::is_equal (const BaseType &other) const
{
if (get_kind () != other.get_kind ())
@@ -2011,13 +2108,6 @@ FnType::as_string () const
}
bool
-FnType::can_eq (const BaseType *other, bool emit_errors) const
-{
- FnCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
-bool
FnType::is_equal (const BaseType &other) const
{
if (get_kind () != other.get_kind ())
@@ -2044,9 +2134,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;
}
@@ -2217,14 +2306,13 @@ FnPtr::as_string () const
params_str += p.get_tyty ()->as_string () + " ,";
}
- return "fnptr (" + params_str + ") -> " + get_return_type ()->as_string ();
-}
+ std::string unsafety = "";
+ if (get_unsafety () == Unsafety::Unsafe)
+ unsafety = "unsafe ";
-bool
-FnPtr::can_eq (const BaseType *other, bool emit_errors) const
-{
- FnptrCmp r (this, emit_errors);
- return r.can_eq (other);
+ std::string abi = get_string_from_abi (get_abi ());
+ return unsafety + "abi:" + abi + " " + "fnptr (" + params_str + ") -> "
+ + get_return_type ()->as_string ();
}
bool
@@ -2254,12 +2342,48 @@ BaseType *
FnPtr::clone () const
{
std::vector<TyVar> cloned_params;
+ cloned_params.reserve (params.size ());
+
for (auto &p : params)
- cloned_params.push_back (TyVar (p.get_ref ()));
+ cloned_params.emplace_back (p.get_ref ());
return new FnPtr (get_ref (), get_ty_ref (), ident.locus,
- std::move (cloned_params), result_type,
- get_combined_refs ());
+ std::move (cloned_params), result_type, get_abi (),
+ get_unsafety (), get_combined_refs ());
+}
+
+FnPtr *
+FnPtr::handle_substitions (SubstitutionArgumentMappings &mappings)
+{
+ auto &mappings_table = Analysis::Mappings::get ();
+
+ auto fn = clone ()->as<FnPtr> ();
+ fn->set_ref (mappings_table.get_next_hir_id ());
+ fn->set_ty_ref (mappings_table.get_next_hir_id ());
+
+ if (!fn->result_type.get_tyty ()->is_concrete ())
+ {
+ BaseType *concrete
+ = Resolver::SubstMapperInternal::Resolve (fn->result_type.get_tyty (),
+ mappings);
+ fn->result_type
+ = TyVar::subst_covariant_var (fn->result_type.get_tyty (), concrete);
+ }
+
+ for (size_t i = 0; i < fn->params.size (); i++)
+ {
+ TyVar &field = fn->params.at (i);
+ if (!field.get_tyty ()->is_concrete ())
+ {
+ BaseType *concrete
+ = Resolver::SubstMapperInternal::Resolve (field.get_tyty (),
+ mappings);
+ fn->params[i]
+ = TyVar::subst_covariant_var (field.get_tyty (), concrete);
+ }
+ }
+
+ return fn;
}
void
@@ -2282,13 +2406,6 @@ ClosureType::as_string () const
}
bool
-ClosureType::can_eq (const BaseType *other, bool emit_errors) const
-{
- ClosureCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
-bool
ClosureType::is_equal (const BaseType &other) const
{
if (other.get_kind () != TypeKind::CLOSURE)
@@ -2385,14 +2502,10 @@ ArrayType::accept_vis (TyConstVisitor &vis) const
std::string
ArrayType::as_string () const
{
- return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]";
-}
+ auto cap = get_capacity ();
+ std::string capacity_str = cap->as_string ();
-bool
-ArrayType::can_eq (const BaseType *other, bool emit_errors) const
-{
- ArrayCmp r (this, emit_errors);
- return r.can_eq (other);
+ return "[" + get_element_type ()->as_string () + "; " + capacity_str + "]";
}
bool
@@ -2422,9 +2535,15 @@ ArrayType::get_var_element_type () const
}
BaseType *
+ArrayType::get_capacity () const
+{
+ return capacity.get_tyty ();
+}
+
+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 ());
}
@@ -2441,6 +2560,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 = TyVar::subst_covariant_var (cap, concrete_cap);
+
return ref;
}
@@ -2463,13 +2589,6 @@ SliceType::as_string () const
}
bool
-SliceType::can_eq (const BaseType *other, bool emit_errors) const
-{
- SliceCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
-bool
SliceType::is_equal (const BaseType &other) const
{
if (get_kind () != other.get_kind ())
@@ -2556,13 +2675,6 @@ BoolType::as_string () const
return "bool";
}
-bool
-BoolType::can_eq (const BaseType *other, bool emit_errors) const
-{
- BoolCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
BaseType *
BoolType::clone () const
{
@@ -2629,13 +2741,6 @@ IntType::as_string () const
return "__unknown_int_type";
}
-bool
-IntType::can_eq (const BaseType *other, bool emit_errors) const
-{
- IntCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
BaseType *
IntType::clone () const
{
@@ -2714,13 +2819,6 @@ UintType::as_string () const
return "__unknown_uint_type";
}
-bool
-UintType::can_eq (const BaseType *other, bool emit_errors) const
-{
- UintCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
BaseType *
UintType::clone () const
{
@@ -2793,13 +2891,6 @@ FloatType::as_string () const
return "__unknown_float_type";
}
-bool
-FloatType::can_eq (const BaseType *other, bool emit_errors) const
-{
- FloatCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
BaseType *
FloatType::clone () const
{
@@ -2855,13 +2946,6 @@ USizeType::as_string () const
return "usize";
}
-bool
-USizeType::can_eq (const BaseType *other, bool emit_errors) const
-{
- USizeCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
BaseType *
USizeType::clone () const
{
@@ -2906,13 +2990,6 @@ ISizeType::as_string () const
return "isize";
}
-bool
-ISizeType::can_eq (const BaseType *other, bool emit_errors) const
-{
- ISizeCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
BaseType *
ISizeType::clone () const
{
@@ -2957,13 +3034,6 @@ CharType::as_string () const
return "char";
}
-bool
-CharType::can_eq (const BaseType *other, bool emit_errors) const
-{
- CharCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
BaseType *
CharType::clone () const
{
@@ -3078,13 +3148,6 @@ ReferenceType::get_name () const
}
bool
-ReferenceType::can_eq (const BaseType *other, bool emit_errors) const
-{
- ReferenceCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
-bool
ReferenceType::is_equal (const BaseType &other) const
{
if (get_kind () != other.get_kind ())
@@ -3240,13 +3303,6 @@ PointerType::get_name () const
}
bool
-PointerType::can_eq (const BaseType *other, bool emit_errors) const
-{
- PointerCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
-bool
PointerType::is_equal (const BaseType &other) const
{
if (get_kind () != other.get_kind ())
@@ -3297,33 +3353,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
{
@@ -3363,18 +3412,11 @@ ParamType::get_name () const
return destructure ()->get_name ();
}
-bool
-ParamType::can_eq (const BaseType *other, bool emit_errors) const
-{
- ParamCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
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 ());
}
@@ -3428,7 +3470,9 @@ ParamType::is_equal (const BaseType &other) const
return false;
if (can_resolve ())
- return resolve ()->can_eq (other2.resolve (), false);
+ return Resolver::types_compatable (TyTy::TyWithLocation (resolve ()),
+ TyTy::TyWithLocation (other2.resolve ()),
+ UNKNOWN_LOCATION, false, false);
return get_symbol ().compare (other2.get_symbol ()) == 0;
}
@@ -3444,12 +3488,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 ())
+ pp.resolve ();
}
// this is the new subst that this needs to pass
@@ -3471,6 +3515,399 @@ ParamType::is_implicit_self_trait () const
return is_trait_self;
}
+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;
+}
+
+// ---
+
+ConstParamType::ConstParamType (std::string symbol, location_t locus,
+ BaseType *type, HirId ref, HirId ty_ref,
+ std::set<HirId> refs)
+ : BaseConstType (type),
+ BaseGeneric (ref, ty_ref, KIND,
+ {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+ locus},
+ {}, refs),
+ symbol (symbol)
+{}
+
+BaseConstType::ConstKind
+ConstParamType::const_kind () const
+{
+ return BaseConstType::ConstKind::Decl;
+}
+
+std::string
+ConstParamType::get_symbol () const
+{
+ return symbol;
+}
+
+bool
+ConstParamType::can_resolve () const
+{
+ return get_ref () != get_ty_ref ();
+}
+
+BaseType *
+ConstParamType::resolve () const
+{
+ TyVar var (get_ty_ref ());
+ BaseType *r = var.get_tyty ();
+
+ while (r->get_kind () == TypeKind::CONST)
+ {
+ TyVar v (r->get_ty_ref ());
+ BaseType *n = v.get_tyty ();
+
+ // fix infinite loop
+ if (r == n)
+ break;
+
+ r = n;
+ }
+
+ if (r->get_kind () == TypeKind::CONST && (r->get_ref () == r->get_ty_ref ()))
+ {
+ auto *const_type = r->as_const_type ();
+ if (const_type->const_kind () != BaseConstType::ConstKind::Value)
+ return TyVar (r->get_ty_ref ()).get_tyty ();
+ }
+
+ return r;
+}
+
+void
+ConstParamType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstParamType::accept_vis (TyConstVisitor &vis) const
+{
+ vis.visit (*this);
+}
+
+std::string
+ConstParamType::as_string () const
+{
+ if (!can_resolve ())
+ {
+ return get_symbol () + " CONST_REF: " + std::to_string (get_ref ());
+ }
+
+ BaseType *lookup = resolve ();
+ // Avoid infinite recursion if resolve() returns this same type
+ if (lookup == this->as_base_type ())
+ {
+ return get_symbol () + " CONST_REF: " + std::to_string (get_ref ());
+ }
+
+ return get_symbol () + "=" + lookup->as_string ();
+}
+
+BaseType *
+ConstParamType::clone () const
+{
+ return new ConstParamType (get_symbol (), ident.locus, specified_type,
+ get_ref (), get_ty_ref (), get_combined_refs ());
+}
+
+std::string
+ConstParamType::get_name () const
+{
+ if (!can_resolve ())
+ return get_symbol ();
+
+ BaseType *lookup = resolve ();
+ if (lookup == this->as_base_type ())
+ return get_symbol () + ":" + get_specified_type ()->get_name ();
+
+ return lookup->get_name ();
+}
+
+bool
+ConstParamType::is_equal (const BaseType &other) const
+{
+ if (get_kind () != other.get_kind ())
+ {
+ if (!can_resolve ())
+ return false;
+
+ return resolve ()->is_equal (other);
+ }
+
+ auto other_const = other.as_const_type ();
+ if (other_const->const_kind () != BaseConstType::ConstKind::Decl)
+ return false;
+
+ auto &other2 = static_cast<const ConstParamType &> (*other_const);
+ if (can_resolve () != other2.can_resolve ())
+ return false;
+
+ if (can_resolve ())
+ {
+ // Compare the resolved ty_ref values to avoid infinite recursion
+ // through types_compatable/unification
+ BaseType *lhs = resolve ();
+ BaseType *rhs = other2.resolve ();
+
+ // If they resolve to the same type (same ty_ref), they're equal
+ if (lhs->get_ty_ref () == rhs->get_ty_ref ())
+ return true;
+
+ // Otherwise check if the resolved types are equal
+ // Avoid recursion by checking if we'd be comparing ConstParamTypes again
+ if (lhs->get_kind () == TypeKind::CONST
+ && lhs->as_const_type ()->const_kind ()
+ == BaseConstType::ConstKind::Decl)
+ return false; // Would cause recursion, so not equal
+
+ return lhs->is_equal (*rhs);
+ }
+
+ return get_symbol ().compare (other2.get_symbol ()) == 0;
+}
+
+BaseType *
+ConstParamType::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;
+
+ ConstParamType *p = static_cast<ConstParamType *> (clone ());
+ const BaseType *resolved = arg.get_tyty ();
+
+ // this is the new subst that this needs to pass
+ p->set_ref (mappings.get_next_hir_id ());
+ p->set_ty_ref (resolved->get_ref ());
+
+ return p;
+}
+
+// --- ConstValueType
+
+ConstValueType::ConstValueType (tree value, BaseType *type, HirId ref,
+ HirId ty_ref, std::set<HirId> refs)
+ : BaseType (ref, ty_ref, KIND,
+ {Resolver::CanonicalPath::create_empty (), UNKNOWN_LOCATION},
+ refs),
+ BaseConstType (type), folded_val (value)
+{}
+
+BaseConstType::ConstKind
+ConstValueType::const_kind () const
+{
+ return BaseConstType::ConstKind::Value;
+}
+
+void
+ConstValueType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstValueType::accept_vis (TyConstVisitor &vis) const
+{
+ vis.visit (*this);
+}
+
+std::string
+ConstValueType::as_string () const
+{
+ return generate_tree_str (folded_val);
+}
+
+BaseType *
+ConstValueType::clone () const
+{
+ return new ConstValueType (folded_val, specified_type, get_ref (),
+ get_ty_ref (), get_combined_refs ());
+}
+
+std::string
+ConstValueType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+ConstValueType::is_equal (const BaseType &other) const
+{
+ if (get_kind () != other.get_kind ())
+ return false;
+
+ auto other_const = other.as_const_type ();
+ if (other_const->const_kind () != BaseConstType::ConstKind::Value)
+ return false;
+
+ auto &other2 = static_cast<const ConstValueType &> (*other_const);
+ return folded_val == other2.folded_val;
+}
+
+tree
+ConstValueType::get_value () const
+{
+ return folded_val;
+}
+
+// --- ConstInferType
+
+ConstInferType::ConstInferType (BaseType *type, HirId ref, HirId ty_ref,
+ std::set<HirId> refs)
+ : BaseType (ref, ty_ref, KIND,
+ {Resolver::CanonicalPath::create_empty (), UNKNOWN_LOCATION},
+ refs),
+ BaseConstType (type)
+{}
+
+BaseConstType::ConstKind
+ConstInferType::const_kind () const
+{
+ return BaseConstType::ConstKind::Infer;
+}
+
+void
+ConstInferType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstInferType::accept_vis (TyConstVisitor &vis) const
+{
+ vis.visit (*this);
+}
+
+std::string
+ConstInferType::as_string () const
+{
+ return specified_type->get_name () + "-?";
+}
+
+BaseType *
+ConstInferType::clone () const
+{
+ auto &mappings = Analysis::Mappings::get ();
+ auto context = Resolver::TypeCheckContext::get ();
+
+ ConstInferType *clone
+ = new ConstInferType (specified_type, mappings.get_next_hir_id (),
+ get_ty_ref (), get_combined_refs ());
+
+ context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (),
+ UNKNOWN_NODEID,
+ clone->get_ref (),
+ UNKNOWN_LOCAL_DEFID),
+ clone);
+ mappings.insert_location (clone->get_ref (),
+ mappings.lookup_location (get_ref ()));
+
+ clone->append_reference (get_ref ());
+
+ return clone;
+}
+
+std::string
+ConstInferType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+ConstInferType::is_equal (const BaseType &other) const
+{
+ if (get_kind () != other.get_kind ())
+ return false;
+
+ auto other_const = other.as_const_type ();
+ if (other_const->const_kind () != BaseConstType::ConstKind::Infer)
+ return false;
+
+ return get_ref () == other.get_ref ();
+}
+
+// --- ConstErrorType
+
+ConstErrorType::ConstErrorType (BaseType *type, HirId ref, HirId ty_ref,
+ std::set<HirId> refs)
+ : BaseType (ref, ty_ref, KIND,
+ {Resolver::CanonicalPath::create_empty (), UNKNOWN_LOCATION},
+ refs),
+ BaseConstType (type)
+{}
+
+BaseConstType::ConstKind
+ConstErrorType::const_kind () const
+{
+ return BaseConstType::ConstKind::Error;
+}
+
+void
+ConstErrorType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstErrorType::accept_vis (TyConstVisitor &vis) const
+{
+ vis.visit (*this);
+}
+
+std::string
+ConstErrorType::as_string () const
+{
+ return "<const_error>";
+}
+
+BaseType *
+ConstErrorType::clone () const
+{
+ return new ConstErrorType (specified_type, get_ref (), get_ty_ref (),
+ get_combined_refs ());
+}
+
+std::string
+ConstErrorType::get_name () const
+{
+ return as_string ();
+}
+
+bool
+ConstErrorType::is_equal (const BaseType &other) const
+{
+ if (get_kind () != other.get_kind ())
+ return false;
+
+ auto other_const = other.as_const_type ();
+ return other_const->const_kind () == BaseConstType::ConstKind::Error;
+}
+
// OpaqueType
OpaqueType::OpaqueType (location_t locus, HirId ref,
@@ -3521,13 +3958,6 @@ OpaqueType::get_name () const
return "impl " + raw_bounds_as_name ();
}
-bool
-OpaqueType::can_eq (const BaseType *other, bool emit_errors) const
-{
- OpaqueCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
BaseType *
OpaqueType::clone () const
{
@@ -3539,28 +3969,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
@@ -3570,39 +3979,24 @@ 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;
- // }
+ if (num_specified_bounds () != other.num_specified_bounds ())
+ return false;
- // // 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 ());
+ for (const auto &pred : specified_bounds)
+ {
+ bool found = false;
+ for (const auto &opred : other.get_specified_bounds ())
+ {
+ found = pred.is_equal (opred);
+ if (found)
+ break;
+ }
- // return p;
+ if (!found)
+ return false;
+ }
- rust_unreachable ();
- return nullptr;
+ return true;
}
// StrType
@@ -3650,13 +4044,6 @@ StrType::as_string () const
}
bool
-StrType::can_eq (const BaseType *other, bool emit_errors) const
-{
- StrCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
-bool
StrType::is_equal (const BaseType &other) const
{
return get_kind () == other.get_kind ();
@@ -3700,13 +4087,6 @@ NeverType::as_string () const
return "!";
}
-bool
-NeverType::can_eq (const BaseType *other, bool emit_errors) const
-{
- NeverCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
BaseType *
NeverType::clone () const
{
@@ -3762,13 +4142,6 @@ PlaceholderType::as_string () const
+ ">";
}
-bool
-PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const
-{
- PlaceholderCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
BaseType *
PlaceholderType::clone () const
{
@@ -3905,12 +4278,6 @@ ProjectionType::as_string () const
return "<Projection=" + subst_as_string () + "::" + base->as_string () + ">";
}
-bool
-ProjectionType::can_eq (const BaseType *other, bool emit_errors) const
-{
- return base->can_eq (other, emit_errors);
-}
-
BaseType *
ProjectionType::clone () const
{
@@ -4024,13 +4391,6 @@ DynamicObjectType::as_string () const
return "dyn [" + raw_bounds_as_string () + "]";
}
-bool
-DynamicObjectType::can_eq (const BaseType *other, bool emit_errors) const
-{
- DynamicCmp r (this, emit_errors);
- return r.can_eq (other);
-}
-
BaseType *
DynamicObjectType::clone () const
{
@@ -4053,7 +4413,21 @@ DynamicObjectType::is_equal (const BaseType &other) const
if (num_specified_bounds () != other.num_specified_bounds ())
return false;
- return bounds_compatible (other, UNDEF_LOCATION, false);
+ for (const auto &pred : specified_bounds)
+ {
+ bool found = false;
+ for (const auto &opred : other.get_specified_bounds ())
+ {
+ found = pred.is_equal (opred);
+ if (found)
+ break;
+ }
+
+ if (!found)
+ return false;
+ }
+
+ return true;
}
const std::vector<
@@ -4074,7 +4448,7 @@ DynamicObjectType::get_object_items () const
if (item->get_trait_item_type ()
== Resolver::TraitItemReference::TraitItemType::FN
&& item->is_object_safe ())
- items.push_back ({item, &bound});
+ items.emplace_back (item, &bound);
}
}
return items;
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index e814f07..50f6347 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -19,16 +19,17 @@
#ifndef RUST_TYTY
#define RUST_TYTY
+#include "optional.h"
#include "rust-hir-map.h"
#include "rust-common.h"
#include "rust-identifier.h"
#include "rust-abi.h"
-#include "rust-tyty-bounds.h"
#include "rust-tyty-util.h"
#include "rust-tyty-subst.h"
#include "rust-tyty-region.h"
#include "rust-system.h"
#include "rust-hir.h"
+#include "tree.h"
namespace Rust {
@@ -56,6 +57,7 @@ enum TypeKind
REF,
POINTER,
PARAM,
+ CONST,
ARRAY,
SLICE,
FNDEF,
@@ -78,8 +80,7 @@ enum TypeKind
ERROR
};
-extern bool
-is_primitive_type_kind (TypeKind kind);
+extern bool is_primitive_type_kind (TypeKind kind);
class TypeKindFormat
{
@@ -89,6 +90,128 @@ public:
class TyVisitor;
class TyConstVisitor;
+class BaseConstType;
+
+class TypeBoundPredicate : public SubstitutionRef
+{
+public:
+ TypeBoundPredicate (const Resolver::TraitReference &trait_reference,
+ BoundPolarity polarity, location_t locus);
+
+ TypeBoundPredicate (DefId reference,
+ std::vector<SubstitutionParamMapping> substitutions,
+ BoundPolarity polarity, location_t locus);
+
+ TypeBoundPredicate (const TypeBoundPredicate &other);
+
+ virtual ~TypeBoundPredicate () {}
+
+ TypeBoundPredicate &operator= (const TypeBoundPredicate &other);
+
+ static TypeBoundPredicate error ();
+
+ std::string as_string () const;
+
+ std::string as_name () const;
+
+ const Resolver::TraitReference *get () const;
+
+ location_t get_locus () const { return locus; }
+
+ std::string get_name () const;
+
+ // 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 is_super_trait);
+
+ void apply_argument_mappings (SubstitutionArgumentMappings &arguments,
+ bool is_super_trait);
+
+ bool contains_item (const std::string &search) const;
+
+ tl::optional<TypeBoundPredicateItem>
+ lookup_associated_item (const std::string &search) const;
+
+ tl::optional<TypeBoundPredicateItem>
+ lookup_associated_item (const Resolver::TraitItemReference *ref) const;
+
+ // WARNING THIS WILL ALWAYS RETURN NULLPTR
+ BaseType *
+ handle_substitions (SubstitutionArgumentMappings &mappings) override final;
+
+ bool is_error () const;
+
+ bool requires_generic_args () const;
+
+ bool contains_associated_types () const;
+
+ DefId get_id () const { return reference; }
+
+ BoundPolarity get_polarity () const { return polarity; }
+
+ std::vector<TypeBoundPredicateItem> get_associated_type_items ();
+
+ size_t get_num_associated_bindings () const override final;
+
+ TypeBoundPredicateItem
+ lookup_associated_type (const std::string &search) override final;
+
+ bool is_equal (const TypeBoundPredicate &other) const;
+
+ bool validate_type_implements_super_traits (TyTy::BaseType &self,
+ HIR::Type &impl_type,
+ HIR::Type &trait) const;
+
+ bool validate_type_implements_this (TyTy::BaseType &self,
+ HIR::Type &impl_type,
+ HIR::Type &trait) const;
+
+private:
+ struct mark_is_error
+ {
+ };
+
+ TypeBoundPredicate (mark_is_error);
+
+ void get_trait_hierachy (
+ std::function<void (const Resolver::TraitReference &)> callback) const;
+
+ DefId reference;
+ location_t locus;
+ bool error_flag;
+ BoundPolarity polarity;
+ std::vector<TyTy::TypeBoundPredicate> super_traits;
+};
+
+class TypeBoundsMappings
+{
+protected:
+ TypeBoundsMappings (std::vector<TypeBoundPredicate> specified_bounds);
+
+public:
+ std::vector<TypeBoundPredicate> &get_specified_bounds ();
+
+ const std::vector<TypeBoundPredicate> &get_specified_bounds () const;
+
+ TypeBoundPredicate lookup_predicate (DefId id);
+
+ size_t num_specified_bounds () const;
+
+ std::string raw_bounds_as_string () const;
+
+ std::string bounds_as_string () const;
+
+ std::string raw_bounds_as_name () const;
+
+protected:
+ void add_bound (TypeBoundPredicate predicate);
+
+ std::vector<TypeBoundPredicate> specified_bounds;
+};
+
class BaseType : public TypeBoundsMappings
{
public:
@@ -108,35 +231,24 @@ public:
virtual std::string as_string () const = 0;
virtual std::string get_name () const = 0;
- // similar to unify but does not actually perform type unification but
- // determines whether they are compatible. Consider the following
- //
- // fn foo<T>() -> T { ... }
- // fn foo() -> i32 { ... }
- //
- // when the function has been substituted they can be considered equal.
- //
- // It can also be used to optional emit errors for trait item compatibility
- // checks
- virtual bool can_eq (const BaseType *other, bool emit_errors) const = 0;
-
// Check value equality between two ty. Type inference rules are ignored. Two
// ty are considered equal if they're of the same kind, and
// 1. (For ADTs, arrays, tuples, refs) have the same underlying ty
// 2. (For functions) have the same signature
virtual bool is_equal (const BaseType &other) const;
- bool satisfies_bound (const TypeBoundPredicate &predicate,
- bool emit_error) const;
+ bool satisfies_bound (const TypeBoundPredicate &predicate, bool emit_error);
- bool bounds_compatible (const BaseType &other, location_t locus,
- bool emit_error) const;
+ bool bounds_compatible (BaseType &other, location_t locus, bool emit_error);
void inherit_bounds (const BaseType &other);
void inherit_bounds (
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
+ // contains_infer checks if there is an inference variable inside the type
+ const TyTy::BaseType *contains_infer () const;
+
// is_unit returns whether this is just a unit-struct
bool is_unit () const;
@@ -162,8 +274,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
@@ -236,6 +347,11 @@ public:
return static_cast<T *> (this);
}
+ // Helper to get BaseConstType interface for CONST types
+ // Overridden by const types that also inherit from BaseConstType
+ virtual BaseConstType *as_const_type () { return nullptr; }
+ virtual const BaseConstType *as_const_type () const { return nullptr; }
+
protected:
BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
std::set<HirId> refs = std::set<HirId> ());
@@ -265,8 +381,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;
};
@@ -323,8 +439,6 @@ public:
std::string as_string () const override;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
BaseType *clone () const final override;
InferTypeKind get_infer_kind () const;
@@ -355,25 +469,39 @@ public:
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_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> ());
@@ -382,17 +510,13 @@ public:
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;
+ std::string get_symbol () const override final;
- HIR::GenericParam &get_generic_param ();
+ bool can_resolve () const override final;
- bool can_resolve () const;
-
- BaseType *resolve () const;
+ BaseType *resolve () const override final;
std::string get_name () const override final;
@@ -406,7 +530,170 @@ public:
private:
bool is_trait_self;
std::string symbol;
- HIR::GenericParam &param;
+};
+
+class BaseConstType
+{
+public:
+ static constexpr auto KIND = TypeKind::CONST;
+
+ enum ConstKind
+ {
+ Decl,
+ Value,
+ Infer,
+ Error
+ };
+
+ virtual ConstKind const_kind () const = 0;
+
+ BaseType *get_specified_type () const { return specified_type; }
+
+ // Helper to get BaseType interface (all const types also inherit BaseType)
+ // This must be implemented by concrete classes since BaseConstType doesn't
+ // inherit from BaseType, but all concrete const types do.
+ virtual BaseType *as_base_type () = 0;
+ virtual const BaseType *as_base_type () const = 0;
+
+protected:
+ BaseConstType (BaseType *type) : specified_type (type) {}
+
+ BaseType *specified_type;
+};
+
+class ConstParamType : public BaseConstType, public BaseGeneric
+{
+public:
+ ConstParamType (std::string symbol, location_t locus, BaseType *type,
+ HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
+
+ ConstKind const_kind () const override final;
+
+ std::string get_symbol () const override final;
+
+ bool can_resolve () const override final;
+
+ BaseType *resolve () const override final;
+
+ void accept_vis (TyVisitor &vis) override;
+ void accept_vis (TyConstVisitor &vis) const override;
+
+ std::string as_string () const override;
+
+ BaseType *clone () const final override;
+ std::string get_name () const override final;
+
+ bool is_equal (const BaseType &other) const override;
+
+ BaseType *handle_substitions (SubstitutionArgumentMappings &mappings);
+
+ BaseType *as_base_type () override { return static_cast<BaseType *> (this); }
+ const BaseType *as_base_type () const override
+ {
+ return static_cast<const BaseType *> (this);
+ }
+
+ BaseConstType *as_const_type () override { return this; }
+ const BaseConstType *as_const_type () const override { return this; }
+
+private:
+ std::string symbol;
+};
+
+class ConstValueType : public BaseType, public BaseConstType
+{
+public:
+ static constexpr auto KIND = TypeKind::CONST;
+
+ ConstValueType (tree value, BaseType *type, HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
+
+ ConstKind const_kind () const override final;
+
+ void accept_vis (TyVisitor &vis) override;
+ void accept_vis (TyConstVisitor &vis) const override;
+
+ std::string as_string () const override;
+
+ BaseType *clone () const final override;
+ std::string get_name () const override final;
+
+ bool is_equal (const BaseType &other) const override;
+
+ tree get_value () const;
+
+ BaseType *as_base_type () override { return static_cast<BaseType *> (this); }
+ const BaseType *as_base_type () const override
+ {
+ return static_cast<const BaseType *> (this);
+ }
+
+ BaseConstType *as_const_type () override { return this; }
+ const BaseConstType *as_const_type () const override { return this; }
+
+private:
+ tree folded_val;
+};
+
+class ConstInferType : public BaseType, public BaseConstType
+{
+public:
+ static constexpr auto KIND = TypeKind::CONST;
+
+ ConstInferType (BaseType *type, HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
+
+ ConstKind const_kind () const override final;
+
+ void accept_vis (TyVisitor &vis) override;
+ void accept_vis (TyConstVisitor &vis) const override;
+
+ std::string as_string () const override;
+
+ BaseType *clone () const final override;
+ std::string get_name () const override final;
+
+ bool is_equal (const BaseType &other) const override;
+
+ BaseType *as_base_type () override { return static_cast<BaseType *> (this); }
+ const BaseType *as_base_type () const override
+ {
+ return static_cast<const BaseType *> (this);
+ }
+
+ BaseConstType *as_const_type () override { return this; }
+ const BaseConstType *as_const_type () const override { return this; }
+};
+
+class ConstErrorType : public BaseType, public BaseConstType
+{
+public:
+ static constexpr auto KIND = TypeKind::CONST;
+
+ ConstErrorType (BaseType *type, HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
+
+ ConstKind const_kind () const override final;
+
+ void accept_vis (TyVisitor &vis) override;
+ void accept_vis (TyConstVisitor &vis) const override;
+
+ std::string as_string () const override;
+
+ BaseType *clone () const final override;
+ std::string get_name () const override final;
+
+ bool is_equal (const BaseType &other) const override;
+
+ BaseType *as_base_type () override { return static_cast<BaseType *> (this); }
+ const BaseType *as_base_type () const override
+ {
+ return static_cast<const BaseType *> (this);
+ }
+
+ BaseConstType *as_const_type () override { return this; }
+ const BaseConstType *as_const_type () const override { return this; }
};
class OpaqueType : public BaseType
@@ -427,8 +714,6 @@ public:
std::string as_string () const override;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
BaseType *clone () const final override;
bool can_resolve () const;
@@ -438,8 +723,6 @@ public:
std::string get_name () const override final;
bool is_equal (const BaseType &other) const override;
-
- OpaqueType *handle_substitions (SubstitutionArgumentMappings &mappings);
};
class StructFieldType
@@ -490,8 +773,6 @@ public:
std::string as_string () const override;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
bool is_equal (const BaseType &other) const override;
size_t num_fields () const;
@@ -510,96 +791,6 @@ private:
std::vector<TyVar> fields;
};
-class TypeBoundPredicate : public SubstitutionRef
-{
-public:
- TypeBoundPredicate (const Resolver::TraitReference &trait_reference,
- BoundPolarity polarity, location_t locus);
-
- TypeBoundPredicate (DefId reference,
- std::vector<SubstitutionParamMapping> substitutions,
- BoundPolarity polarity, location_t locus);
-
- TypeBoundPredicate (const TypeBoundPredicate &other);
-
- virtual ~TypeBoundPredicate (){};
-
- TypeBoundPredicate &operator= (const TypeBoundPredicate &other);
-
- static TypeBoundPredicate error ();
-
- std::string as_string () const;
-
- std::string as_name () const;
-
- const Resolver::TraitReference *get () const;
-
- location_t get_locus () const { return locus; }
-
- std::string get_name () const;
-
- // check that this predicate 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);
-
- void apply_argument_mappings (SubstitutionArgumentMappings &arguments);
-
- bool contains_item (const std::string &search) const;
-
- TypeBoundPredicateItem
- lookup_associated_item (const std::string &search) const;
-
- TypeBoundPredicateItem
- lookup_associated_item (const Resolver::TraitItemReference *ref) const;
-
- // WARNING THIS WILL ALWAYS RETURN NULLPTR
- BaseType *
- handle_substitions (SubstitutionArgumentMappings &mappings) override final;
-
- bool is_error () const;
-
- bool requires_generic_args () const;
-
- bool contains_associated_types () const;
-
- DefId get_id () const { return reference; }
-
- BoundPolarity get_polarity () const { return polarity; }
-
- std::vector<TypeBoundPredicateItem> get_associated_type_items ();
-
- size_t get_num_associated_bindings () const override final;
-
- TypeBoundPredicateItem
- lookup_associated_type (const std::string &search) override final;
-
- bool is_equal (const TypeBoundPredicate &other) const;
-
- bool validate_type_implements_super_traits (TyTy::BaseType &self,
- HIR::Type &impl_type,
- HIR::Type &trait) const;
-
- bool validate_type_implements_this (TyTy::BaseType &self,
- HIR::Type &impl_type,
- HIR::Type &trait) const;
-
-private:
- struct mark_is_error
- {
- };
-
- TypeBoundPredicate (mark_is_error);
-
- DefId reference;
- location_t locus;
- bool error_flag;
- BoundPolarity polarity;
- std::vector<TyTy::TypeBoundPredicate> super_traits;
-};
-
class TypeBoundPredicateItem
{
public:
@@ -711,12 +902,22 @@ public:
ENUM
};
+ enum ReprKind
+ {
+ RUST,
+ C,
+ INT,
+ ALIGN,
+ PACKED,
+ // TRANSPARENT,
+ // SIMD,
+ // ...
+ };
+
// Representation options, specified via attributes e.g. #[repr(packed)]
struct ReprOptions
{
- // bool is_c;
- // bool is_transparent;
- //...
+ ReprKind repr_kind = ReprKind::RUST;
// For align and pack: 0 = unspecified. Nonzero = byte alignment.
// It is an error for both to be nonzero, this should be caught when
@@ -770,8 +971,6 @@ public:
std::string as_string () const override;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
bool is_equal (const BaseType &other) const override;
std::string get_identifier () const { return identifier; }
@@ -877,6 +1076,7 @@ public:
static const uint8_t FNTYPE_IS_METHOD_FLAG = 0x01;
static const uint8_t FNTYPE_IS_EXTERN_FLAG = 0x02;
static const uint8_t FNTYPE_IS_VARADIC_FLAG = 0X04;
+ static const uint8_t FNTYPE_IS_SYN_CONST_FLAG = 0X08;
FnType (HirId ref, DefId id, std::string identifier, RustIdent ident,
uint8_t flags, ABI abi, std::vector<FnParam> params, BaseType *type,
@@ -922,8 +1122,6 @@ public:
std::string get_identifier () const { return identifier; }
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
bool is_equal (const BaseType &other) const override;
size_t num_params () const { return params.size (); }
@@ -940,6 +1138,11 @@ public:
bool is_variadic () const { return (flags & FNTYPE_IS_VARADIC_FLAG) != 0; }
+ bool is_syn_constant () const
+ {
+ return (flags & FNTYPE_IS_SYN_CONST_FLAG) != 0;
+ }
+
DefId get_id () const { return id; }
// get the Self type for the method
@@ -995,19 +1198,22 @@ public:
static constexpr auto KIND = TypeKind::FNPTR;
FnPtr (HirId ref, location_t locus, std::vector<TyVar> params,
- TyVar result_type, std::set<HirId> refs = std::set<HirId> ())
+ TyVar result_type, ABI abi, Unsafety unsafety,
+ std::set<HirId> refs = std::set<HirId> ())
: CallableTypeInterface (ref, ref, TypeKind::FNPTR,
{Resolver::CanonicalPath::create_empty (), locus},
refs),
- params (std::move (params)), result_type (result_type)
+ params (std::move (params)), result_type (result_type), abi (abi),
+ unsafety (unsafety)
{}
FnPtr (HirId ref, HirId ty_ref, location_t locus, std::vector<TyVar> params,
- TyVar result_type, std::set<HirId> refs = std::set<HirId> ())
+ TyVar result_type, ABI abi, Unsafety unsafety,
+ std::set<HirId> refs = std::set<HirId> ())
: CallableTypeInterface (ref, ty_ref, TypeKind::FNPTR,
{Resolver::CanonicalPath::create_empty (), locus},
refs),
- params (params), result_type (result_type)
+ params (params), result_type (result_type), abi (abi), unsafety (unsafety)
{}
std::string get_name () const override final { return as_string (); }
@@ -1036,8 +1242,6 @@ public:
std::string as_string () const override;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
@@ -1045,9 +1249,17 @@ public:
std::vector<TyVar> &get_params () { return params; }
const std::vector<TyVar> &get_params () const { return params; }
+ ABI get_abi () const { return abi; }
+
+ Unsafety get_unsafety () const { return unsafety; }
+
+ FnPtr *handle_substitions (SubstitutionArgumentMappings &mappings);
+
private:
std::vector<TyVar> params;
TyVar result_type;
+ ABI abi;
+ Unsafety unsafety;
};
class ClosureType : public CallableTypeInterface, public SubstitutionRef
@@ -1113,8 +1325,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final { return as_string (); }
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
@@ -1143,19 +1353,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, TyVar 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, TyVar 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;
@@ -1165,8 +1374,6 @@ public:
std::string get_name () const override final { return as_string (); }
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
bool is_equal (const BaseType &other) const override;
BaseType *get_element_type () const;
@@ -1174,15 +1381,14 @@ public:
BaseType *clone () const final override;
- HIR::Expr &get_capacity_expr () const { return capacity_expr; }
+ BaseType *get_capacity () const;
+ const TyVar &get_capacity_var () 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;
+ TyVar capacity;
};
class SliceType : public BaseType
@@ -1211,8 +1417,6 @@ public:
std::string get_name () const override final { return as_string (); }
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
bool is_equal (const BaseType &other) const override;
BaseType *get_element_type () const;
@@ -1241,8 +1445,6 @@ public:
std::string get_name () const override final;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
BaseType *clone () const final override;
};
@@ -1271,8 +1473,6 @@ public:
std::string get_name () const override final;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
IntKind get_int_kind () const;
BaseType *clone () const final override;
@@ -1309,8 +1509,6 @@ public:
std::string get_name () const override final;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
UintKind get_uint_kind () const;
BaseType *clone () const final override;
@@ -1343,8 +1541,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
FloatKind get_float_kind () const;
BaseType *clone () const final override;
@@ -1370,8 +1566,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
BaseType *clone () const final override;
};
@@ -1390,8 +1584,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
BaseType *clone () const final override;
};
@@ -1409,8 +1601,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
BaseType *clone () const final override;
};
@@ -1429,8 +1619,6 @@ public:
std::string as_string () const override;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
@@ -1454,8 +1642,6 @@ public:
std::string as_string () const override;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
@@ -1490,8 +1676,6 @@ public:
std::string get_name () const override final;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
@@ -1534,8 +1718,6 @@ public:
std::string as_string () const override;
std::string get_name () const override final;
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
@@ -1581,8 +1763,6 @@ public:
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_name () const override final;
@@ -1605,8 +1785,6 @@ public:
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_name () const override final;
@@ -1656,8 +1834,6 @@ public:
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_name () const override final;
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 294b677..36dbc0e 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -17,35 +17,53 @@
// <http://www.gnu.org/licenses/>.
#include "rust-unify.h"
+#include "fold-const.h"
+#include "rust-tyty-util.h"
+#include "rust-tyty.h"
namespace Rust {
namespace Resolver {
+static TyTy::BaseType *
+unify_error_type_node ()
+{
+ static TyTy::BaseType *error = nullptr;
+ if (error == nullptr)
+ error = new TyTy::ErrorType (0);
+ return error;
+}
+
UnifyRules::UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
location_t locus, bool commit_flag, bool emit_error,
- bool infer, std::vector<CommitSite> &commits,
+ bool check_bounds, bool infer,
+ std::vector<CommitSite> &commits,
std::vector<InferenceSite> &infers)
: lhs (lhs), rhs (rhs), locus (locus), commit_flag (commit_flag),
- emit_error (emit_error), infer_flag (infer), commits (commits),
- infers (infers), mappings (Analysis::Mappings::get ()),
- context (*TypeCheckContext::get ())
+ emit_error (emit_error), infer_flag (infer),
+ check_bounds_flag (check_bounds), commits (commits), infers (infers),
+ mappings (Analysis::Mappings::get ()), context (*TypeCheckContext::get ())
{}
TyTy::BaseType *
UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
location_t locus, bool commit_flag, bool emit_error,
- bool infer, std::vector<CommitSite> &commits,
+ bool check_bounds, bool infer,
+ std::vector<CommitSite> &commits,
std::vector<InferenceSite> &infers)
{
- UnifyRules r (lhs, rhs, locus, commit_flag, emit_error, infer, commits,
- infers);
+ UnifyRules r (lhs, rhs, locus, commit_flag, emit_error, infer, check_bounds,
+ commits, infers);
TyTy::BaseType *result = r.go ();
- commits.push_back ({lhs.get_ty (), rhs.get_ty (), result});
- if (r.commit_flag)
- UnifyRules::commit (lhs.get_ty (), rhs.get_ty (), result);
-
bool failed = result->get_kind () == TyTy::TypeKind::ERROR;
+
+ commits.emplace_back (lhs.get_ty (), rhs.get_ty (), result);
+ if (r.commit_flag && !failed)
+ {
+ result = result->clone ();
+ UnifyRules::commit (lhs.get_ty (), rhs.get_ty (), result);
+ }
+
if (failed && r.emit_error)
r.emit_type_mismatch ();
@@ -53,6 +71,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,
+ check_bounds_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 +103,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 ();
@@ -86,28 +119,58 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other,
b->append_reference (resolved->get_ref ());
b->append_reference (o->get_ref ());
- bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER;
- bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER;
- bool results_is_non_general_infer_var
- = (result_is_infer_var
- && (static_cast<TyTy::InferType *> (resolved))->get_infer_kind ()
- != TyTy::InferType::GENERAL);
- if (result_resolved || results_is_non_general_infer_var)
+ if (resolved->get_kind () != TyTy::TypeKind::CONST)
{
- for (auto &ref : resolved->get_combined_refs ())
+ bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER;
+ bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER;
+ bool results_is_non_general_infer_var
+ = (result_is_infer_var
+ && (static_cast<TyTy::InferType *> (resolved))->get_infer_kind ()
+ != TyTy::InferType::GENERAL);
+ if (result_resolved || results_is_non_general_infer_var)
{
- TyTy::BaseType *ref_tyty = nullptr;
- bool ok = context.lookup_type (ref, &ref_tyty);
- if (!ok)
- continue;
+ for (auto &ref : resolved->get_combined_refs ())
+ {
+ TyTy::BaseType *ref_tyty = nullptr;
+ bool ok = context.lookup_type (ref, &ref_tyty);
+ if (!ok)
+ continue;
+
+ // if any of the types are inference variables lets fix them
+ if (ref_tyty->is<TyTy::InferType> ())
+ context.insert_implicit_type (ref, resolved);
+ }
+ }
+ }
+ else
+ {
+ auto base_const = resolved->as_const_type ();
+ if (base_const->const_kind () == TyTy::BaseConstType::ConstKind::Value)
+ {
+ rust_debug ("UnifyRules::commit const value, resolved_ref=%u "
+ "resolved_ty_ref=%u combined_refs.size=%zu",
+ resolved->get_ref (), resolved->get_ty_ref (),
+ resolved->get_combined_refs ().size ());
- // if any of the types are inference variables lets fix them
- if (ref_tyty->get_kind () == TyTy::TypeKind::INFER)
+ for (auto &ref : resolved->get_combined_refs ())
{
- auto node = Analysis::NodeMapping (mappings.get_current_crate (),
- UNKNOWN_NODEID, ref,
- UNKNOWN_LOCAL_DEFID);
- context.insert_type (node, resolved->clone ());
+ TyTy::BaseType *ref_tyty = nullptr;
+ bool ok = context.lookup_type (ref, &ref_tyty);
+ if (!ok)
+ continue;
+ if (ref_tyty->get_kind () != TyTy::TypeKind::CONST)
+ continue;
+
+ auto ref_base_const = ref_tyty->as_const_type ();
+ if (ref_base_const->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Infer
+ || ref_base_const->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Decl)
+ {
+ rust_debug (" committing to ref=%u kind=%d", ref,
+ (int) ref_base_const->const_kind ());
+ context.insert_implicit_type (ref, resolved);
+ }
}
}
}
@@ -142,39 +205,40 @@ UnifyRules::emit_abi_mismatch (const TyTy::FnType &expected,
TyTy::BaseType *
UnifyRules::go ()
{
- TyTy::BaseType *ltype = lhs.get_ty ();
- TyTy::BaseType *rtype = rhs.get_ty ();
-
- ltype = lhs.get_ty ()->destructure ();
- rtype = rhs.get_ty ()->destructure ();
+ TyTy::BaseType *ltype = lhs.get_ty ()->destructure ();
+ TyTy::BaseType *rtype = rhs.get_ty ()->destructure ();
rust_debug ("unify::go ltype={%s} rtype={%s}", ltype->debug_str ().c_str (),
rtype->debug_str ().c_str ());
- // check bounds
- bool ltype_is_placeholder = ltype->get_kind () == TyTy::TypeKind::PLACEHOLDER;
- bool rtype_is_placeholder = rtype->get_kind () == TyTy::TypeKind::PLACEHOLDER;
- bool types_equal = ltype->is_equal (*rtype);
- bool should_check_bounds
- = !types_equal && !(ltype_is_placeholder || rtype_is_placeholder);
- if (should_check_bounds)
+ if (check_bounds_flag)
{
- if (ltype->num_specified_bounds () > 0)
+ bool ltype_is_placeholder
+ = ltype->get_kind () == TyTy::TypeKind::PLACEHOLDER;
+ bool rtype_is_placeholder
+ = rtype->get_kind () == TyTy::TypeKind::PLACEHOLDER;
+ bool types_equal = ltype->is_equal (*rtype);
+ bool should_check_bounds
+ = !types_equal && !(ltype_is_placeholder || rtype_is_placeholder);
+ if (should_check_bounds)
{
- if (!ltype->bounds_compatible (*rtype, locus, emit_error))
+ if (ltype->num_specified_bounds () > 0)
{
- // already emitted an error
- emit_error = false;
- return new TyTy::ErrorType (0);
+ if (!ltype->bounds_compatible (*rtype, locus, emit_error))
+ {
+ // already emitted an error
+ emit_error = false;
+ return unify_error_type_node ();
+ }
}
- }
- else if (rtype->num_specified_bounds () > 0)
- {
- if (!rtype->bounds_compatible (*ltype, locus, emit_error))
+ else if (rtype->num_specified_bounds () > 0)
{
- // already emitted an error
- emit_error = false;
- return new TyTy::ErrorType (0);
+ if (!rtype->bounds_compatible (*ltype, locus, emit_error))
+ {
+ // already emitted an error
+ emit_error = false;
+ return unify_error_type_node ();
+ }
}
}
}
@@ -209,7 +273,7 @@ UnifyRules::go ()
rust_assert (iv.get_tyty ()->get_kind () == TyTy::TypeKind::INFER);
TyTy::InferType *i = static_cast<TyTy::InferType *> (iv.get_tyty ());
- infers.push_back ({p->get_ref (), p->get_ty_ref (), p, i});
+ infers.emplace_back (p->get_ref (), p->get_ty_ref (), p, i);
// FIXME
// this is hacky to set the implicit param lets make this a function
@@ -226,7 +290,7 @@ UnifyRules::go ()
rust_assert (iv.get_tyty ()->get_kind () == TyTy::TypeKind::INFER);
TyTy::InferType *i = static_cast<TyTy::InferType *> (iv.get_tyty ());
- infers.push_back ({p->get_ref (), p->get_ty_ref (), p, i});
+ infers.emplace_back (p->get_ref (), p->get_ty_ref (), p, i);
// FIXME
// this is hacky to set the implicit param lets make this a function
@@ -235,6 +299,68 @@ UnifyRules::go ()
// set the rtype now to the new inference var
ltype = i;
}
+ else if (ltype->get_kind () == TyTy::TypeKind::CONST
+ && rtype->get_kind () == TyTy::TypeKind::CONST)
+ {
+ auto lhs = ltype->as_const_type ();
+ auto rhs = rtype->as_const_type ();
+
+ bool both_are_decls
+ = lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl
+ && rhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl;
+ bool have_decls
+ = lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl
+ || rhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl;
+
+ if (have_decls && !both_are_decls)
+ {
+ if (lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl)
+ {
+ auto l = lhs->as_base_type ()->get_locus ();
+ auto p = static_cast<TyTy::ConstParamType *> (lhs);
+ auto it = TyTy::TyVar::get_implicit_infer_var (l);
+ auto iv = TyTy::TyVar::get_implicit_const_infer_var (l, &it);
+ auto ivt = iv.get_tyty ();
+
+ infers.emplace_back (0, 0, nullptr, it.get_tyty ());
+ infers.emplace_back (ltype->get_ref (), ltype->get_ty_ref (),
+ p, ivt);
+
+ ltype = ivt;
+ p->set_ty_ref (ltype->get_ref ());
+ }
+ else if (rhs->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Decl)
+ {
+ auto l = rhs->as_base_type ()->get_locus ();
+ auto p = static_cast<TyTy::ConstParamType *> (rhs);
+ auto it = TyTy::TyVar::get_implicit_infer_var (l);
+ auto iv = TyTy::TyVar::get_implicit_const_infer_var (l, &it);
+ auto ivt = iv.get_tyty ();
+
+ infers.emplace_back (0, 0, nullptr, it.get_tyty ());
+ infers.emplace_back (rtype->get_ref (), rtype->get_ty_ref (),
+ p, ivt);
+
+ rtype = ivt;
+ p->set_ty_ref (rtype->get_ref ());
+ }
+ }
+ }
+ }
+
+ if (ltype->get_kind () != TyTy::TypeKind::CONST
+ && rtype->get_kind () == TyTy::TypeKind::CONST)
+ {
+ auto *rc = rtype->as_const_type ();
+ rtype = rc->get_specified_type ();
+ }
+
+ if (ltype->get_kind () == TyTy::TypeKind::CONST
+ && rtype->get_kind () != TyTy::TypeKind::CONST)
+ {
+ auto *lc = ltype->as_const_type ();
+ ltype = lc->get_specified_type ();
}
switch (ltype->get_kind ())
@@ -315,11 +441,14 @@ UnifyRules::go ()
case TyTy::OPAQUE:
return expect_opaque (static_cast<TyTy::OpaqueType *> (ltype), rtype);
+ case TyTy::CONST:
+ return expect_const (ltype->as_const_type (), rtype);
+
case TyTy::ERROR:
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -328,30 +457,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 ();
+ return rtype;
- 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,28 +493,32 @@ 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 ()
== TyTy::InferType::InferTypeKind::INTEGRAL);
if (is_valid)
{
- ltype->apply_primitive_type_hint (*rtype);
- return rtype->clone ();
+ if (commit_flag)
+ ltype->apply_primitive_type_hint (*rtype);
+ return rtype;
}
}
break;
- case TyTy::FLOAT: {
+ case TyTy::FLOAT:
+ {
bool is_valid = (ltype->get_infer_kind ()
== TyTy::InferType::InferTypeKind::GENERAL)
|| (ltype->get_infer_kind ()
== TyTy::InferType::InferTypeKind::FLOAT);
if (is_valid)
{
- ltype->apply_primitive_type_hint (*rtype);
- return rtype->clone ();
+ if (commit_flag)
+ ltype->apply_primitive_type_hint (*rtype);
+ return rtype;
}
}
break;
@@ -404,19 +540,21 @@ 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)
- return rtype->clone ();
+ return rtype;
}
break;
case TyTy::ERROR:
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -424,30 +562,32 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
break;
- case TyTy::ADT: {
+ case TyTy::ADT:
+ {
TyTy::ADTType &type = *static_cast<TyTy::ADTType *> (rtype);
if (ltype->get_adt_kind () != type.get_adt_kind ())
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
if (ltype->get_identifier ().compare (type.get_identifier ()) != 0)
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
if (ltype->number_of_variants () != type.number_of_variants ())
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
for (size_t i = 0; i < type.number_of_variants (); ++i)
@@ -457,7 +597,7 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
if (a->num_fields () != b->num_fields ())
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
for (size_t j = 0; j < a->num_fields (); j++)
@@ -469,14 +609,11 @@ 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);
+ return unify_error_type_node ();
}
}
}
@@ -495,19 +632,16 @@ 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);
+ return unify_error_type_node ();
}
}
}
- return type.clone ();
+ return ltype;
}
break;
@@ -533,10 +667,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -544,17 +679,18 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
break;
case TyTy::STR:
- return rtype->clone ();
+ return rtype;
case TyTy::ADT:
case TyTy::REF:
@@ -578,10 +714,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -589,28 +726,28 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
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);
+ return unify_error_type_node ();
}
// rust is permissive about mutablity here you can always go from
@@ -618,12 +755,10 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype)
bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true;
if (!mutability_ok)
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
- return new TyTy::ReferenceType (ltype->get_ref (), ltype->get_ty_ref (),
- TyTy::TyVar (base_resolved->get_ref ()),
- ltype->mutability ());
+ return ltype;
}
break;
@@ -649,10 +784,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -660,28 +796,28 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
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);
+ return unify_error_type_node ();
}
// rust is permissive about mutablity here you can always go from
@@ -689,12 +825,10 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype)
bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true;
if (!mutability_ok)
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
- return new TyTy::PointerType (ltype->get_ref (), ltype->get_ty_ref (),
- TyTy::TyVar (base_resolved->get_ref ()),
- ltype->mutability ());
+ return ltype;
}
break;
@@ -720,10 +854,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -731,16 +866,18 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
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,10 +919,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -793,30 +931,53 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
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 unify_error_type_node ();
+
+ auto ltype_cap = ltype->get_capacity ();
+ auto rtype_cap = type.get_capacity ();
+
+ // If either capacity is not a const type, return error
+ if (ltype_cap->get_kind () != TyTy::TypeKind::CONST
+ || rtype_cap->get_kind () != TyTy::TypeKind::CONST)
+ return unify_error_type_node ();
+
+ bool save_emit_error = emit_error;
+ emit_error = false;
+ TyTy::BaseType *capacity_unify
+ = resolve_subtype (TyTy::TyWithLocation (ltype_cap),
+ TyTy::TyWithLocation (rtype_cap));
+ emit_error = save_emit_error;
+
+ if (capacity_unify->get_kind () != TyTy::TypeKind::CONST)
+ return unify_error_type_node ();
+
+ auto capacity_type_unify = capacity_unify->as_const_type ();
+ if (capacity_type_unify->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Error)
+ return unify_error_type_node ();
+
+ return new TyTy::ArrayType (
+ type.get_ref (), type.get_ty_ref (), type.get_ident ().locus,
+ TyTy::TyVar (capacity_type_unify->as_base_type ()->get_ref ()),
+ TyTy::TyVar (element_unify->get_ref ()));
}
break;
@@ -842,10 +1003,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -853,29 +1015,25 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
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)
- {
- return new TyTy::SliceType (type.get_ref (), type.get_ty_ref (),
- type.get_ident ().locus,
- TyTy::TyVar (
- element_unify->get_ref ()));
- }
+ return ltype;
}
break;
@@ -901,10 +1059,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -912,20 +1071,22 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
break;
- case TyTy::FNDEF: {
+ case TyTy::FNDEF:
+ {
TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype);
if (ltype->num_params () != type.num_params ())
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
for (size_t i = 0; i < ltype->num_params (); i++)
@@ -933,24 +1094,20 @@ 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);
+ return unify_error_type_node ();
}
}
- 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);
+ return unify_error_type_node ();
}
// ABI match? see
@@ -961,12 +1118,12 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype)
{
emit_abi_mismatch (*ltype, type);
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
// DEF Id match? see https://github.com/Rust-GCC/gccrs/issues/2053
- return ltype->clone ();
+ return ltype;
}
break;
@@ -992,10 +1149,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1003,20 +1161,22 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
break;
- case TyTy::FNPTR: {
+ case TyTy::FNPTR:
+ {
TyTy::FnPtr &type = *static_cast<TyTy::FnPtr *> (rtype);
if (ltype->num_params () != type.num_params ())
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
for (size_t i = 0; i < ltype->num_params (); i++)
@@ -1024,48 +1184,53 @@ 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);
+ return unify_error_type_node ();
}
}
- 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);
+ return unify_error_type_node ();
}
- return ltype->clone ();
+ if (ltype->get_abi () != type.get_abi ())
+ {
+ return unify_error_type_node ();
+ }
+
+ if (ltype->get_unsafety () != type.get_unsafety ())
+ {
+ return unify_error_type_node ();
+ }
+
+ return ltype;
}
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);
+ return unify_error_type_node ();
}
if (ltype->num_params () != type.num_params ())
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
for (size_t i = 0; i < ltype->num_params (); i++)
@@ -1074,17 +1239,71 @@ 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 unify_error_type_node ();
+ }
+ }
+
+ // FIXME
+ //
+ // there is a bug in:
+ // testsuite/rust/compile/try-catch-unwind-{new,old}.rs I think the test
+ //
+ // case is wrong because it should be taking an FnOnce which probably
+ // didnt exist at the time in gccrs
+ //
+ // if (ltype->get_abi () != type.get_abi ())
+ // {
+ // return unify_error_type_node ();
+ // }
+
+ // FIXME fntype needs to track unsafe or not
+ // if (ltype->get_unsafety () != type.get_unsafety ())
+ // {
+ // return unify_error_type_node ();
+ // }
+
+ return ltype;
+ }
+ 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 unify_error_type_node ();
+ }
+
+ if (ltype->num_params () != type.get_num_params ())
+ {
+ return unify_error_type_node ();
+ }
+
+ for (size_t i = 0; i < ltype->num_params (); i++)
+ {
+ auto this_param = ltype->get_param_type_at (i);
+ auto other_param = type.get_param_type_at (i);
+
+ auto unified_param
+ = resolve_subtype (TyTy::TyWithLocation (this_param),
+ TyTy::TyWithLocation (other_param));
if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
}
- return ltype->clone ();
+ return ltype;
}
break;
@@ -1107,12 +1326,12 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1120,20 +1339,22 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
break;
- case TyTy::TUPLE: {
+ case TyTy::TUPLE:
+ {
TyTy::TupleType &type = *static_cast<TyTy::TupleType *> (rtype);
if (ltype->num_fields () != type.num_fields ())
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
std::vector<TyTy::TyVar> fields;
@@ -1143,18 +1364,15 @@ 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);
+ return unify_error_type_node ();
- fields.push_back (TyTy::TyVar (unified_ty->get_ref ()));
+ fields.emplace_back (unified_ty->get_ref ());
}
- return new TyTy::TupleType (type.get_ref (), type.get_ty_ref (),
- type.get_ident ().locus, fields);
+ return ltype;
}
break;
@@ -1180,10 +1398,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1191,20 +1410,22 @@ 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;
if (is_valid)
{
- r->apply_primitive_type_hint (*ltype);
- return ltype->clone ();
+ if (commit_flag)
+ r->apply_primitive_type_hint (*ltype);
+ return ltype;
}
}
break;
case TyTy::BOOL:
- return rtype->clone ();
+ return rtype;
case TyTy::CHAR:
case TyTy::INT:
@@ -1228,10 +1449,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1239,20 +1461,22 @@ 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;
if (is_valid)
{
- r->apply_primitive_type_hint (*ltype);
- return ltype->clone ();
+ if (commit_flag)
+ r->apply_primitive_type_hint (*ltype);
+ return ltype;
}
}
break;
case TyTy::CHAR:
- return rtype->clone ();
+ return rtype;
case TyTy::INT:
case TyTy::FLOAT:
@@ -1276,10 +1500,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1287,25 +1512,27 @@ 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
|| r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL;
if (is_valid)
{
- r->apply_primitive_type_hint (*ltype);
- return ltype->clone ();
+ if (commit_flag)
+ r->apply_primitive_type_hint (*ltype);
+ return ltype;
}
}
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)
- return new TyTy::IntType (type.get_ref (), type.get_ty_ref (),
- type.get_int_kind ());
+ return ltype;
}
break;
@@ -1331,10 +1558,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1342,25 +1570,27 @@ 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
|| r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL;
if (is_valid)
{
- r->apply_primitive_type_hint (*ltype);
- return ltype->clone ();
+ if (commit_flag)
+ r->apply_primitive_type_hint (*ltype);
+ return ltype;
}
}
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)
- return new TyTy::UintType (type.get_ref (), type.get_ty_ref (),
- type.get_uint_kind ());
+ return ltype;
}
break;
@@ -1386,10 +1616,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1397,25 +1628,27 @@ 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
|| r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT;
if (is_valid)
{
- r->apply_primitive_type_hint (*ltype);
- return ltype->clone ();
+ if (commit_flag)
+ r->apply_primitive_type_hint (*ltype);
+ return ltype;
}
}
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)
- return new TyTy::FloatType (type.get_ref (), type.get_ty_ref (),
- type.get_float_kind ());
+ return ltype;
}
break;
@@ -1441,10 +1674,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1452,20 +1686,22 @@ 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;
if (is_valid)
{
- r->apply_primitive_type_hint (*ltype);
- return ltype->clone ();
+ if (commit_flag)
+ r->apply_primitive_type_hint (*ltype);
+ return ltype;
}
}
break;
case TyTy::ISIZE:
- return rtype->clone ();
+ return rtype;
case TyTy::ADT:
case TyTy::STR:
@@ -1489,10 +1725,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1500,20 +1737,22 @@ 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;
if (is_valid)
{
- r->apply_primitive_type_hint (*ltype);
- return ltype->clone ();
+ if (commit_flag)
+ r->apply_primitive_type_hint (*ltype);
+ return ltype;
}
}
break;
case TyTy::USIZE:
- return rtype->clone ();
+ return rtype;
case TyTy::ADT:
case TyTy::STR:
@@ -1537,10 +1776,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1548,19 +1788,20 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
break;
default:
- return rtype->clone ();
+ return rtype;
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1569,17 +1810,18 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
break;
case TyTy::PLACEHOLDER:
- return ltype->clone ();
+ return ltype;
case TyTy::PROJECTION:
case TyTy::DYNAMIC:
@@ -1604,13 +1846,14 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype,
case TyTy::NEVER:
case TyTy::OPAQUE:
if (infer_flag)
- return rtype->clone ();
+ return rtype;
gcc_fallthrough ();
+ case TyTy::CONST:
case TyTy::ERROR:
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1619,12 +1862,13 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
break;
@@ -1655,10 +1899,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1666,29 +1911,31 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
break;
- case TyTy::DYNAMIC: {
+ case TyTy::DYNAMIC:
+ {
TyTy::DynamicObjectType &type
= *static_cast<TyTy::DynamicObjectType *> (rtype);
if (ltype->num_specified_bounds () != type.num_specified_bounds ())
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
if (!ltype->bounds_compatible (type, locus, true))
{
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
- return ltype->clone ();
+ return ltype;
}
break;
@@ -1714,10 +1961,11 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
TyTy::BaseType *
@@ -1725,41 +1973,41 @@ 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;
if (is_valid)
- return ltype->clone ();
+ return ltype;
}
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);
+ return unify_error_type_node ();
}
- 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);
+ return unify_error_type_node ();
}
- 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);
+ return unify_error_type_node ();
}
- return ltype->clone ();
+ return ltype;
}
break;
@@ -1785,68 +2033,162 @@ 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);
+ return unify_error_type_node ();
}
- return new TyTy::ErrorType (0);
+ return unify_error_type_node ();
}
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 unify_error_type_node ();
- 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))
- {
- return new TyTy::ErrorType (0);
- }
+ auto res = resolve_subtype (TyTy::TyWithLocation (lr),
+ TyTy::TyWithLocation (rr));
+ if (res->get_kind () == TyTy::TypeKind::ERROR)
+ return unify_error_type_node ();
+ }
+ 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 unify_error_type_node ();
+ }
+ else
+ {
+ ltype->set_ty_ref (rtype->get_ref ());
+ }
- return ltype->clone ();
- }
- break;
+ return ltype;
+}
- 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);
+TyTy::BaseType *
+UnifyRules::expect_const (TyTy::BaseConstType *ltype, TyTy::BaseType *rtype)
+{
+ if (rtype->get_kind () != TyTy::TypeKind::CONST)
+ return unify_error_type_node ();
+
+ auto &lhs = *ltype;
+ auto &rhs = *rtype->as_const_type ();
+
+ // Handle error types early
+ if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Error
+ || rhs.const_kind () == TyTy::BaseConstType::ConstKind::Error)
+ {
+ auto lhs_base = ltype->as_base_type ();
+ return new TyTy::ConstErrorType (lhs.get_specified_type (),
+ lhs_base->get_ref (),
+ lhs_base->get_ty_ref (),
+ lhs_base->get_combined_refs ());
}
- return new TyTy::ErrorType (0);
+
+ // Try to resolve Decl types (ConstParamType)
+ TyTy::BaseConstType *resolved_lhs = &lhs;
+ TyTy::BaseConstType *resolved_rhs = &rhs;
+
+ if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl)
+ {
+ auto *param = static_cast<TyTy::ConstParamType *> (&lhs);
+ if (param->can_resolve ())
+ {
+ auto *resolved = param->resolve ();
+ if (resolved->get_kind () == TyTy::TypeKind::CONST)
+ resolved_lhs = resolved->as_const_type ();
+ }
+ }
+
+ if (rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl)
+ {
+ auto *param = static_cast<TyTy::ConstParamType *> (&rhs);
+ if (param->can_resolve ())
+ {
+ auto *resolved = param->resolve ();
+ if (resolved->get_kind () == TyTy::TypeKind::CONST)
+ resolved_rhs = resolved->as_const_type ();
+ }
+ }
+
+ auto res = resolve_subtype (
+ TyTy::TyWithLocation (resolved_lhs->get_specified_type ()),
+ TyTy::TyWithLocation (resolved_rhs->get_specified_type ()));
+ if (res->get_kind () == TyTy::TypeKind::ERROR)
+ return unify_error_type_node ();
+
+ if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Value
+ && resolved_rhs->const_kind () == TyTy::BaseConstType::ConstKind::Value)
+ {
+ auto vlhs = static_cast<TyTy::ConstValueType &> (*resolved_lhs);
+ auto vrhs = static_cast<TyTy::ConstValueType &> (*resolved_rhs);
+ tree lv = vlhs.get_value ();
+ tree rv = vrhs.get_value ();
+
+ bool ok = operand_equal_p (lv, rv, 0);
+ if (!ok)
+ return unify_error_type_node ();
+ else
+ {
+ auto lhs_base = resolved_lhs->as_base_type ();
+ return new TyTy::ConstValueType (lv, res, lhs_base->get_ref (),
+ lhs_base->get_ty_ref (),
+ lhs_base->get_combined_refs ());
+ }
+ }
+ else if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Infer
+ && resolved_rhs->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Value)
+ return resolved_rhs->as_base_type ();
+ else if (resolved_rhs->const_kind () == TyTy::BaseConstType::ConstKind::Infer
+ && resolved_lhs->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Value)
+ return resolved_lhs->as_base_type ();
+ else if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Infer
+ && resolved_rhs->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Infer)
+ return resolved_lhs->as_base_type ();
+ else if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl
+ || resolved_rhs->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Decl)
+ {
+ // If we still have unresolved Decl after trying to resolve, unify with it
+ // This allows const inference to work
+ if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl
+ && resolved_rhs->const_kind ()
+ != TyTy::BaseConstType::ConstKind::Decl)
+ return resolved_rhs->as_base_type ();
+ else if (resolved_rhs->const_kind ()
+ == TyTy::BaseConstType::ConstKind::Decl
+ && resolved_lhs->const_kind ()
+ != TyTy::BaseConstType::ConstKind::Decl)
+ return resolved_lhs->as_base_type ();
+ // Both are Decl - return lhs
+ return resolved_lhs->as_base_type ();
+ }
+
+ return unify_error_type_node ();
}
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h
index 5ff3b7c..2b772fe 100644
--- a/gcc/rust/typecheck/rust-unify.h
+++ b/gcc/rust/typecheck/rust-unify.h
@@ -30,13 +30,23 @@ class UnifyRules
public:
struct InferenceSite
{
+ InferenceSite (HirId pref, HirId ptyref, TyTy::BaseGeneric *param,
+ TyTy::BaseType *infer)
+ : pref (pref), ptyref (ptyref), param (param), infer (infer)
+ {}
+
HirId pref;
HirId ptyref;
- TyTy::ParamType *param;
- TyTy::InferType *infer;
+ TyTy::BaseGeneric *param;
+ TyTy::BaseType *infer;
};
struct CommitSite
{
+ CommitSite (TyTy::BaseType *lhs, TyTy::BaseType *rhs,
+ TyTy::BaseType *resolved)
+ : lhs (lhs), rhs (rhs), resolved (resolved)
+ {}
+
TyTy::BaseType *lhs;
TyTy::BaseType *rhs;
TyTy::BaseType *resolved;
@@ -45,6 +55,7 @@ public:
static TyTy::BaseType *Resolve (TyTy::TyWithLocation lhs,
TyTy::TyWithLocation rhs, location_t locus,
bool commit_flag, bool emit_error, bool infer,
+ bool check_bounds,
std::vector<CommitSite> &commits,
std::vector<InferenceSite> &infers);
@@ -84,13 +95,18 @@ protected:
TyTy::BaseType *rtype);
TyTy::BaseType *expect_opaque (TyTy::OpaqueType *ltype,
TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_const (TyTy::BaseConstType *ltype,
+ TyTy::BaseType *rtype);
private:
UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
location_t locus, bool commit_flag, bool emit_error, bool infer,
- std::vector<CommitSite> &commits,
+ bool check_bounds, 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;
@@ -106,6 +122,7 @@ private:
bool commit_flag;
bool emit_error;
bool infer_flag;
+ bool check_bounds_flag;
std::vector<CommitSite> &commits;
std::vector<InferenceSite> &infers;
diff --git a/gcc/rust/util/bi-map.h b/gcc/rust/util/bi-map.h
index 54870f7..4af157f 100644
--- a/gcc/rust/util/bi-map.h
+++ b/gcc/rust/util/bi-map.h
@@ -17,6 +17,7 @@
// <http://www.gnu.org/licenses/>.
#include "rust-system.h"
+#include "optional.h"
#ifndef BIMAP_H
#define BIMAP_H
diff --git a/gcc/rust/util/expected.h b/gcc/rust/util/expected.h
index a9e3bc2..07ba877 100644
--- a/gcc/rust/util/expected.h
+++ b/gcc/rust/util/expected.h
@@ -212,10 +212,8 @@ template <typename E>
throw std::forward<E>(e);
#else
(void)e;
-#ifdef _MSC_VER
gcc_unreachable();
#endif
-#endif
}
#ifndef TL_TRAITS_MUTEX
@@ -2437,4 +2435,4 @@ void swap(expected<T, E> &lhs,
}
} // namespace tl
-#endif \ No newline at end of file
+#endif
diff --git a/gcc/rust/util/fnv-hash.h b/gcc/rust/util/fnv-hash.h
index 6d2ec01..e51b66a 100644
--- a/gcc/rust/util/fnv-hash.h
+++ b/gcc/rust/util/fnv-hash.h
@@ -15,6 +15,7 @@
// 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-system.h"
#ifndef RUST_FNV_HASH_H
#define RUST_FNV_HASH_H
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 9ef5cc5..0f35f56 100644
--- a/gcc/rust/util/rust-attribute-values.h
+++ b/gcc/rust/util/rust-attribute-values.h
@@ -36,16 +36,19 @@ public:
static constexpr auto &DOC = "doc";
static constexpr auto &MUST_USE = "must_use";
static constexpr auto &LANG = "lang";
+ static constexpr auto &LINK_NAME = "link_name";
static constexpr auto &LINK_SECTION = "link_section";
static constexpr auto &NO_MANGLE = "no_mangle";
static constexpr auto &REPR = "repr";
static constexpr auto &RUSTC_BUILTIN_MACRO = "rustc_builtin_macro";
+ static constexpr auto &RUSTC_MACRO_TRANSPARENCY = "rustc_macro_transparency";
static constexpr auto &PATH = "path";
static constexpr auto &MACRO_USE = "macro_use";
static constexpr auto &MACRO_EXPORT = "macro_export";
static constexpr auto &PROC_MACRO = "proc_macro";
static constexpr auto &PROC_MACRO_DERIVE = "proc_macro_derive";
static constexpr auto &PROC_MACRO_ATTRIBUTE = "proc_macro_attribute";
+
static constexpr auto &TARGET_FEATURE = "target_feature";
// From now on, these are reserved by the compiler and gated through
// #![feature(rustc_attrs)]
@@ -54,10 +57,42 @@ public:
= "rustc_inherit_overflow_checks";
static constexpr auto &STABLE = "stable";
static constexpr auto &UNSTABLE = "unstable";
+
+ static constexpr auto &RUSTC_PROMOTABLE = "rustc_promotable";
static constexpr auto &RUSTC_CONST_STABLE = "rustc_const_stable";
static constexpr auto &RUSTC_CONST_UNSTABLE = "rustc_const_unstable";
+ static constexpr auto &RUSTC_ALLOW_CONST_FN_UNSTABLE
+ = "rustc_allow_const_fn_unstable";
+
+ static constexpr auto &RUSTC_SPECIALIZATION_TRAIT
+ = "rustc_specialization_trait";
+ static constexpr auto &RUSTC_UNSAFE_SPECIALIZATION_MARKER
+ = "rustc_unsafe_specialization_marker";
+ static constexpr auto &RUSTC_RESERVATION_IMPL = "rustc_reservation_impl";
+ static constexpr auto &RUSTC_PAREN_SUGAR = "rustc_paren_sugar";
+ static constexpr auto &RUSTC_NONNULL_OPTIMIZATION_GUARANTEED
+ = "rustc_nonnull_optimization_guaranteed";
+
+ static constexpr auto &RUSTC_LAYOUT_SCALAR_VALID_RANGE_START
+ = "rustc_layout_scalar_valid_range_start";
+
static constexpr auto &MAY_DANGLE = "may_dangle";
static constexpr auto &PRELUDE_IMPORT = "prelude_import";
+ static constexpr auto &TRACK_CALLER = "track_caller";
+
+ static constexpr auto &RUSTC_DIAGNOSTIC_ITEM = "rustc_diagnostic_item";
+ static constexpr auto &RUSTC_ON_UNIMPLEMENTED = "rustc_on_unimplemented";
+
+ static constexpr auto &FUNDAMENTAL = "fundamental";
+
+ static constexpr auto &NON_EXHAUSTIVE = "non_exhaustive";
+
+ static constexpr auto &RUSTFMT = "rustfmt";
+
+ static constexpr auto &TEST = "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 03452c7..70f26e7 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -38,6 +38,31 @@ Attributes::is_known (const std::string &attribute_path)
return !lookup.is_error ();
}
+tl::optional<std::string>
+Attributes::extract_string_literal (const AST::Attribute &attr)
+{
+ if (!attr.has_attr_input ())
+ return tl::nullopt;
+
+ auto &attr_input = attr.get_attr_input ();
+
+ if (attr_input.get_attr_input_type ()
+ != AST::AttrInput::AttrInputType::LITERAL)
+ return tl::nullopt;
+
+ auto &literal_expr
+ = static_cast<AST::AttrInputLiteral &> (attr_input).get_literal ();
+
+ auto lit_type = literal_expr.get_lit_type ();
+
+ // TODO: bring escape sequence handling out of lexing?
+ if (lit_type != AST::Literal::LitType::STRING
+ && lit_type != AST::Literal::LitType::RAW_STRING)
+ return tl::nullopt;
+
+ return literal_expr.as_string ();
+}
+
using Attrs = Values::Attributes;
// https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_feature/builtin_attrs.rs.html#248
@@ -53,10 +78,12 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::DOC, HIR_LOWERING},
{Attrs::MUST_USE, STATIC_ANALYSIS},
{Attrs::LANG, HIR_LOWERING},
+ {Attrs::LINK_NAME, CODE_GENERATION},
{Attrs::LINK_SECTION, CODE_GENERATION},
{Attrs::NO_MANGLE, CODE_GENERATION},
{Attrs::REPR, CODE_GENERATION},
{Attrs::RUSTC_BUILTIN_MACRO, EXPANSION},
+ {Attrs::RUSTC_MACRO_TRANSPARENCY, EXPANSION},
{Attrs::PATH, EXPANSION},
{Attrs::MACRO_USE, NAME_RESOLUTION},
{Attrs::MACRO_EXPORT, NAME_RESOLUTION},
@@ -73,9 +100,32 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::STABLE, STATIC_ANALYSIS},
{Attrs::UNSTABLE, STATIC_ANALYSIS},
// assuming we keep these for static analysis
+ {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION},
{Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS},
{Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS},
- {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION}};
+ {Attrs::RUSTC_ALLOW_CONST_FN_UNSTABLE, STATIC_ANALYSIS},
+ {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
+ {Attrs::TRACK_CALLER, CODE_GENERATION},
+ {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK},
+ {Attrs::RUSTC_UNSAFE_SPECIALIZATION_MARKER, TYPE_CHECK},
+ {Attrs::RUSTC_RESERVATION_IMPL, TYPE_CHECK},
+ {Attrs::RUSTC_PAREN_SUGAR, TYPE_CHECK},
+ {Attrs::RUSTC_NONNULL_OPTIMIZATION_GUARANTEED, TYPE_CHECK},
+ {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},
+ {Attrs::RUSTC_ON_UNIMPLEMENTED, STATIC_ANALYSIS},
+ {Attrs::FUNDAMENTAL, TYPE_CHECK},
+ {Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
+ {Attrs::RUSTFMT, EXTERNAL},
+ {Attrs::TEST, CODE_GENERATION}};
+
+static const std::set<std::string> __outer_attributes
+ = {Attrs::INLINE, Attrs::DERIVE_ATTR, Attrs::ALLOW_INTERNAL_UNSTABLE,
+ Attrs::LANG, Attrs::REPR, Attrs::PATH,
+ Attrs::TARGET_FEATURE, Attrs::TEST};
BuiltinAttributeMappings *
BuiltinAttributeMappings::get ()
@@ -118,6 +168,7 @@ AttributeChecker::go (AST::Crate &crate)
void
AttributeChecker::visit (AST::Crate &crate)
{
+ check_inner_attributes (crate.get_inner_attrs ());
check_attributes (crate.get_inner_attrs ());
for (auto &item : crate.items)
@@ -188,8 +239,8 @@ check_doc_attribute (const AST::Attribute &attribute)
{
rust_error_at (
attribute.get_locus (),
- // FIXME: Improve error message here. Rustc has a very good one
- "%<#[doc]%> cannot be an empty attribute");
+ "valid forms for the attribute are "
+ "%<#[doc(hidden|inline|...)]%> and %<#[doc = \" string \"]%>");
return;
}
@@ -201,7 +252,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 ());
@@ -271,8 +323,42 @@ check_proc_macro_non_root (AST::AttrVec attributes, location_t loc)
}
void
+AttributeChecker::check_inner_attribute (const AST::Attribute &attribute)
+{
+ BuiltinAttrDefinition result;
+
+ if (!is_builtin (attribute, result))
+ return;
+
+ if (__outer_attributes.find (result.name) != __outer_attributes.end ())
+ rust_error_at (attribute.get_locus (),
+ "attribute cannot be used at crate level");
+}
+
+void
+AttributeChecker::check_inner_attributes (const AST::AttrVec &attributes)
+{
+ for (auto &attr : attributes)
+ check_inner_attribute (attr);
+}
+
+void
AttributeChecker::check_attribute (const AST::Attribute &attribute)
{
+ if (!attribute.empty_input ())
+ {
+ const auto &attr_input = attribute.get_attr_input ();
+ auto type = attr_input.get_attr_input_type ();
+ if (type == AST::AttrInput::AttrInputType::TOKEN_TREE)
+ {
+ const auto &option = static_cast<const AST::DelimTokenTree &> (
+ attribute.get_attr_input ());
+ std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item (
+ option.parse_to_meta_item ());
+ AST::DefaultASTVisitor::visit (meta_item);
+ }
+ }
+
BuiltinAttrDefinition result;
// This checker does not check non-builtin attributes
@@ -302,10 +388,6 @@ AttributeChecker::visit (AST::DelimTokenTree &)
{}
void
-AttributeChecker::visit (AST::AttrInputMetaItemContainer &)
-{}
-
-void
AttributeChecker::visit (AST::IdentifierExpr &)
{}
@@ -368,8 +450,16 @@ AttributeChecker::visit (AST::MetaItemLitExpr &)
{}
void
-AttributeChecker::visit (AST::MetaItemPathLit &)
-{}
+AttributeChecker::visit (AST::MetaItemPathExpr &attribute)
+{
+ if (!attribute.get_expr ().is_literal ())
+ {
+ rust_error_at (attribute.get_expr ().get_locus (),
+ "malformed %<path%> attribute input");
+ rust_inform (attribute.get_expr ().get_locus (),
+ "must be of the form: %<#[path = \"file\"]%>");
+ }
+}
void
AttributeChecker::visit (AST::BorrowExpr &)
@@ -595,6 +685,7 @@ AttributeChecker::visit (AST::TypeBoundWhereClauseItem &)
void
AttributeChecker::visit (AST::Module &module)
{
+ check_attributes (module.get_outer_attrs ());
check_proc_macro_non_function (module.get_outer_attrs ());
for (auto &item : module.get_items ())
{
@@ -747,10 +838,6 @@ AttributeChecker::visit (AST::StaticItem &item)
}
void
-AttributeChecker::visit (AST::TraitItemConst &)
-{}
-
-void
AttributeChecker::visit (AST::TraitItemType &)
{}
@@ -758,6 +845,7 @@ void
AttributeChecker::visit (AST::Trait &trait)
{
check_proc_macro_non_function (trait.get_outer_attrs ());
+ check_attributes (trait.get_outer_attrs ());
}
void
@@ -814,10 +902,6 @@ AttributeChecker::visit (AST::MetaItemPath &)
{}
void
-AttributeChecker::visit (AST::MetaItemSeq &)
-{}
-
-void
AttributeChecker::visit (AST::MetaWord &)
{}
@@ -893,11 +977,11 @@ AttributeChecker::visit (AST::StructPattern &)
// void AttributeChecker::visit(TupleStructItems& ){}
void
-AttributeChecker::visit (AST::TupleStructItemsNoRange &)
+AttributeChecker::visit (AST::TupleStructItemsNoRest &)
{}
void
-AttributeChecker::visit (AST::TupleStructItemsRange &)
+AttributeChecker::visit (AST::TupleStructItemsHasRest &)
{}
void
@@ -907,11 +991,11 @@ AttributeChecker::visit (AST::TupleStructPattern &)
// void AttributeChecker::visit(TuplePatternItems& ){}
void
-AttributeChecker::visit (AST::TuplePatternItemsMultiple &)
+AttributeChecker::visit (AST::TuplePatternItemsNoRest &)
{}
void
-AttributeChecker::visit (AST::TuplePatternItemsRanged &)
+AttributeChecker::visit (AST::TuplePatternItemsHasRest &)
{}
void
diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h
index c928c8e..f4a2d38 100644
--- a/gcc/rust/util/rust-attributes.h
+++ b/gcc/rust/util/rust-attributes.h
@@ -29,6 +29,8 @@ class Attributes
{
public:
static bool is_known (const std::string &attribute_path);
+ static tl::optional<std::string>
+ extract_string_literal (const AST::Attribute &attr);
};
enum CompilerPass
@@ -40,7 +42,12 @@ enum CompilerPass
HIR_LOWERING,
TYPE_CHECK,
STATIC_ANALYSIS,
- CODE_GENERATION
+ CODE_GENERATION,
+
+ // External Rust tooling attributes, like #[rustfmt::skip]
+ EXTERNAL,
+
+ // Do we need to add something here for const fns?
};
struct BuiltinAttrDefinition
@@ -95,9 +102,13 @@ public:
private:
using AST::DefaultASTVisitor::visit;
+
+ /* Check the validity of an inner attribute */
+ void check_inner_attribute (const AST::Attribute &attribute);
+ /* Check the validy of all inner attributes */
+ void check_inner_attributes (const AST::AttrVec &attributes);
/* Check the validity of a given attribute */
void check_attribute (const AST::Attribute &attribute);
-
/* Check the validity of all given attributes */
void check_attributes (const AST::AttrVec &attributes);
@@ -105,7 +116,6 @@ private:
void visit (AST::Crate &crate) override;
void visit (AST::Token &tok) override;
void visit (AST::DelimTokenTree &delim_tok_tree) override;
- void visit (AST::AttrInputMetaItemContainer &input) override;
void visit (AST::IdentifierExpr &ident_expr) override;
void visit (AST::Lifetime &lifetime) override;
void visit (AST::LifetimeParam &lifetime_param) override;
@@ -125,7 +135,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;
@@ -198,7 +208,6 @@ private:
void visit (AST::Union &union_item) override;
void visit (AST::ConstantItem &const_item) override;
void visit (AST::StaticItem &static_item) override;
- void visit (AST::TraitItemConst &item) override;
void visit (AST::TraitItemType &item) override;
void visit (AST::Trait &trait) override;
void visit (AST::InherentImpl &impl) override;
@@ -214,7 +223,6 @@ private:
void visit (AST::MacroRulesDefinition &rules_def) override;
void visit (AST::MacroInvocation &macro_invoc) override;
void visit (AST::MetaItemPath &meta_item) override;
- void visit (AST::MetaItemSeq &meta_item) override;
void visit (AST::MetaWord &meta_item) override;
void visit (AST::MetaNameValueStr &meta_item) override;
void visit (AST::MetaListPaths &meta_item) override;
@@ -237,12 +245,12 @@ private:
void visit (AST::StructPatternFieldIdent &field) override;
void visit (AST::StructPattern &pattern) override;
// void visit(TupleStructItems& tuple_items) override;
- void visit (AST::TupleStructItemsNoRange &tuple_items) override;
- void visit (AST::TupleStructItemsRange &tuple_items) override;
+ void visit (AST::TupleStructItemsNoRest &tuple_items) override;
+ void visit (AST::TupleStructItemsHasRest &tuple_items) override;
void visit (AST::TupleStructPattern &pattern) override;
// void visit(TuplePatternItems& tuple_items) override;
- void visit (AST::TuplePatternItemsMultiple &tuple_items) override;
- void visit (AST::TuplePatternItemsRanged &tuple_items) override;
+ void visit (AST::TuplePatternItemsNoRest &tuple_items) override;
+ void visit (AST::TuplePatternItemsHasRest &tuple_items) override;
void visit (AST::TuplePattern &pattern) override;
void visit (AST::GroupedPattern &pattern) override;
void visit (AST::SlicePattern &pattern) 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..4c4d9df 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
@@ -109,6 +114,8 @@ public:
return CanonicalPath (other.segs, crate_num);
std::vector<std::pair<NodeId, std::string>> copy (segs);
+ copy.reserve (other.segs.size ());
+
for (auto &s : other.segs)
copy.push_back (s);
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-dump.h b/gcc/rust/util/rust-dump.h
index c2d9c4d..111174b 100644
--- a/gcc/rust/util/rust-dump.h
+++ b/gcc/rust/util/rust-dump.h
@@ -16,6 +16,8 @@
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+#include "rust-system.h"
+
// Common definitions useful for textual dump of IRs (AST and HIR).
#ifndef RUST_DUMP_H
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..46220a2
--- /dev/null
+++ b/gcc/rust/util/rust-ggc.cc
@@ -0,0 +1,44 @@
+// 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 "rust-ast.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 ()))
+{}
+
+Ident::Ident (const Rust::Identifier &ident) : Ident (ident.as_string ()) {}
+
+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..da4ede1
--- /dev/null
+++ b/gcc/rust/util/rust-ggc.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/>.
+
+#ifndef RUST_GGC_H
+#define RUST_GGC_H
+
+#include "rust-system.h"
+#include "tree.h"
+
+namespace Rust {
+
+// forward declare
+class Identifier;
+
+namespace GGC {
+
+class Ident
+{
+ tree inner;
+
+public:
+ Ident (const char *str);
+ Ident (const std::string &str);
+ Ident (const Rust::Identifier &ident);
+
+ 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..a6d323e 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -925,10 +925,10 @@ Mappings::lookup_macro_invocation (AST::MacroInvocation &invoc)
void
Mappings::insert_exported_macro (AST::MacroRulesDefinition &def)
{
- exportedMacros.emplace_back (def.get_node_id ());
+ exportedMacros.emplace_back (def);
}
-std::vector<NodeId> &
+std::vector<AST::MacroRulesDefinition>
Mappings::get_exported_macros ()
{
return exportedMacros;
@@ -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};
@@ -1356,5 +1358,17 @@ Mappings::lookup_captures (NodeId closure)
return cap->second;
}
+void
+Mappings::add_derived_node (NodeId node_id)
+{
+ derived_nodes.insert (node_id);
+}
+
+bool
+Mappings::is_derived_node (NodeId node_id)
+{
+ return derived_nodes.find (node_id) != derived_nodes.end ();
+}
+
} // namespace Analysis
} // namespace Rust
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index b523a36..60066d6 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -279,7 +279,7 @@ public:
lookup_macro_invocation (AST::MacroInvocation &invoc);
void insert_exported_macro (AST::MacroRulesDefinition &def);
- std::vector<NodeId> &get_exported_macros ();
+ std::vector<AST::MacroRulesDefinition> get_exported_macros ();
void insert_derive_proc_macros (CrateNum num,
std::vector<CustomDeriveProcMacro> macros);
@@ -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);
@@ -350,6 +350,9 @@ public:
void add_capture (NodeId closure, NodeId definition);
tl::optional<std::vector<NodeId>> lookup_captures (NodeId closure);
+ void add_derived_node (NodeId node_id);
+ bool is_derived_node (NodeId node_id);
+
private:
Mappings ();
@@ -408,7 +411,7 @@ private:
std::map<NodeId, std::pair<AST::MacroRulesDefinition *, CrateNum>>
macroMappings;
std::map<NodeId, AST::MacroRulesDefinition *> macroInvocations;
- std::vector<NodeId> exportedMacros;
+ std::vector<AST::MacroRulesDefinition> exportedMacros;
// Procedural macros
std::map<CrateNum, std::vector<CustomDeriveProcMacro>>
@@ -436,13 +439,15 @@ 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;
// Closure AST NodeId -> vector of Definition node ids
std::unordered_map<NodeId, std::vector<NodeId>> captures;
+
+ std::set<NodeId> derived_nodes;
};
} // namespace Analysis
diff --git a/gcc/rust/util/rust-inline-visitor.h b/gcc/rust/util/rust-inline-visitor.h
index 2a35aa6..a00cd2c 100644
--- a/gcc/rust/util/rust-inline-visitor.h
+++ b/gcc/rust/util/rust-inline-visitor.h
@@ -15,6 +15,7 @@
// 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-system.h"
// An improved implementation of the inline visitor.
// Original idea from https://members.accu.org/index.php/articles/2021
diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc
index a76cc7f..9aff31b 100644
--- a/gcc/rust/util/rust-lang-item.cc
+++ b/gcc/rust/util/rust-lang-item.cc
@@ -118,6 +118,7 @@ const BiMap<std::string, LangItem::Kind> Rust::LangItem::lang_items = {{
{"discriminant_kind", Kind::DISCRIMINANT_KIND},
{"discriminant_type", Kind::DISCRIMINANT_TYPE},
+ {"manually_drop", Kind::MANUALLY_DROP},
}};
tl::optional<LangItem::Kind>
diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index 8f3af36..7b9f498 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -21,6 +21,9 @@
#include "optional.h"
#include "bi-map.h"
+#ifndef RUST_LANG_ITEM_H
+#define RUST_LANG_ITEM_H
+
namespace Rust {
class LangItem
@@ -150,6 +153,8 @@ public:
DISCRIMINANT_TYPE,
DISCRIMINANT_KIND,
+
+ MANUALLY_DROP,
};
static const BiMap<std::string, Kind> lang_items;
@@ -183,3 +188,5 @@ template <> struct hash<Rust::LangItem::Kind>
}
};
} // namespace std
+
+#endif // RUST_LANG_ITEM_H
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-stacked-contexts.h b/gcc/rust/util/rust-stacked-contexts.h
index fe0bc8a..b263d75 100644
--- a/gcc/rust/util/rust-stacked-contexts.h
+++ b/gcc/rust/util/rust-stacked-contexts.h
@@ -71,7 +71,14 @@ public:
return last;
}
- const T &peek ()
+ const T &peek () const
+ {
+ rust_assert (!stack.empty ());
+
+ return stack.back ();
+ }
+
+ T &peek ()
{
rust_assert (!stack.empty ());
diff --git a/gcc/rust/util/rust-token-converter.cc b/gcc/rust/util/rust-token-converter.cc
index fc34adb..0865bf9 100644
--- a/gcc/rust/util/rust-token-converter.cc
+++ b/gcc/rust/util/rust-token-converter.cc
@@ -102,7 +102,9 @@ ProcMacro::TokenStream
convert (const std::vector<const_TokenPtr> &tokens)
{
std::vector<ProcMacro::TokenStream> trees;
- trees.push_back (ProcMacro::TokenStream::make_tokenstream ());
+ trees.reserve (tokens.size ());
+
+ trees.emplace_back (ProcMacro::TokenStream::make_tokenstream ());
for (auto &token : tokens)
{
auto loc = convert (token->get_locus ());
@@ -202,7 +204,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 +263,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..ccc1e61 100644
--- a/gcc/rust/util/rust-unwrap-segment.h
+++ b/gcc/rust/util/rust-unwrap-segment.h
@@ -16,6 +16,10 @@
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+#include "rust-system.h"
+#include "optional.h"
+#include "rust-lang-item.h"
+#include "rust-mapping-common.h"
#include <ast/rust-ast-full-decls.h>
namespace Rust {
@@ -83,14 +87,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
@@ -118,4 +119,20 @@ unwrap_segment_get_lang_item (const std::unique_ptr<T> &ptr)
return unwrap_segment_get_lang_item (*ptr);
}
+/**
+ * Used to output a path in error messages
+ */
+
+inline static std::string
+unwrap_segment_error_string (const AST::TypePath &path)
+{
+ return path.make_debug_string ();
+}
+
+inline static std::string
+unwrap_segment_error_string (const AST::PathInExpression &path)
+{
+ return path.as_simple_path ().as_string ();
+}
+
} // namespace Rust