diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-04-09 09:32:30 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-09 09:32:30 +0000 |
commit | 85bd4cef64e1be492d1c62eb05d77a6cea1a8d21 (patch) | |
tree | 8bb52fa13b51bfbbd960f3d5ba5836204eb8cb2f /gcc | |
parent | 4937562f7ca354dc80369cc2e049c391838537f1 (diff) | |
parent | 90d5337d97e6193a8728413e2b34fc6e0e998dd8 (diff) | |
download | gcc-85bd4cef64e1be492d1c62eb05d77a6cea1a8d21.zip gcc-85bd4cef64e1be492d1c62eb05d77a6cea1a8d21.tar.gz gcc-85bd4cef64e1be492d1c62eb05d77a6cea1a8d21.tar.bz2 |
Merge #288
288: Fix crash with zero length array r=philberty a=YizhePKU
This PR fixes the crash that results from zero-length arrays, such as `let arr = []`(issue #260). `ArrayExpr` now uses `ArrayElemsValues` to represent an empty array like that, instead of `nullptr`.
However, currently such code still doesn't compile. Four tests were added, two of which report an error:
```Rust
// compilable/array_empty_list.rs
fn main() {
let arr = [];
}
// rust1: error: unable to determine type: please give this a type: 24
```
```Rust
// compilable/array_zero_length_fold.rs
fn main() {
let arr = ["Hello"; 123 - 123];
}
// array_zero_length_fold.rs:2:25: fatal error: failed to fold capacity constant
```
I think these are best treated as separate bugs. We can merge first and fix later, or we can delay this PR. Either is OK.
Co-authored-by: Yizhe <yizhe@pku.edu.cn>
Co-authored-by: YizhePKU <yizhe@pku.edu.cn>
Co-authored-by: YizhePKU <42838469+YizhePKU@users.noreply.github.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/ast/rust-ast-full-test.cc | 5 | ||||
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 17 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 7 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 215 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 20 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 4 | ||||
-rw-r--r-- | gcc/rust/util/rust-make-unique.h | 17 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compile/array_type_infer.rs | 3 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compile/array_zero_length.rs | 3 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/xfail_compile/array_empty_list.rs | 4 |
11 files changed, 166 insertions, 131 deletions
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index 69d1e6e..f17d269 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -2165,10 +2165,7 @@ ArrayExpr::as_string () const str += append_attributes (inner_attrs, INNER); str += "\n Array elems: "; - if (!has_array_elems ()) - str += "none"; - else - str += internal_elements->as_string (); + str += internal_elements->as_string (); return str; } diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 3de14cc..db90096 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1099,9 +1099,6 @@ public: outer_attrs = std::move (new_attrs); } - // Returns whether array expr has array elems or if it is just empty. - bool has_array_elems () const { return internal_elements != nullptr; } - // Constructor requires ArrayElems pointer ArrayExpr (std::unique_ptr<ArrayElems> array_elems, std::vector<Attribute> inner_attribs, @@ -1109,7 +1106,9 @@ public: : outer_attrs (std::move (outer_attribs)), inner_attrs (std::move (inner_attribs)), internal_elements (std::move (array_elems)), locus (locus) - {} + { + rust_assert (internal_elements != nullptr); + } // Copy constructor requires cloning ArrayElems for polymorphism to hold ArrayExpr (ArrayExpr const &other) @@ -1117,8 +1116,8 @@ public: inner_attrs (other.inner_attrs), locus (other.locus), marked_for_strip (other.marked_for_strip) { - if (other.has_array_elems ()) - internal_elements = other.internal_elements->clone_array_elems (); + internal_elements = other.internal_elements->clone_array_elems (); + rust_assert (internal_elements != nullptr); } // Overload assignment operator to clone internal_elements @@ -1130,11 +1129,9 @@ public: marked_for_strip = other.marked_for_strip; outer_attrs = other.outer_attrs; - if (other.has_array_elems ()) - internal_elements = other.internal_elements->clone_array_elems (); - else - internal_elements = nullptr; + internal_elements = other.internal_elements->clone_array_elems (); + rust_assert (internal_elements != nullptr); return *this; } diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index bde5a19..e52cb7b 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -727,8 +727,7 @@ public: /* assuming you can't strip away the ArrayElems type, but can strip * internal expressions and whatever */ - if (expr.has_array_elems ()) - expr.get_array_elems ()->accept_vis (*this); + expr.get_array_elems ()->accept_vis (*this); } void visit (AST::ArrayIndexExpr &expr) override { @@ -3264,8 +3263,8 @@ MacroExpander::expand_invoc (std::unique_ptr<AST::MacroInvocation> &invoc) // how would errors be signalled? null fragment? something else? // what about error vs just not having stuff in rules definition yet? - /* replace macro invocation with ast frag. actually, don't have any context here. maybe attach ast - * frag to macro invocation, and then have a method above get it? Or just return the ast frag from + /* replace macro invocation with ast frag. actually, don't have any context here. maybe attach ast + * frag to macro invocation, and then have a method above get it? Or just return the ast frag from * this method. */ } #endif diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 4379dc5..9697169 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -20,6 +20,9 @@ along with GCC; see the file COPYING3. If not see /* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h * This is also the reason why there are no include guards. */ +#include "rust-diagnostics.h" +#include "util/rust-make-unique.h" + namespace Rust { // Left binding powers of operations. enum binding_powers @@ -402,7 +405,7 @@ Parser<ManagedTokenSource>::parse_crate () std::vector<AST::Attribute> inner_attrs = parse_inner_attributes (); // parse items - std::vector<std::unique_ptr<AST::Item> > items; + std::vector<std::unique_ptr<AST::Item>> items; const_TokenPtr t = lexer.peek_token (); while (t->get_id () != END_OF_FILE) @@ -415,7 +418,7 @@ Parser<ManagedTokenSource>::parse_crate () add_error (std::move (error)); // TODO: should all items be cleared? - items = std::vector<std::unique_ptr<AST::Item> > (); + items = std::vector<std::unique_ptr<AST::Item>> (); break; } @@ -874,7 +877,7 @@ Parser<ManagedTokenSource>::parse_delim_token_tree () } // parse actual token tree vector - 0 or more - std::vector<std::unique_ptr<AST::TokenTree> > token_trees_in_tree; + std::vector<std::unique_ptr<AST::TokenTree>> token_trees_in_tree; // repeat loop until finding the matching delimiter t = lexer.peek_token (); @@ -979,10 +982,10 @@ Parser<ManagedTokenSource>::parse_token_tree () * individually is pretty simple and allows for better error diagnostics and * detection. */ template <typename ManagedTokenSource> -std::vector<std::unique_ptr<AST::Item> > +std::vector<std::unique_ptr<AST::Item>> Parser<ManagedTokenSource>::parse_items () { - std::vector<std::unique_ptr<AST::Item> > items; + std::vector<std::unique_ptr<AST::Item>> items; // TODO: replace with do-while loop? // infinite loop to save on comparisons (may be a tight loop) - breaks when @@ -1544,7 +1547,7 @@ Parser<ManagedTokenSource>::parse_macro_invocation_semi ( lexer.skip_token (); // parse actual token trees - std::vector<std::unique_ptr<AST::TokenTree> > token_trees; + std::vector<std::unique_ptr<AST::TokenTree>> token_trees; t = lexer.peek_token (); // parse token trees until the initial delimiter token is found again @@ -1713,7 +1716,7 @@ Parser<ManagedTokenSource>::parse_macro_matcher () lexer.skip_token (); // parse actual macro matches - std::vector<std::unique_ptr<AST::MacroMatch> > matches; + std::vector<std::unique_ptr<AST::MacroMatch>> matches; t = lexer.peek_token (); // parse token trees until the initial delimiter token is found again @@ -1883,7 +1886,7 @@ Parser<ManagedTokenSource>::parse_macro_match_repetition () skip_token (DOLLAR_SIGN); skip_token (LEFT_PAREN); - std::vector<std::unique_ptr<AST::MacroMatch> > matches; + std::vector<std::unique_ptr<AST::MacroMatch>> matches; // parse required first macro match std::unique_ptr<AST::MacroMatch> initial_match = parse_macro_match (); @@ -2091,7 +2094,7 @@ Parser<ManagedTokenSource>::parse_module ( std::vector<AST::Attribute> inner_attrs = parse_inner_attributes (); // parse items - std::vector<std::unique_ptr<AST::Item> > items; + std::vector<std::unique_ptr<AST::Item>> items; const_TokenPtr tok = lexer.peek_token (); while (tok->get_id () != RIGHT_CURLY) { @@ -2331,7 +2334,7 @@ Parser<ManagedTokenSource>::parse_use_tree () // nested tree UseTree type lexer.skip_token (); - std::vector<std::unique_ptr<AST::UseTree> > use_trees; + std::vector<std::unique_ptr<AST::UseTree>> use_trees; const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_CURLY) @@ -2409,7 +2412,7 @@ Parser<ManagedTokenSource>::parse_use_tree () // nested tree UseTree type lexer.skip_token (); - std::vector<std::unique_ptr<AST::UseTree> > use_trees; + std::vector<std::unique_ptr<AST::UseTree>> use_trees; // TODO: think of better control structure const_TokenPtr t = lexer.peek_token (); @@ -2523,7 +2526,7 @@ Parser<ManagedTokenSource>::parse_function ( Identifier function_name = function_name_tok->get_str (); // parse generic params - if exist - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params_in_angles (); if (!skip_token (LEFT_PAREN)) @@ -2626,20 +2629,20 @@ Parser<ManagedTokenSource>::parse_function_qualifiers () // Parses generic (lifetime or type) params inside angle brackets (optional). template <typename ManagedTokenSource> -std::vector<std::unique_ptr<AST::GenericParam> > +std::vector<std::unique_ptr<AST::GenericParam>> Parser<ManagedTokenSource>::parse_generic_params_in_angles () { if (lexer.peek_token ()->get_id () != LEFT_ANGLE) { // seems to be no generic params, so exit with empty vector - return std::vector<std::unique_ptr<AST::GenericParam> > (); + return std::vector<std::unique_ptr<AST::GenericParam>> (); } lexer.skip_token (); // DEBUG: fprintf (stderr, "skipped left angle in generic param\n"); - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params (is_right_angle_tok); // DEBUG: @@ -2652,7 +2655,7 @@ Parser<ManagedTokenSource>::parse_generic_params_in_angles () fprintf (stderr, "failed to skip generics right angle - returning empty " "generic params\n"); - return std::vector<std::unique_ptr<AST::GenericParam> > (); + return std::vector<std::unique_ptr<AST::GenericParam>> (); } return generic_params; @@ -2661,10 +2664,10 @@ Parser<ManagedTokenSource>::parse_generic_params_in_angles () /* Parse generic (lifetime or type) params NOT INSIDE ANGLE BRACKETS!!! Almost * always parse_generic_params_in_angles is what is wanted. */ template <typename ManagedTokenSource> -std::vector<std::unique_ptr<AST::GenericParam> > +std::vector<std::unique_ptr<AST::GenericParam>> Parser<ManagedTokenSource>::parse_generic_params () { - std::vector<std::unique_ptr<AST::GenericParam> > generic_params; + std::vector<std::unique_ptr<AST::GenericParam>> generic_params; // can't parse lifetime and type params separately due to lookahead issues // thus, parse them all here @@ -2748,12 +2751,12 @@ Parser<ManagedTokenSource>::parse_generic_params () "failed to parse identifier in type param in generic params"); add_error (std::move (error)); - return std::vector<std::unique_ptr<AST::GenericParam> > (); + return std::vector<std::unique_ptr<AST::GenericParam>> (); } Identifier ident = ident_tok->get_str (); // parse optional bounds - std::vector<std::unique_ptr<AST::TypeParamBound> > type_param_bounds; + std::vector<std::unique_ptr<AST::TypeParamBound>> type_param_bounds; if (lexer.peek_token ()->get_id () == COLON) { lexer.skip_token (); @@ -2777,7 +2780,7 @@ Parser<ManagedTokenSource>::parse_generic_params () "failed to parse type in type param in generic params"); add_error (std::move (error)); - return std::vector<std::unique_ptr<AST::GenericParam> > (); + return std::vector<std::unique_ptr<AST::GenericParam>> (); } } @@ -2811,7 +2814,7 @@ Parser<ManagedTokenSource>::parse_generic_params () "failed to parse type param in generic params"); add_error (std::move (error)); - return std::vector<std::unique_ptr<AST::GenericParam> > (); + return std::vector<std::unique_ptr<AST::GenericParam>> (); } // DEBUG @@ -2858,10 +2861,10 @@ Parser<ManagedTokenSource>::parse_generic_params () * always parse_generic_params_in_angles is what is wanted. */ template <typename ManagedTokenSource> template <typename EndTokenPred> -std::vector<std::unique_ptr<AST::GenericParam> > +std::vector<std::unique_ptr<AST::GenericParam>> Parser<ManagedTokenSource>::parse_generic_params (EndTokenPred is_end_token) { - std::vector<std::unique_ptr<AST::GenericParam> > generic_params; + std::vector<std::unique_ptr<AST::GenericParam>> generic_params; /* can't parse lifetime and type params separately due to lookahead issues * thus, parse them all here */ @@ -2929,7 +2932,7 @@ Parser<ManagedTokenSource>::parse_generic_params (EndTokenPred is_end_token) Identifier ident = ident_tok->get_str (); // parse optional bounds - std::vector<std::unique_ptr<AST::TypeParamBound> > type_param_bounds; + std::vector<std::unique_ptr<AST::TypeParamBound>> type_param_bounds; if (lexer.peek_token ()->get_id () == COLON) { lexer.skip_token (); @@ -3021,10 +3024,10 @@ Parser<ManagedTokenSource>::parse_generic_params (EndTokenPred is_end_token) /* Parses lifetime generic parameters (pointers). Will also consume any trailing * comma. No extra checks for end token. */ template <typename ManagedTokenSource> -std::vector<std::unique_ptr<AST::LifetimeParam> > +std::vector<std::unique_ptr<AST::LifetimeParam>> Parser<ManagedTokenSource>::parse_lifetime_params () { - std::vector<std::unique_ptr<AST::LifetimeParam> > lifetime_params; + std::vector<std::unique_ptr<AST::LifetimeParam>> lifetime_params; while (lexer.peek_token ()->get_id () != END_OF_FILE) { @@ -3055,10 +3058,10 @@ Parser<ManagedTokenSource>::parse_lifetime_params () * comma. Has extra is_end_token predicate checking. */ template <typename ManagedTokenSource> template <typename EndTokenPred> -std::vector<std::unique_ptr<AST::LifetimeParam> > +std::vector<std::unique_ptr<AST::LifetimeParam>> Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token) { - std::vector<std::unique_ptr<AST::LifetimeParam> > lifetime_params; + std::vector<std::unique_ptr<AST::LifetimeParam>> lifetime_params; // if end_token is not specified, it defaults to EOF, so should work fine while (!is_end_token (lexer.peek_token ()->get_id ())) @@ -3244,10 +3247,10 @@ Parser<ManagedTokenSource>::parse_lifetime_param () // Parses type generic parameters. Will also consume any trailing comma. template <typename ManagedTokenSource> -std::vector<std::unique_ptr<AST::TypeParam> > +std::vector<std::unique_ptr<AST::TypeParam>> Parser<ManagedTokenSource>::parse_type_params () { - std::vector<std::unique_ptr<AST::TypeParam> > type_params; + std::vector<std::unique_ptr<AST::TypeParam>> type_params; // infinite loop with break on failure as no info on ending token while (true) @@ -3276,10 +3279,10 @@ Parser<ManagedTokenSource>::parse_type_params () // Parses type generic parameters. Will also consume any trailing comma. template <typename ManagedTokenSource> template <typename EndTokenPred> -std::vector<std::unique_ptr<AST::TypeParam> > +std::vector<std::unique_ptr<AST::TypeParam>> Parser<ManagedTokenSource>::parse_type_params (EndTokenPred is_end_token) { - std::vector<std::unique_ptr<AST::TypeParam> > type_params; + std::vector<std::unique_ptr<AST::TypeParam>> type_params; while (!is_end_token (lexer.peek_token ()->get_id ())) { @@ -3329,7 +3332,7 @@ Parser<ManagedTokenSource>::parse_type_param () lexer.skip_token (); // parse type param bounds (if they exist) - std::vector<std::unique_ptr<AST::TypeParamBound> > type_param_bounds; + std::vector<std::unique_ptr<AST::TypeParamBound>> type_param_bounds; if (lexer.peek_token ()->get_id () == COLON) { lexer.skip_token (); @@ -3492,7 +3495,7 @@ Parser<ManagedTokenSource>::parse_where_clause () /* parse where clause items - this is not a separate rule in the reference so * won't be here */ - std::vector<std::unique_ptr<AST::WhereClauseItem> > where_clause_items; + std::vector<std::unique_ptr<AST::WhereClauseItem>> where_clause_items; /* HACK: where clauses end with a right curly or semicolon or equals in all * uses currently */ @@ -3589,7 +3592,7 @@ Parser<ManagedTokenSource>::parse_type_bound_where_clause_item () } // parse type param bounds if they exist - std::vector<std::unique_ptr<AST::TypeParamBound> > type_param_bounds + std::vector<std::unique_ptr<AST::TypeParamBound>> type_param_bounds = parse_type_param_bounds (); return std::unique_ptr<AST::TypeBoundWhereClauseItem> ( @@ -3637,10 +3640,10 @@ Parser<ManagedTokenSource>::parse_for_lifetimes () // Parses type parameter bounds in where clause or generic arguments. template <typename ManagedTokenSource> -std::vector<std::unique_ptr<AST::TypeParamBound> > +std::vector<std::unique_ptr<AST::TypeParamBound>> Parser<ManagedTokenSource>::parse_type_param_bounds () { - std::vector<std::unique_ptr<AST::TypeParamBound> > type_param_bounds; + std::vector<std::unique_ptr<AST::TypeParamBound>> type_param_bounds; std::unique_ptr<AST::TypeParamBound> initial_bound = parse_type_param_bound (); @@ -3677,10 +3680,10 @@ Parser<ManagedTokenSource>::parse_type_param_bounds () * token handling. */ template <typename ManagedTokenSource> template <typename EndTokenPred> -std::vector<std::unique_ptr<AST::TypeParamBound> > +std::vector<std::unique_ptr<AST::TypeParamBound>> Parser<ManagedTokenSource>::parse_type_param_bounds (EndTokenPred is_end_token) { - std::vector<std::unique_ptr<AST::TypeParamBound> > type_param_bounds; + std::vector<std::unique_ptr<AST::TypeParamBound>> type_param_bounds; std::unique_ptr<AST::TypeParamBound> initial_bound = parse_type_param_bound (); @@ -3917,7 +3920,7 @@ Parser<ManagedTokenSource>::parse_type_alias ( Identifier alias_name = alias_name_tok->get_str (); // parse generic params, which may not exist - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params_in_angles (); // parse where clause, which may not exist @@ -3977,7 +3980,7 @@ Parser<ManagedTokenSource>::parse_struct ( Identifier struct_name = name_tok->get_str (); // parse generic params, which may or may not exist - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params_in_angles (); // branch on next token - determines whether proper struct or tuple struct @@ -4285,7 +4288,7 @@ Parser<ManagedTokenSource>::parse_enum (AST::Visibility vis, Identifier enum_name = enum_name_tok->get_str (); // parse generic params (of enum container, not enum variants) if they exist - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params_in_angles (); // parse where clause if it exists @@ -4298,7 +4301,7 @@ Parser<ManagedTokenSource>::parse_enum (AST::Visibility vis, } // parse actual enum variant definitions - std::vector<std::unique_ptr<AST::EnumItem> > enum_items + std::vector<std::unique_ptr<AST::EnumItem>> enum_items = parse_enum_items ([] (TokenId id) { return id == RIGHT_CURLY; }); if (!skip_token (RIGHT_CURLY)) @@ -4315,10 +4318,10 @@ Parser<ManagedTokenSource>::parse_enum (AST::Visibility vis, // Parses the enum variants inside an enum definiton. template <typename ManagedTokenSource> -std::vector<std::unique_ptr<AST::EnumItem> > +std::vector<std::unique_ptr<AST::EnumItem>> Parser<ManagedTokenSource>::parse_enum_items () { - std::vector<std::unique_ptr<AST::EnumItem> > items; + std::vector<std::unique_ptr<AST::EnumItem>> items; std::unique_ptr<AST::EnumItem> initial_item = parse_enum_item (); @@ -4351,10 +4354,10 @@ Parser<ManagedTokenSource>::parse_enum_items () // Parses the enum variants inside an enum definiton. template <typename ManagedTokenSource> template <typename EndTokenPred> -std::vector<std::unique_ptr<AST::EnumItem> > +std::vector<std::unique_ptr<AST::EnumItem>> Parser<ManagedTokenSource>::parse_enum_items (EndTokenPred is_end_tok) { - std::vector<std::unique_ptr<AST::EnumItem> > items; + std::vector<std::unique_ptr<AST::EnumItem>> items; std::unique_ptr<AST::EnumItem> initial_item = parse_enum_item (); @@ -4491,7 +4494,7 @@ Parser<ManagedTokenSource>::parse_union ( Identifier union_name = union_name_tok->get_str (); // parse optional generic parameters - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params_in_angles (); // parse optional where clause @@ -4656,11 +4659,11 @@ Parser<ManagedTokenSource>::parse_trait ( Identifier ident = ident_tok->get_str (); // parse generic parameters (if they exist) - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params_in_angles (); // create placeholder type param bounds in case they don't exist - std::vector<std::unique_ptr<AST::TypeParamBound> > type_param_bounds; + std::vector<std::unique_ptr<AST::TypeParamBound>> type_param_bounds; // parse type param bounds (if they exist) if (lexer.peek_token ()->get_id () == COLON) @@ -4685,7 +4688,7 @@ Parser<ManagedTokenSource>::parse_trait ( std::vector<AST::Attribute> inner_attrs = parse_inner_attributes (); // parse trait items - std::vector<std::unique_ptr<AST::TraitItem> > trait_items; + std::vector<std::unique_ptr<AST::TraitItem>> trait_items; const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_CURLY) @@ -4761,7 +4764,7 @@ Parser<ManagedTokenSource>::parse_trait_item () Identifier ident = ident_tok->get_str (); // parse generic params - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params_in_angles (); if (!skip_token (LEFT_PAREN)) @@ -4893,7 +4896,7 @@ Parser<ManagedTokenSource>::parse_trait_type ( const_TokenPtr ident_tok = expect_token (IDENTIFIER); Identifier ident = ident_tok->get_str (); - std::vector<std::unique_ptr<AST::TypeParamBound> > bounds; + std::vector<std::unique_ptr<AST::TypeParamBound>> bounds; // parse optional colon if (lexer.peek_token ()->get_id () == COLON) @@ -4986,7 +4989,7 @@ Parser<ManagedTokenSource>::parse_impl (AST::Visibility vis, } // parse generic params (shared by trait and inherent impls) - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params_in_angles (); // Again, trait impl-only feature, but optional one, so can be used for @@ -5039,7 +5042,7 @@ Parser<ManagedTokenSource>::parse_impl (AST::Visibility vis, std::vector<AST::Attribute> inner_attrs = parse_inner_attributes (); // parse inherent impl items - std::vector<std::unique_ptr<AST::InherentImplItem> > impl_items; + std::vector<std::unique_ptr<AST::InherentImplItem>> impl_items; const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_CURLY) @@ -5114,7 +5117,7 @@ Parser<ManagedTokenSource>::parse_impl (AST::Visibility vis, std::vector<AST::Attribute> inner_attrs = parse_inner_attributes (); // parse trait impl items - std::vector<std::unique_ptr<AST::TraitImplItem> > impl_items; + std::vector<std::unique_ptr<AST::TraitImplItem>> impl_items; const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_CURLY) @@ -5296,7 +5299,7 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method ( Identifier ident = ident_tok->get_str (); // parse generic params - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params_in_angles (); if (!skip_token (LEFT_PAREN)) @@ -5531,7 +5534,7 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method ( "about to start parsing generic params in trait impl function or method\n"); // parse generic params - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params_in_angles (); // DEBUG: @@ -5689,7 +5692,7 @@ Parser<ManagedTokenSource>::parse_extern_block ( std::vector<AST::Attribute> inner_attrs = parse_inner_attributes (); // parse declarations inside extern block - std::vector<std::unique_ptr<AST::ExternalItem> > extern_items; + std::vector<std::unique_ptr<AST::ExternalItem>> extern_items; const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_CURLY) @@ -5806,7 +5809,7 @@ Parser<ManagedTokenSource>::parse_external_item () Identifier ident = ident_tok->get_str (); // parse (optional) generic params - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params_in_angles (); if (!skip_token (LEFT_PAREN)) @@ -6132,7 +6135,7 @@ Parser<ManagedTokenSource>::parse_type_path () } // create segment vector - std::vector<std::unique_ptr<AST::TypePathSegment> > segments; + std::vector<std::unique_ptr<AST::TypePathSegment>> segments; // parse required initial segment std::unique_ptr<AST::TypePathSegment> initial_segment @@ -6217,7 +6220,7 @@ Parser<ManagedTokenSource>::parse_path_generic_args () } // try to parse types second - std::vector<std::unique_ptr<AST::Type> > type_args; + std::vector<std::unique_ptr<AST::Type>> type_args; // TODO: think of better control structure t = lexer.peek_token (); @@ -6402,7 +6405,7 @@ Parser<ManagedTokenSource>::parse_type_path_function () } // parse function inputs - std::vector<std::unique_ptr<AST::Type> > inputs; + std::vector<std::unique_ptr<AST::Type>> inputs; while (lexer.peek_token ()->get_id () != RIGHT_PAREN) { @@ -6705,7 +6708,7 @@ Parser<ManagedTokenSource>::parse_qualified_path_in_type () } // parse path segments - std::vector<std::unique_ptr<AST::TypePathSegment> > segments; + std::vector<std::unique_ptr<AST::TypePathSegment>> segments; segments.reserve (1); // parse initial required segment @@ -6879,7 +6882,7 @@ Parser<ManagedTokenSource>::parse_method () Identifier method_name = ident_tok->get_str (); // parse generic params - if exist - std::vector<std::unique_ptr<AST::GenericParam> > generic_params + std::vector<std::unique_ptr<AST::GenericParam>> generic_params = parse_generic_params_in_angles (); if (!skip_token (LEFT_PAREN)) @@ -7282,7 +7285,7 @@ Parser<ManagedTokenSource>::parse_block_expr ( std::vector<AST::Attribute> inner_attrs = parse_inner_attributes (); // parse statements and expression - std::vector<std::unique_ptr<AST::Stmt> > stmts; + std::vector<std::unique_ptr<AST::Stmt>> stmts; std::unique_ptr<AST::ExprWithoutBlock> expr = nullptr; const_TokenPtr t = lexer.peek_token (); @@ -7894,7 +7897,7 @@ Parser<ManagedTokenSource>::parse_if_let_expr ( lexer.skip_token (); // parse match arm patterns (which are required) - std::vector<std::unique_ptr<AST::Pattern> > match_arm_patterns + std::vector<std::unique_ptr<AST::Pattern>> match_arm_patterns = parse_match_arm_patterns (EQUAL); if (match_arm_patterns.empty ()) { @@ -8199,7 +8202,7 @@ Parser<ManagedTokenSource>::parse_while_let_loop_expr ( lexer.skip_token (); // parse predicate patterns - std::vector<std::unique_ptr<AST::Pattern> > 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? @@ -8522,7 +8525,7 @@ Parser<ManagedTokenSource>::parse_match_arm () } // parse match arm patterns - at least 1 is required - std::vector<std::unique_ptr<AST::Pattern> > match_arm_patterns + std::vector<std::unique_ptr<AST::Pattern>> match_arm_patterns = parse_match_arm_patterns (RIGHT_CURLY); if (match_arm_patterns.empty ()) { @@ -8566,7 +8569,7 @@ Parser<ManagedTokenSource>::parse_match_arm () * that would exist after the patterns are done (e.g. '}' for match expr, '=' * for if let and while let). */ template <typename ManagedTokenSource> -std::vector<std::unique_ptr<AST::Pattern> > +std::vector<std::unique_ptr<AST::Pattern>> Parser<ManagedTokenSource>::parse_match_arm_patterns (TokenId end_token_id) { // skip optional leading '|' @@ -8576,7 +8579,7 @@ Parser<ManagedTokenSource>::parse_match_arm_patterns (TokenId end_token_id) * If semantically different, I need a wrapped "match arm patterns" object for * this. */ - std::vector<std::unique_ptr<AST::Pattern> > patterns; + std::vector<std::unique_ptr<AST::Pattern>> patterns; // quick break out if end_token_id if (lexer.peek_token ()->get_id () == end_token_id) @@ -8717,9 +8720,12 @@ Parser<ManagedTokenSource>::parse_array_expr ( // no array elements lexer.skip_token (); - return std::unique_ptr<AST::ArrayExpr> ( - new AST::ArrayExpr (nullptr, std::move (inner_attrs), - std::move (outer_attrs), locus)); + std::vector<std::unique_ptr<AST::Expr>> exprs; + auto array_elems + = Rust::make_unique<AST::ArrayElemsValues> (std::move (exprs)); + return Rust::make_unique<AST::ArrayExpr> (std::move (array_elems), + std::move (inner_attrs), + std::move (outer_attrs), locus); } else { @@ -8768,7 +8774,7 @@ Parser<ManagedTokenSource>::parse_array_expr ( else if (lexer.peek_token ()->get_id () == RIGHT_SQUARE) { // single-element array expression - std::vector<std::unique_ptr<AST::Expr> > exprs; + std::vector<std::unique_ptr<AST::Expr>> exprs; exprs.reserve (1); exprs.push_back (std::move (initial_expr)); exprs.shrink_to_fit (); @@ -8785,7 +8791,7 @@ Parser<ManagedTokenSource>::parse_array_expr ( else if (lexer.peek_token ()->get_id () == COMMA) { // multi-element array expression (or trailing comma) - std::vector<std::unique_ptr<AST::Expr> > exprs; + std::vector<std::unique_ptr<AST::Expr>> exprs; exprs.push_back (std::move (initial_expr)); const_TokenPtr t = lexer.peek_token (); @@ -8905,7 +8911,7 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_expr ( // create tuple with empty tuple elems return std::unique_ptr<AST::TupleExpr> ( - new AST::TupleExpr (std::vector<std::unique_ptr<AST::Expr> > (), + new AST::TupleExpr (std::vector<std::unique_ptr<AST::Expr>> (), std::move (inner_attrs), std::move (outer_attrs), locus)); } @@ -8936,7 +8942,7 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_expr ( else if (lexer.peek_token ()->get_id () == COMMA) { // tuple expr - std::vector<std::unique_ptr<AST::Expr> > exprs; + std::vector<std::unique_ptr<AST::Expr>> exprs; exprs.push_back (std::move (first_expr)); // parse potential other tuple exprs @@ -9064,7 +9070,7 @@ Parser<ManagedTokenSource>::parse_type () case LIFETIME: { /* probably a lifetime bound, so probably type param bounds in * TraitObjectType */ - std::vector<std::unique_ptr<AST::TypeParamBound> > bounds + std::vector<std::unique_ptr<AST::TypeParamBound>> bounds = parse_type_param_bounds (); return std::unique_ptr<AST::TraitObjectType> ( @@ -9129,7 +9135,7 @@ Parser<ManagedTokenSource>::parse_type () } case PLUS: { // type param bounds - std::vector<std::unique_ptr<AST::TypeParamBound> > bounds; + std::vector<std::unique_ptr<AST::TypeParamBound>> bounds; // convert type path to trait bound std::unique_ptr<AST::TraitBound> path_bound ( @@ -9184,7 +9190,7 @@ Parser<ManagedTokenSource>::parse_type () { /* cannot be one bound because lifetime prevents it from being * traitbound */ - std::vector<std::unique_ptr<AST::TypeParamBound> > bounds + std::vector<std::unique_ptr<AST::TypeParamBound>> bounds = parse_type_param_bounds (); return std::unique_ptr<AST::ImplTraitType> ( @@ -9221,7 +9227,7 @@ Parser<ManagedTokenSource>::parse_type () } // parse additional type param bounds - std::vector<std::unique_ptr<AST::TypeParamBound> > bounds; + std::vector<std::unique_ptr<AST::TypeParamBound>> bounds; bounds.push_back (std::move (initial_bound)); while (t->get_id () == PLUS) { @@ -9257,7 +9263,7 @@ Parser<ManagedTokenSource>::parse_type () { /* cannot be one bound because lifetime prevents it from being * traitbound */ - std::vector<std::unique_ptr<AST::TypeParamBound> > bounds + std::vector<std::unique_ptr<AST::TypeParamBound>> bounds = parse_type_param_bounds (); return std::unique_ptr<AST::TraitObjectType> ( @@ -9294,7 +9300,7 @@ Parser<ManagedTokenSource>::parse_type () } // parse additional type param bounds - std::vector<std::unique_ptr<AST::TypeParamBound> > bounds; + std::vector<std::unique_ptr<AST::TypeParamBound>> bounds; bounds.push_back (std::move (initial_bound)); while (t->get_id () == PLUS) { @@ -9350,7 +9356,7 @@ Parser<ManagedTokenSource>::parse_paren_prefixed_type () * whether trailing comma happens */ const_TokenPtr t = lexer.peek_token (); bool trailing_comma = true; - std::vector<std::unique_ptr<AST::Type> > types; + std::vector<std::unique_ptr<AST::Type>> types; while (t->get_id () != RIGHT_PAREN) { @@ -9389,7 +9395,7 @@ Parser<ManagedTokenSource>::parse_paren_prefixed_type () if (lexer.peek_token ()->get_id () == PLUS) { // create type param bounds vector - std::vector<std::unique_ptr<AST::TypeParamBound> > bounds; + std::vector<std::unique_ptr<AST::TypeParamBound>> bounds; // HACK: convert type to traitbound and add to bounds std::unique_ptr<AST::Type> released_ptr = std::move (types[0]); @@ -9514,7 +9520,7 @@ Parser<ManagedTokenSource>::parse_for_prefixed_type () std::unique_ptr<AST::TraitBound> initial_bound ( new AST::TraitBound (std::move (path), for_locus, false, false, std::move (for_lifetimes))); - std::vector<std::unique_ptr<AST::TypeParamBound> > bounds; + std::vector<std::unique_ptr<AST::TypeParamBound>> bounds; bounds.push_back (std::move (initial_bound)); while (t->get_id () == PLUS) @@ -10115,7 +10121,7 @@ Parser<ManagedTokenSource>::parse_paren_prefixed_type_no_bounds () * whether trailing comma happens */ const_TokenPtr t = lexer.peek_token (); bool trailing_comma = true; - std::vector<std::unique_ptr<AST::Type> > types; + std::vector<std::unique_ptr<AST::Type>> types; while (t->get_id () != RIGHT_PAREN) { @@ -10672,7 +10678,7 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () lexer.skip_token (); // parse new patterns while next token is a comma - std::vector<std::unique_ptr<AST::Pattern> > patterns; + std::vector<std::unique_ptr<AST::Pattern>> patterns; const_TokenPtr t = lexer.peek_token (); while (t->get_id () == COMMA) @@ -10711,8 +10717,7 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () // create ranged tuple pattern items with only upper items std::unique_ptr<AST::TuplePatternItemsRanged> items ( new AST::TuplePatternItemsRanged ( - std::vector<std::unique_ptr<AST::Pattern> > (), - std::move (patterns))); + std::vector<std::unique_ptr<AST::Pattern>> (), std::move (patterns))); return std::unique_ptr<AST::TuplePattern> ( new AST::TuplePattern (std::move (items), paren_locus)); } @@ -10743,7 +10748,7 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () lexer.skip_token (); // create vector of patterns - std::vector<std::unique_ptr<AST::Pattern> > patterns; + std::vector<std::unique_ptr<AST::Pattern>> patterns; patterns.push_back (std::move (initial_pattern)); t = lexer.peek_token (); @@ -10785,7 +10790,7 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () lexer.skip_token (); // parse upper patterns - std::vector<std::unique_ptr<AST::Pattern> > upper_patterns; + std::vector<std::unique_ptr<AST::Pattern>> upper_patterns; t = lexer.peek_token (); while (t->get_id () == COMMA) { @@ -10863,7 +10868,7 @@ Parser<ManagedTokenSource>::parse_slice_pattern () return nullptr; } - std::vector<std::unique_ptr<AST::Pattern> > patterns; + std::vector<std::unique_ptr<AST::Pattern>> patterns; patterns.push_back (std::move (initial_pattern)); const_TokenPtr t = lexer.peek_token (); @@ -11112,7 +11117,7 @@ template <typename ManagedTokenSource> std::unique_ptr<AST::TupleStructItems> Parser<ManagedTokenSource>::parse_tuple_struct_items () { - std::vector<std::unique_ptr<AST::Pattern> > lower_patterns; + std::vector<std::unique_ptr<AST::Pattern>> lower_patterns; // DEBUG fprintf (stderr, "started parsing tuple struct items\n"); @@ -11126,7 +11131,7 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items () // DEBUG fprintf (stderr, "'..' at front in tuple struct items detected\n"); - std::vector<std::unique_ptr<AST::Pattern> > upper_patterns; + std::vector<std::unique_ptr<AST::Pattern>> upper_patterns; const_TokenPtr t = lexer.peek_token (); while (t->get_id () == COMMA) @@ -11207,7 +11212,7 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items () // has an upper range that must be parsed separately lexer.skip_token (); - std::vector<std::unique_ptr<AST::Pattern> > upper_patterns; + std::vector<std::unique_ptr<AST::Pattern>> upper_patterns; t = lexer.peek_token (); while (t->get_id () == COMMA) @@ -11252,7 +11257,7 @@ template <typename ManagedTokenSource> AST::StructPatternElements Parser<ManagedTokenSource>::parse_struct_pattern_elems () { - std::vector<std::unique_ptr<AST::StructPatternField> > fields; + std::vector<std::unique_ptr<AST::StructPatternField>> fields; std::vector<AST::Attribute> etc_attrs; bool has_etc = false; @@ -11742,7 +11747,7 @@ Parser<ManagedTokenSource>::parse_path_based_stmt_or_expr ( lexer.skip_token (); // parse actual token trees - std::vector<std::unique_ptr<AST::TokenTree> > token_trees; + std::vector<std::unique_ptr<AST::TokenTree>> token_trees; t3 = lexer.peek_token (); // parse token trees until the initial delimiter token is found again @@ -12057,7 +12062,7 @@ Parser<ManagedTokenSource>::parse_macro_invocation_maybe_semi ( lexer.skip_token (); // parse actual token trees - std::vector<std::unique_ptr<AST::TokenTree> > token_trees; + std::vector<std::unique_ptr<AST::TokenTree>> token_trees; t3 = lexer.peek_token (); // parse token trees until the initial delimiter token is found again @@ -14209,7 +14214,7 @@ Parser<ManagedTokenSource>::parse_method_call_expr ( } // parse method params (if they exist) - std::vector<std::unique_ptr<AST::Expr> > params; + std::vector<std::unique_ptr<AST::Expr>> params; const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_PAREN) @@ -14255,7 +14260,7 @@ Parser<ManagedTokenSource>::parse_function_call_expr ( std::vector<AST::Attribute> outer_attrs, ParseRestrictions) { // parse function params (if they exist) - std::vector<std::unique_ptr<AST::Expr> > params; + std::vector<std::unique_ptr<AST::Expr>> params; const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_PAREN) @@ -14366,7 +14371,7 @@ Parser<ManagedTokenSource>::parse_struct_expr_struct_partial ( // struct with struct expr fields // parse struct expr fields - std::vector<std::unique_ptr<AST::StructExprField> > fields; + std::vector<std::unique_ptr<AST::StructExprField>> fields; while (t->get_id () != RIGHT_CURLY && t->get_id () != DOT_DOT) { @@ -14480,7 +14485,7 @@ Parser<ManagedTokenSource>::parse_struct_expr_tuple_partial ( std::vector<AST::Attribute> inner_attrs = parse_inner_attributes (); - std::vector<std::unique_ptr<AST::Expr> > exprs; + std::vector<std::unique_ptr<AST::Expr>> exprs; const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_PAREN) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 6c31ab3..6e7dff8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -35,6 +35,9 @@ class TypeCheckExpr : public TypeCheckBase using Rust::Resolver::TypeCheckBase::visit; public: + /* Perform type checking on expr. Also runs type unification algorithm. + Returns the unified type of expr. + `inside_loop` acts as a context for BreakExpr, etc. May change later. */ static TyTy::BaseType *Resolve (HIR::Expr *expr, bool inside_loop) { TypeCheckExpr resolver (inside_loop); @@ -682,6 +685,7 @@ public: HIR::ArrayElems *elements = expr.get_internal_elements (); size_t num_elems = elements->get_num_elements (); + // Check the type of array elements elements->accept_vis (*this); rust_assert (infered_array_elems != nullptr); @@ -698,14 +702,16 @@ public: return true; }); - infered_array_elems = types[0]; - for (size_t i = 1; i < types.size (); i++) + infered_array_elems = TyTy::TyVar::get_implicit_infer_var ().get_tyty (); + + for (auto &type : types) { - infered_array_elems = infered_array_elems->unify (types.at (i)); + infered_array_elems = infered_array_elems->unify (type); } - for (auto &elem : types) - infered_array_elems->append_reference (elem->get_ref ()); + { + infered_array_elems->append_reference (elem->get_ref ()); + } } void visit (HIR::ArrayElemsCopied &elems) override @@ -991,7 +997,11 @@ private: gcc_unreachable (); } + /* The return value of TypeCheckExpr::Resolve */ TyTy::BaseType *infered; + + /* The return value of visit(ArrayElemsValues&) and visit(ArrayElemsCopied&) + Stores the type of array elements, if `expr` is ArrayExpr. */ TyTy::BaseType *infered_array_elems; bool inside_loop; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index ae17baf..cb0543c 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -48,7 +48,7 @@ TyVar::get_tyty () const } TyVar -TyVar::get_implict_infer_var () +TyVar::get_implicit_infer_var () { auto mappings = Analysis::Mappings::get (); auto context = Resolver::TypeCheckContext::get (); diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 596b95d..7b4197f 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -154,7 +154,7 @@ public: BaseType *get_tyty () const; - static TyVar get_implict_infer_var (); + static TyVar get_implicit_infer_var (); private: HirId ref; @@ -560,7 +560,7 @@ public: std::vector<SubstitutionArg> args; for (auto &sub : get_substs ()) { - TyVar infer_var = TyVar::get_implict_infer_var (); + TyVar infer_var = TyVar::get_implicit_infer_var (); args.push_back (SubstitutionArg (&sub, infer_var.get_tyty ())); } diff --git a/gcc/rust/util/rust-make-unique.h b/gcc/rust/util/rust-make-unique.h new file mode 100644 index 0000000..4698b7d --- /dev/null +++ b/gcc/rust/util/rust-make-unique.h @@ -0,0 +1,17 @@ +#ifndef RUST_MAKE_UNIQUE_H +#define RUST_MAKE_UNIQUE_H + +#include <memory> + +namespace Rust { + +template <typename T, typename... Ts> +std::unique_ptr<T> +make_unique (Ts &&... params) +{ + return std::unique_ptr<T> (new T (std::forward<Ts> (params)...)); +} + +} // namespace Rust + +#endif // RUST_MAKE_UNIQUE_H diff --git a/gcc/testsuite/rust.test/compile/array_type_infer.rs b/gcc/testsuite/rust.test/compile/array_type_infer.rs new file mode 100644 index 0000000..f6a6182 --- /dev/null +++ b/gcc/testsuite/rust.test/compile/array_type_infer.rs @@ -0,0 +1,3 @@ +fn main() { + let arr: [_; 5] = [1, 2, 3, 4, 5]; +} diff --git a/gcc/testsuite/rust.test/compile/array_zero_length.rs b/gcc/testsuite/rust.test/compile/array_zero_length.rs new file mode 100644 index 0000000..a3acc15 --- /dev/null +++ b/gcc/testsuite/rust.test/compile/array_zero_length.rs @@ -0,0 +1,3 @@ +fn main() { + let arr = ["Hello"; 0]; +} diff --git a/gcc/testsuite/rust.test/xfail_compile/array_empty_list.rs b/gcc/testsuite/rust.test/xfail_compile/array_empty_list.rs new file mode 100644 index 0000000..b647cea --- /dev/null +++ b/gcc/testsuite/rust.test/xfail_compile/array_empty_list.rs @@ -0,0 +1,4 @@ +// { dg-error "unable to determine type" "" { target { *-*-* } } 0 } +fn main() { + let arr = []; +} |