diff options
author | Philip Herron <philip.herron@embecosm.com> | 2020-12-12 12:56:02 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2020-12-17 17:23:46 +0000 |
commit | 44d10d9547612b5fda3d27bb628d5d6ee79108af (patch) | |
tree | ee39563bec035ad3882c1e655a49ba55df12d47c /gcc | |
parent | 4fb0ab7e635c65318aadf958e0e1303f3435c4e5 (diff) | |
download | gcc-44d10d9547612b5fda3d27bb628d5d6ee79108af.zip gcc-44d10d9547612b5fda3d27bb628d5d6ee79108af.tar.gz gcc-44d10d9547612b5fda3d27bb628d5d6ee79108af.tar.bz2 |
TypeResolution pass now with a TyTy module
Resolution must implement the Gathering specified in the rust-dev guide.
We need to be able to handle cases such as:
let mut x;
x = 1;
or
let mut x = vec!{}
x.push(1)
Now the TyTy module has a combine abstract method to allow the combination
of types to condense down from their integral parts.
Diffstat (limited to 'gcc')
36 files changed, 2039 insertions, 243 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index aa81813..96457ed 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -78,6 +78,9 @@ GRS_OBJS = \ rust/rust-hir-map.o \ rust/rust-ast-lower.o \ rust/rust-ast-resolve.o \ + rust/rust-hir-type-check.o \ + rust/rust-tyty.o \ + rust/rust-tyctx.o \ $(END) # removed object files from here @@ -231,7 +234,8 @@ RUST_INCLUDES = -I $(srcdir)/rust \ -I $(srcdir)/rust/hir/tree \ -I $(srcdir)/rust/hir \ -I $(srcdir)/rust/resolve \ - -I $(srcdir)/rust/util + -I $(srcdir)/rust/util \ + -I $(srcdir)/rust/typecheck # add files that require cross-folder includes - currently rust-lang.o, rust-lex.o CFLAGS-rust/rust-lang.o += $(RUST_INCLUDES) @@ -287,8 +291,13 @@ rust/%.o: rust/hir/tree/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) -# build rust/hir/tree files in rust folder +# build rust/resolve files in rust folder rust/%.o: rust/resolve/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) +# build rust/typecheck files in rust folder +rust/%.o: rust/typecheck/%.cc + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< + $(POSTCOMPILE) + diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 71e465e..e0ce862 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -93,6 +93,8 @@ public: mappings->insert_defid_mapping (mapping.get_defid (), translated); mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (), translated); + mappings->insert_location (crate_num, mapping.get_hirid (), + function.get_locus ()); } // Helpers diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h index d18dc19..c813639 100644 --- a/gcc/rust/hir/rust-ast-lower-stmt.h +++ b/gcc/rust/hir/rust-ast-lower-stmt.h @@ -58,6 +58,8 @@ public: = new HIR::ExprStmtWithoutBlock (mapping, std::unique_ptr<HIR::Expr> (expr), stmt.get_locus ()); + mappings->insert_location (crate_num, mapping.get_hirid (), + stmt.get_locus ()); } void visit (AST::LetStmt &stmt) @@ -82,6 +84,8 @@ public: std::unique_ptr<HIR::Expr> (init_expression), std::unique_ptr<HIR::Type> (type), std::move (outer_attrs), stmt.get_locus ()); + mappings->insert_location (crate_num, mapping.get_hirid (), + stmt.get_locus ()); } private: diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 9611ca0..4193415 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -65,9 +65,16 @@ public: return true; }); + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, path.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); translated - = new HIR::TypePath (std::move (translated_segments), path.get_locus (), + = new HIR::TypePath (std::move (mapping), std::move (translated_segments), + path.get_locus (), path.has_opening_scope_resolution_op ()); + mappings->insert_hir_type (mapping.get_crate_num (), mapping.get_hirid (), + translated); } private: diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 5f5bbf9..b08aa91 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2169,6 +2169,8 @@ public: Expr *get_fnexpr () { return function.get (); } + size_t num_params () const { return params.size (); } + void iterate_params (std::function<bool (Expr *)> cb) { for (auto it = params.begin (); it != params.end (); it++) @@ -2551,6 +2553,15 @@ public: void accept_vis (HIRVisitor &vis) override; + void iterate_stmts (std::function<bool (Stmt *)> cb) + { + for (auto it = statements.begin (); it != statements.end (); it++) + { + if (!cb (it->get ())) + return; + } + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3118,6 +3129,8 @@ public: void accept_vis (HIRVisitor &vis) override; + Expr *get_expr () { return return_expr.get (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 774e407..cf24bae 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -319,19 +319,6 @@ public: // not having either is not an error } - // Creates an error state self-param. - static SelfParam create_error () - { - /* HACK: creates a dummy type. Since it's a unique pointer, it should - * clean it up, but it still allocates memory, which is not ideal. */ - return SelfParam (Lifetime (Lifetime::STATIC), false, false, - new QualifiedPathInType ( - QualifiedPathInType::create_error ())); - /* FIXME: is there a reason why I didn't just create a null pointer? Is it - * due to error being having both a type and a lifetime? If it is, wouldn't - * something like "not has_ref and has lifetime" for error be better? */ - } - // Type-based self parameter (not ref, no lifetime) SelfParam (std::unique_ptr<Type> type, bool is_mut, Location locus) : has_ref (false), is_mut (is_mut), lifetime (Lifetime::error ()), @@ -588,22 +575,6 @@ class Method : public InherentImplItem, public TraitImplItem Location locus; public: - // Returns whether the method is in an error state. - bool is_error () const - { - return expr == nullptr || method_name.empty () || self_param.is_error (); - } - - // Creates an error state method. - static Method create_error () - { - return Method ("", FunctionQualifiers (FunctionQualifiers::NONE, true), - std::vector<std::unique_ptr<GenericParam> > (), - SelfParam::create_error (), std::vector<FunctionParam> (), - nullptr, WhereClause::create_empty (), nullptr, - Visibility::create_error (), std::vector<Attribute> ()); - } - // Returns whether the method has generic parameters. bool has_generics () const { return !generic_params.empty (); } diff --git a/gcc/rust/hir/tree/rust-hir-macro.h b/gcc/rust/hir/tree/rust-hir-macro.h index 0a38134..84b4914 100644 --- a/gcc/rust/hir/tree/rust-hir-macro.h +++ b/gcc/rust/hir/tree/rust-hir-macro.h @@ -345,7 +345,8 @@ public: MacroInvocation (Analysis::NodeMapping mappings, SimplePath path, DelimTokenTree token_tree, std::vector<Attribute> outer_attrs, Location locus) - : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)), + : TypeNoBounds (mappings), + ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)), path (std::move (path)), token_tree (std::move (token_tree)), locus (locus) {} diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index 06d31aa..1bba506 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -591,20 +591,24 @@ public: // Creates an error state TypePath. static TypePath create_error () { - return TypePath (std::vector<std::unique_ptr<TypePathSegment> > (), + return TypePath (Analysis::NodeMapping::get_error (), + std::vector<std::unique_ptr<TypePathSegment> > (), Location ()); } // Constructor - TypePath (std::vector<std::unique_ptr<TypePathSegment> > segments, + TypePath (Analysis::NodeMapping mappings, + std::vector<std::unique_ptr<TypePathSegment> > segments, Location locus, bool has_opening_scope_resolution = false) - : has_opening_scope_resolution (has_opening_scope_resolution), + : TypeNoBounds (mappings), + has_opening_scope_resolution (has_opening_scope_resolution), segments (std::move (segments)), locus (locus) {} // Copy constructor with vector clone TypePath (TypePath const &other) - : has_opening_scope_resolution (other.has_opening_scope_resolution), + : TypeNoBounds (other.mappings), + has_opening_scope_resolution (other.has_opening_scope_resolution), locus (other.locus) { segments.reserve (other.segments.size ()); @@ -617,6 +621,7 @@ public: { has_opening_scope_resolution = other.has_opening_scope_resolution; locus = other.locus; + mappings = other.mappings; segments.reserve (other.segments.size ()); for (const auto &e : other.segments) @@ -793,10 +798,10 @@ protected: public: QualifiedPathInType ( - QualifiedPathType qual_path_type, + Analysis::NodeMapping mappings, QualifiedPathType qual_path_type, std::vector<std::unique_ptr<TypePathSegment> > path_segments, Location locus = Location ()) - : path_type (std::move (qual_path_type)), + : TypeNoBounds (mappings), path_type (std::move (qual_path_type)), segments (std::move (path_segments)), locus (locus) {} @@ -805,7 +810,7 @@ public: // Copy constructor with vector clone QualifiedPathInType (QualifiedPathInType const &other) - : path_type (other.path_type), locus (other.locus) + : TypeNoBounds (mappings), path_type (other.path_type), locus (other.locus) { segments.reserve (other.segments.size ()); for (const auto &e : other.segments) @@ -817,6 +822,7 @@ public: { path_type = other.path_type; locus = other.locus; + mappings = other.mappings; segments.reserve (other.segments.size ()); for (const auto &e : other.segments) @@ -829,17 +835,6 @@ public: QualifiedPathInType (QualifiedPathInType &&other) = default; QualifiedPathInType &operator= (QualifiedPathInType &&other) = default; - // Returns whether qualified path in type is in an error state. - bool is_error () const { return path_type.is_error (); } - - // Creates an error state qualified path in type. - static QualifiedPathInType create_error () - { - return QualifiedPathInType ( - QualifiedPathType::create_error (), - std::vector<std::unique_ptr<TypePathSegment> > ()); - } - std::string as_string () const override; void accept_vis (HIRVisitor &vis) override; diff --git a/gcc/rust/hir/tree/rust-hir-stmt.h b/gcc/rust/hir/tree/rust-hir-stmt.h index 61d9dcb..31d55b6 100644 --- a/gcc/rust/hir/tree/rust-hir-stmt.h +++ b/gcc/rust/hir/tree/rust-hir-stmt.h @@ -113,6 +113,10 @@ public: void accept_vis (HIRVisitor &vis) override; + HIR::Type *get_type () { return type.get (); } + + HIR::Expr *get_init_expr () { return init_expr.get (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h index 0a446bd..f8c851c 100644 --- a/gcc/rust/hir/tree/rust-hir-type.h +++ b/gcc/rust/hir/tree/rust-hir-type.h @@ -92,13 +92,16 @@ protected: public: ImplTraitType ( + Analysis::NodeMapping mappings, std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds, Location locus) - : type_param_bounds (std::move (type_param_bounds)), locus (locus) + : Type (mappings), type_param_bounds (std::move (type_param_bounds)), + locus (locus) {} // copy constructor with vector clone - ImplTraitType (ImplTraitType const &other) : locus (other.locus) + ImplTraitType (ImplTraitType const &other) + : Type (other.mappings), locus (other.locus) { type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) @@ -109,6 +112,7 @@ public: ImplTraitType &operator= (ImplTraitType const &other) { locus = other.locus; + mappings = other.mappings; type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) @@ -148,15 +152,16 @@ protected: public: TraitObjectType ( + Analysis::NodeMapping mappings, std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds, Location locus, bool is_dyn_dispatch = false) - : has_dyn (is_dyn_dispatch), + : Type (mappings), has_dyn (is_dyn_dispatch), type_param_bounds (std::move (type_param_bounds)), locus (locus) {} // copy constructor with vector clone TraitObjectType (TraitObjectType const &other) - : has_dyn (other.has_dyn), locus (other.locus) + : Type (other.mappings), 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) @@ -166,6 +171,7 @@ public: // overloaded assignment operator to clone TraitObjectType &operator= (TraitObjectType const &other) { + mappings = other.mappings; has_dyn = other.has_dyn; locus = other.locus; type_param_bounds.reserve (other.type_param_bounds.size ()); @@ -209,19 +215,23 @@ protected: public: // Constructor uses Type pointer for polymorphism - ParenthesisedType (std::unique_ptr<Type> type_inside_parens, Location locus) - : type_in_parens (std::move (type_inside_parens)), locus (locus) + ParenthesisedType (Analysis::NodeMapping mappings, + std::unique_ptr<Type> type_inside_parens, Location locus) + : TypeNoBounds (mappings), type_in_parens (std::move (type_inside_parens)), + locus (locus) {} /* Copy constructor uses custom deep copy method for type to preserve * polymorphism */ ParenthesisedType (ParenthesisedType const &other) - : type_in_parens (other.type_in_parens->clone_type ()), locus (other.locus) + : TypeNoBounds (other.mappings), + type_in_parens (other.type_in_parens->clone_type ()), locus (other.locus) {} // overload assignment operator to use custom clone method ParenthesisedType &operator= (ParenthesisedType const &other) { + mappings = other.mappings; type_in_parens = other.type_in_parens->clone_type (); locus = other.locus; return *this; @@ -273,8 +283,10 @@ protected: } public: - ImplTraitTypeOneBound (TraitBound trait_bound, Location locus) - : trait_bound (std::move (trait_bound)), locus (locus) + ImplTraitTypeOneBound (Analysis::NodeMapping mappings, TraitBound trait_bound, + Location locus) + : TypeNoBounds (mappings), trait_bound (std::move (trait_bound)), + locus (locus) {} std::string as_string () const override; @@ -309,10 +321,11 @@ protected: } public: - TraitObjectTypeOneBound (TraitBound trait_bound, Location locus, + TraitObjectTypeOneBound (Analysis::NodeMapping mappings, + TraitBound trait_bound, Location locus, bool is_dyn_dispatch = false) - : has_dyn (is_dyn_dispatch), trait_bound (std::move (trait_bound)), - locus (locus) + : TypeNoBounds (mappings), has_dyn (is_dyn_dispatch), + trait_bound (std::move (trait_bound)), locus (locus) {} std::string as_string () const override; @@ -343,13 +356,16 @@ public: // Returns whether the tuple type is the unit type, i.e. has no elements. bool is_unit_type () const { return elems.empty (); } - TupleType (std::vector<std::unique_ptr<Type> > elems, Location locus) - : elems (std::move (elems)), locus (locus) + TupleType (Analysis::NodeMapping mappings, + std::vector<std::unique_ptr<Type> > elems, Location locus) + : TypeNoBounds (mappings), elems (std::move (elems)), locus (locus) {} // copy constructor with vector clone - TupleType (TupleType const &other) : locus (other.locus) + TupleType (TupleType const &other) + : TypeNoBounds (other.mappings), locus (other.locus) { + mappings = other.mappings; elems.reserve (other.elems.size ()); for (const auto &e : other.elems) elems.push_back (e->clone_type ()); @@ -410,7 +426,9 @@ protected: } public: - NeverType (Location locus) : locus (locus) {} + NeverType (Analysis::NodeMapping mappings, Location locus) + : TypeNoBounds (mappings), locus (locus) + {} std::string as_string () const override { return "! (never type)"; } @@ -439,21 +457,22 @@ public: PointerType get_pointer_type () const { return pointer_type; } // Constructor requires pointer for polymorphism reasons - RawPointerType (PointerType pointer_type, + RawPointerType (Analysis::NodeMapping mappings, PointerType pointer_type, std::unique_ptr<TypeNoBounds> type_no_bounds, Location locus) - : pointer_type (pointer_type), type (std::move (type_no_bounds)), - locus (locus) + : TypeNoBounds (mappings), pointer_type (pointer_type), + type (std::move (type_no_bounds)), locus (locus) {} // Copy constructor calls custom polymorphic clone function RawPointerType (RawPointerType const &other) - : pointer_type (other.pointer_type), + : TypeNoBounds (other.mappings), pointer_type (other.pointer_type), type (other.type->clone_type_no_bounds ()), locus (other.locus) {} // overload assignment operator to use custom clone method RawPointerType &operator= (RawPointerType const &other) { + mappings = other.mappings; pointer_type = other.pointer_type; type = other.type->clone_type_no_bounds (); locus = other.locus; @@ -504,21 +523,24 @@ public: bool has_lifetime () const { return !lifetime.is_error (); } // Constructor - ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds, - Location locus, Lifetime lifetime = Lifetime::error ()) - : lifetime (std::move (lifetime)), has_mut (is_mut), - type (std::move (type_no_bounds)), locus (locus) + ReferenceType (Analysis::NodeMapping mappings, bool is_mut, + std::unique_ptr<TypeNoBounds> type_no_bounds, Location locus, + Lifetime lifetime = Lifetime::error ()) + : TypeNoBounds (mappings), lifetime (std::move (lifetime)), + has_mut (is_mut), type (std::move (type_no_bounds)), locus (locus) {} // Copy constructor with custom clone method ReferenceType (ReferenceType const &other) - : lifetime (other.lifetime), has_mut (other.has_mut), - type (other.type->clone_type_no_bounds ()), locus (other.locus) + : TypeNoBounds (other.mappings), lifetime (other.lifetime), + has_mut (other.has_mut), type (other.type->clone_type_no_bounds ()), + locus (other.locus) {} // Operator overload assignment operator to custom clone the unique pointer ReferenceType &operator= (ReferenceType const &other) { + mappings = other.mappings; lifetime = other.lifetime; has_mut = other.has_mut; type = other.type->clone_type_no_bounds (); @@ -562,20 +584,22 @@ class ArrayType : public TypeNoBounds public: // Constructor requires pointers for polymorphism - ArrayType (std::unique_ptr<Type> type, std::unique_ptr<Expr> array_size, - Location locus) - : elem_type (std::move (type)), size (std::move (array_size)), locus (locus) + ArrayType (Analysis::NodeMapping mappings, std::unique_ptr<Type> type, + std::unique_ptr<Expr> array_size, Location locus) + : TypeNoBounds (mappings), 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 ()), + : TypeNoBounds (mappings), elem_type (other.elem_type->clone_type ()), size (other.size->clone_expr ()), locus (other.locus) {} // Overload assignment operator to deep copy pointers ArrayType &operator= (ArrayType const &other) { + mappings = other.mappings; elem_type = other.elem_type->clone_type (); size = other.size->clone_expr (); locus = other.locus; @@ -620,18 +644,21 @@ class SliceType : public TypeNoBounds public: // Constructor requires pointer for polymorphism - SliceType (std::unique_ptr<Type> type, Location locus) - : elem_type (std::move (type)), locus (locus) + SliceType (Analysis::NodeMapping mappings, std::unique_ptr<Type> type, + Location locus) + : TypeNoBounds (mappings), elem_type (std::move (type)), locus (locus) {} // Copy constructor requires deep copy of Type smart pointer SliceType (SliceType const &other) - : elem_type (other.elem_type->clone_type ()), locus (other.locus) + : TypeNoBounds (other.mappings), elem_type (other.elem_type->clone_type ()), + locus (other.locus) {} // Overload assignment operator to deep copy SliceType &operator= (SliceType const &other) { + mappings = other.mappings; elem_type = other.elem_type->clone_type (); locus = other.locus; @@ -684,7 +711,9 @@ protected: } public: - InferredType (Location locus) : locus (locus) {} + InferredType (Analysis::NodeMapping mappings, Location locus) + : TypeNoBounds (mappings), locus (locus) + {} std::string as_string () const override; @@ -783,11 +812,12 @@ public: // Whether the function has ForLifetimes. bool has_for_lifetimes () const { return !for_lifetimes.empty (); } - BareFunctionType (std::vector<LifetimeParam> lifetime_params, + BareFunctionType (Analysis::NodeMapping mappings, + std::vector<LifetimeParam> lifetime_params, FunctionQualifiers qualifiers, std::vector<MaybeNamedParam> named_params, bool is_variadic, std::unique_ptr<TypeNoBounds> type, Location locus) - : for_lifetimes (std::move (lifetime_params)), + : TypeNoBounds (mappings), for_lifetimes (std::move (lifetime_params)), function_qualifiers (std::move (qualifiers)), params (std::move (named_params)), is_variadic (is_variadic), return_type (std::move (type)), locus (locus) @@ -795,7 +825,7 @@ public: // Copy constructor with clone BareFunctionType (BareFunctionType const &other) - : for_lifetimes (other.for_lifetimes), + : TypeNoBounds (other.mappings), for_lifetimes (other.for_lifetimes), function_qualifiers (other.function_qualifiers), params (other.params), is_variadic (other.is_variadic), return_type (other.return_type->clone_type_no_bounds ()), @@ -805,6 +835,7 @@ public: // Overload assignment operator to deep copy BareFunctionType &operator= (BareFunctionType const &other) { + mappings = other.mappings; for_lifetimes = other.for_lifetimes; function_qualifiers = other.function_qualifiers; params = other.params; diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index b7feb59..cbaa2e9 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -968,9 +968,15 @@ public: virtual void accept_vis (HIRVisitor &vis) = 0; + virtual Analysis::NodeMapping get_mappings () { return mappings; } + protected: + Type (Analysis::NodeMapping mappings) : mappings (mappings) {} + // Clone function implementation as pure virtual method virtual Type *clone_type_impl () const = 0; + + Analysis::NodeMapping mappings; }; // A type without parentheses? - abstract @@ -984,6 +990,8 @@ public: } protected: + TypeNoBounds (Analysis::NodeMapping mappings) : Type (mappings) {} + // Clone function implementation as pure virtual method virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0; diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 9ca763d..b9e7f6a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -49,23 +49,24 @@ public: void visit (AST::ReturnExpr &expr) { - if (expr.has_return_expr ()) - ResolveExpr::go (expr.get_expr (), expr.get_node_id ()); + if (expr.has_returned_expr ()) + ResolveExpr::go (expr.get_returned_expr ().get (), expr.get_node_id ()); } void visit (AST::CallExpr &expr) { - ResolveExpr::go (expr.function.get (), expr.get_node_id ()); + ResolveExpr::go (expr.get_function_expr ().get (), expr.get_node_id ()); expr.iterate_params ([&] (AST::Expr *p) mutable -> bool { ResolveExpr::go (p, expr.get_node_id ()); return true; }); + /// resolver->insert_resolved_name(NodeId refId,NodeId defId) } void visit (AST::AssignmentExpr &expr) { - ResolveExpr::go (expr.get_lhs (), expr.get_node_id ()); - ResolveExpr::go (expr.get_rhs (), expr.get_node_id ()); + ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ()); + ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ()); } void visit (AST::IdentifierExpr &expr) @@ -84,8 +85,8 @@ public: void visit (AST::ArithmeticOrLogicalExpr &expr) { - ResolveExpr::go (expr.get_lhs (), expr.get_node_id ()); - ResolveExpr::go (expr.right_expr.get (), expr.get_node_id ()); + ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ()); + ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ()); } private: diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index ea79fc0..2c21a52 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -23,6 +23,7 @@ #include "rust-ast-full.h" #include "rust-ast-resolve-type.h" #include "rust-ast-resolve-pattern.h" +#include "rust-ast-resolve-stmt.h" namespace Rust { namespace Resolver { @@ -51,11 +52,21 @@ public: param.get_node_id ()); } + // setup parent scoping for names + NodeId scope_node_id = function.get_definition ()->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 ()); + function.get_definition ()->iterate_stmts ( [&] (AST::Stmt *s) mutable -> bool { - // TODO + ResolveStmt::go (s, s->get_node_id ()); return true; }); + + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); } private: diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h index fc2da70..a393d31 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h @@ -78,6 +78,7 @@ public: void visit (AST::IdentifierPattern &pattern) { + printf ("declaration for: %s\n", pattern.as_string ().c_str ()); // if we have a duplicate id this then allows for shadowing correctly // as new refs to this decl will match back here so it is ok to overwrite resolver->get_name_scope ().insert (pattern.get_ident (), diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index 42fb097..623fbd4 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -41,16 +41,16 @@ public: void visit (AST::LetStmt &stmt) { - PatternDeclaration::go (stmt.variables_pattern.get (), stmt.get_node_id ()); + PatternDeclaration::go (stmt.get_pattern ().get (), stmt.get_node_id ()); if (stmt.has_type ()) - ResolveType::go (stmt.type.get (), stmt.get_node_id ()); + ResolveType::go (stmt.get_type ().get (), stmt.get_node_id ()); if (stmt.has_init_expr ()) - ResolveExpr::go (stmt.init_expr.get (), stmt.get_node_id ()); + ResolveExpr::go (stmt.get_init_expr ().get (), stmt.get_node_id ()); } private: - ResolveStmt () : ResolverBase (UNKNOWN_NODEID) {} + ResolveStmt (NodeId parent) : ResolverBase (parent) {} }; } // namespace Resolver diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 664af12..57bd0f3 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -20,8 +20,9 @@ #include "rust-ast-resolve-toplevel.h" #include "rust-ast-resolve-item.h" #include "rust-ast-full.h" +#include "rust-tyty.h" -#define MKBUILTIN_TYPE(_X, _R) \ +#define MKBUILTIN_TYPE(_X, _R, _TY) \ do \ { \ AST::PathIdentSegment seg (_X); \ @@ -34,6 +35,8 @@ = new AST::TypePath (::std::move (segs), \ Linemap::predeclared_location (), false); \ _R.push_back (builtin_type); \ + tyctx->insert_builtin (_TY->get_ref (), builtin_type->get_node_id (), \ + _TY); \ } \ while (0) @@ -43,7 +46,7 @@ namespace Resolver { // Resolver Resolver::Resolver () - : mappings (Analysis::Mappings::get ()), + : mappings (Analysis::Mappings::get ()), tyctx (TypeCheckContext::get ()), name_scope (Scope (mappings->get_current_crate ())), type_scope (Scope (mappings->get_current_crate ())) { @@ -116,22 +119,26 @@ Resolver::get_builtin_types () void Resolver::generate_builtins () { - MKBUILTIN_TYPE ("u8", builtins); - MKBUILTIN_TYPE ("u16", builtins); - MKBUILTIN_TYPE ("u32", builtins); - MKBUILTIN_TYPE ("u64", builtins); - - MKBUILTIN_TYPE ("i8", builtins); - MKBUILTIN_TYPE ("i16", builtins); - MKBUILTIN_TYPE ("i32", builtins); - MKBUILTIN_TYPE ("i64", builtins); - - MKBUILTIN_TYPE ("f32", builtins); - MKBUILTIN_TYPE ("f64", builtins); - - MKBUILTIN_TYPE ("char", builtins); - MKBUILTIN_TYPE ("str", builtins); - MKBUILTIN_TYPE ("bool", builtins); + auto u8 + = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U8); + auto u16 + = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U16); + auto u32 + = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U32); + auto i8 = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I8); + auto i16 + = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I16); + auto i32 + = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I32); + auto rbool = new TyTy::BoolType (mappings->get_next_hir_id ()); + + MKBUILTIN_TYPE ("u8", builtins, u8); + MKBUILTIN_TYPE ("u16", builtins, u16); + MKBUILTIN_TYPE ("u32", builtins, u32); + MKBUILTIN_TYPE ("i8", builtins, i8); + MKBUILTIN_TYPE ("i16", builtins, i16); + MKBUILTIN_TYPE ("i32", builtins, i32); + MKBUILTIN_TYPE ("bool", builtins, rbool); } void diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h index 4aac7d5..2aa592c 100644 --- a/gcc/rust/resolve/rust-name-resolver.h +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -21,6 +21,7 @@ #include "rust-system.h" #include "rust-hir-map.h" +#include "rust-hir-type-check.h" namespace Rust { namespace Resolver { @@ -55,6 +56,15 @@ public: CrateNum get_crate_num () const { return crate_num; } NodeId get_node_id () const { return node_id; } + void iterate_decls (std::function<bool (NodeId)> cb) + { + for (auto it : decls_within_rib) + { + if (!cb (it)) + return; + } + } + private: CrateNum crate_num; NodeId node_id; @@ -174,6 +184,7 @@ private: void generate_builtins (); Analysis::Mappings *mappings; + TypeCheckContext *tyctx; std::vector<AST::TypePath *> builtins; diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 3131af0..fc64994 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -26,16 +26,15 @@ #include "tm.h" #include "tm_p.h" +#include "rust-target.h" + #include "rust-lex.h" #include "rust-parse.h" #include "rust-scan.h" #include "rust-macro-expand.h" -#include "rust-compile.h" -#include "rust-target.h" - -// hir passes wip #include "rust-ast-resolve.h" #include "rust-ast-lower.h" +#include "rust-hir-type-check.h" extern Linemap * rust_get_linemap (); @@ -531,7 +530,7 @@ Session::parse_file (const char *filename) } // lower AST to HIR - HIR::Crate hir = HIR::ASTLowering::Resolve (parsed_crate); + HIR::Crate hir = lower_ast (parsed_crate); if (options.dump_option == CompileOptions::HIR_DUMP) { fprintf (stderr, "%s", hir.as_string ().c_str ()); @@ -539,13 +538,13 @@ Session::parse_file (const char *filename) } // type resolve - // TODO + type_resolution (hir); if (saw_errors ()) return; // do compile - Compile::Compilation::Compile (parsed_crate, backend); + // Compile::Compilation::Compile (parsed_crate, backend); } // TODO: actually implement method @@ -777,6 +776,23 @@ Session::resolution (AST::Crate &crate) fprintf (stderr, "finished name resolution\n"); } +HIR::Crate +Session::lower_ast (AST::Crate &crate) +{ + fprintf (stderr, "started lowering AST\n"); + auto hir = HIR::ASTLowering::Resolve (crate); + fprintf (stderr, "finished lowering AST\n"); + return hir; +} + +void +Session::type_resolution (HIR::Crate &crate) +{ + fprintf (stderr, "started type resolution\n"); + Resolver::TypeResolution::Resolve (crate); + fprintf (stderr, "finished type resolution\n"); +} + void TargetOptions::dump_target_options () const { diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index 2bb1dfb..4836cc8 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -37,6 +37,10 @@ class Lexer; namespace AST { struct Crate; } +// crate forward decl +namespace HIR { +struct Crate; +} /* Data related to target, most useful for conditional compilation and * whatever. */ @@ -240,6 +244,11 @@ private: * Performs name resolution and type resolution, maybe complete gated * feature checking, maybe create buffered lints in future. */ void resolution (AST::Crate &crate); + /* This lowers the AST down to HIR and assigns all mappings from AST + * NodeIds back to HirIds */ + HIR::Crate lower_ast (AST::Crate &crate); + /* This adds the type resolution process */ + void type_resolution (HIR::Crate &crate); }; } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h new file mode 100644 index 0000000..78afff9 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -0,0 +1,256 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_BASE +#define RUST_HIR_TYPE_CHECK_BASE + +#include "rust-diagnostics.h" +#include "rust-hir-type-check.h" +#include "rust-name-resolver.h" +#include "rust-hir-visitor.h" +#include "rust-hir-map.h" + +namespace Rust { +namespace Resolver { + +// base class to allow derivatives to overload as needed +class TypeCheckBase : public HIR::HIRVisitor +{ +public: + virtual ~TypeCheckBase () {} + + // visitor impl + // rust-ast.h + // virtual void visit(AttrInput& attr_input); + // virtual void visit(TokenTree& token_tree); + // virtual void visit(MacroMatch& macro_match); + virtual void visit (HIR::Token &tok) {} + virtual void visit (HIR::DelimTokenTree &delim_tok_tree) {} + virtual void visit (HIR::AttrInputMetaItemContainer &input) {} + // virtual void visit(MetaItem& meta_item) {} + // void vsit(Stmt& stmt) {} + // virtual void visit(Expr& expr) {} + virtual void visit (HIR::IdentifierExpr &ident_expr) {} + // virtual void visit(Pattern& pattern) {} + // virtual void visit(Type& type) {} + // virtual void visit(TypeParamBound& type_param_bound) {} + virtual void visit (HIR::Lifetime &lifetime) {} + // virtual void visit(GenericParam& generic_param) {} + virtual void visit (HIR::LifetimeParam &lifetime_param) {} + // virtual void visit(TraitItem& trait_item) {} + // virtual void visit(InherentImplItem& inherent_impl_item) {} + // virtual void visit(TraitImplItem& trait_impl_item) {} + virtual void visit (HIR::MacroInvocationSemi ¯o) {} + + // rust-path.h + virtual void visit (HIR::PathInExpression &path) {} + virtual void visit (HIR::TypePathSegment &segment) {} + virtual void visit (HIR::TypePathSegmentGeneric &segment) {} + virtual void visit (HIR::TypePathSegmentFunction &segment) {} + virtual void visit (HIR::TypePath &path) {} + virtual void visit (HIR::QualifiedPathInExpression &path) {} + virtual void visit (HIR::QualifiedPathInType &path) {} + + // rust-expr.h + virtual void visit (HIR::LiteralExpr &expr) {} + virtual void visit (HIR::AttrInputLiteral &attr_input) {} + virtual void visit (HIR::MetaItemLitExpr &meta_item) {} + virtual void visit (HIR::MetaItemPathLit &meta_item) {} + virtual void visit (HIR::BorrowExpr &expr) {} + virtual void visit (HIR::DereferenceExpr &expr) {} + virtual void visit (HIR::ErrorPropagationExpr &expr) {} + virtual void visit (HIR::NegationExpr &expr) {} + virtual void visit (HIR::ArithmeticOrLogicalExpr &expr) {} + virtual void visit (HIR::ComparisonExpr &expr) {} + virtual void visit (HIR::LazyBooleanExpr &expr) {} + virtual void visit (HIR::TypeCastExpr &expr) {} + virtual void visit (HIR::AssignmentExpr &expr) {} + virtual void visit (HIR::CompoundAssignmentExpr &expr) {} + virtual void visit (HIR::GroupedExpr &expr) {} + // virtual void visit(ArrayElems& elems) {} + virtual void visit (HIR::ArrayElemsValues &elems) {} + virtual void visit (HIR::ArrayElemsCopied &elems) {} + virtual void visit (HIR::ArrayExpr &expr) {} + virtual void visit (HIR::ArrayIndexExpr &expr) {} + virtual void visit (HIR::TupleExpr &expr) {} + virtual void visit (HIR::TupleIndexExpr &expr) {} + virtual void visit (HIR::StructExprStruct &expr) {} + // virtual void visit(StructExprField& field) {} + virtual void visit (HIR::StructExprFieldIdentifier &field) {} + virtual void visit (HIR::StructExprFieldIdentifierValue &field) {} + virtual void visit (HIR::StructExprFieldIndexValue &field) {} + virtual void visit (HIR::StructExprStructFields &expr) {} + virtual void visit (HIR::StructExprStructBase &expr) {} + virtual void visit (HIR::StructExprTuple &expr) {} + virtual void visit (HIR::StructExprUnit &expr) {} + // virtual void visit(EnumExprField& field) {} + virtual void visit (HIR::EnumExprFieldIdentifier &field) {} + virtual void visit (HIR::EnumExprFieldIdentifierValue &field) {} + virtual void visit (HIR::EnumExprFieldIndexValue &field) {} + virtual void visit (HIR::EnumExprStruct &expr) {} + virtual void visit (HIR::EnumExprTuple &expr) {} + virtual void visit (HIR::EnumExprFieldless &expr) {} + virtual void visit (HIR::CallExpr &expr) {} + virtual void visit (HIR::MethodCallExpr &expr) {} + virtual void visit (HIR::FieldAccessExpr &expr) {} + virtual void visit (HIR::ClosureExprInner &expr) {} + virtual void visit (HIR::BlockExpr &expr) {} + virtual void visit (HIR::ClosureExprInnerTyped &expr) {} + virtual void visit (HIR::ContinueExpr &expr) {} + virtual void visit (HIR::BreakExpr &expr) {} + virtual void visit (HIR::RangeFromToExpr &expr) {} + virtual void visit (HIR::RangeFromExpr &expr) {} + virtual void visit (HIR::RangeToExpr &expr) {} + virtual void visit (HIR::RangeFullExpr &expr) {} + virtual void visit (HIR::RangeFromToInclExpr &expr) {} + virtual void visit (HIR::RangeToInclExpr &expr) {} + virtual void visit (HIR::ReturnExpr &expr) {} + virtual void visit (HIR::UnsafeBlockExpr &expr) {} + virtual void visit (HIR::LoopExpr &expr) {} + virtual void visit (HIR::WhileLoopExpr &expr) {} + virtual void visit (HIR::WhileLetLoopExpr &expr) {} + virtual void visit (HIR::ForLoopExpr &expr) {} + virtual void visit (HIR::IfExpr &expr) {} + virtual void visit (HIR::IfExprConseqElse &expr) {} + virtual void visit (HIR::IfExprConseqIf &expr) {} + virtual void visit (HIR::IfExprConseqIfLet &expr) {} + virtual void visit (HIR::IfLetExpr &expr) {} + virtual void visit (HIR::IfLetExprConseqElse &expr) {} + virtual void visit (HIR::IfLetExprConseqIf &expr) {} + virtual void visit (HIR::IfLetExprConseqIfLet &expr) {} + // virtual void visit(MatchCase& match_case) {} + // virtual void visit (HIR::MatchCaseBlockExpr &match_case) {} + // virtual void visit (HIR::MatchCaseExpr &match_case) {} + virtual void visit (HIR::MatchExpr &expr) {} + virtual void visit (HIR::AwaitExpr &expr) {} + virtual void visit (HIR::AsyncBlockExpr &expr) {} + + // rust-item.h + virtual void visit (HIR::TypeParam ¶m) {} + // virtual void visit(WhereClauseItem& item) {} + virtual void visit (HIR::LifetimeWhereClauseItem &item) {} + virtual void visit (HIR::TypeBoundWhereClauseItem &item) {} + virtual void visit (HIR::Method &method) {} + virtual void visit (HIR::ModuleBodied &module) {} + virtual void visit (HIR::ModuleNoBody &module) {} + virtual void visit (HIR::ExternCrate &crate) {} + // virtual void visit(UseTree& use_tree) {} + virtual void visit (HIR::UseTreeGlob &use_tree) {} + virtual void visit (HIR::UseTreeList &use_tree) {} + virtual void visit (HIR::UseTreeRebind &use_tree) {} + virtual void visit (HIR::UseDeclaration &use_decl) {} + virtual void visit (HIR::Function &function) {} + virtual void visit (HIR::TypeAlias &type_alias) {} + virtual void visit (HIR::StructStruct &struct_item) {} + virtual void visit (HIR::TupleStruct &tuple_struct) {} + virtual void visit (HIR::EnumItem &item) {} + virtual void visit (HIR::EnumItemTuple &item) {} + virtual void visit (HIR::EnumItemStruct &item) {} + virtual void visit (HIR::EnumItemDiscriminant &item) {} + virtual void visit (HIR::Enum &enum_item) {} + virtual void visit (HIR::Union &union_item) {} + virtual void visit (HIR::ConstantItem &const_item) {} + virtual void visit (HIR::StaticItem &static_item) {} + virtual void visit (HIR::TraitItemFunc &item) {} + virtual void visit (HIR::TraitItemMethod &item) {} + virtual void visit (HIR::TraitItemConst &item) {} + virtual void visit (HIR::TraitItemType &item) {} + virtual void visit (HIR::Trait &trait) {} + virtual void visit (HIR::InherentImpl &impl) {} + virtual void visit (HIR::TraitImpl &impl) {} + // virtual void visit(ExternalItem& item) {} + virtual void visit (HIR::ExternalStaticItem &item) {} + virtual void visit (HIR::ExternalFunctionItem &item) {} + virtual void visit (HIR::ExternBlock &block) {} + + // rust-macro.h + virtual void visit (HIR::MacroMatchFragment &match) {} + virtual void visit (HIR::MacroMatchRepetition &match) {} + virtual void visit (HIR::MacroMatcher &matcher) {} + virtual void visit (HIR::MacroRulesDefinition &rules_def) {} + virtual void visit (HIR::MacroInvocation ¯o_invoc) {} + virtual void visit (HIR::MetaItemPath &meta_item) {} + virtual void visit (HIR::MetaItemSeq &meta_item) {} + virtual void visit (HIR::MetaWord &meta_item) {} + virtual void visit (HIR::MetaNameValueStr &meta_item) {} + virtual void visit (HIR::MetaListPaths &meta_item) {} + virtual void visit (HIR::MetaListNameValueStr &meta_item) {} + + // rust-pattern.h + virtual void visit (HIR::LiteralPattern &pattern) {} + virtual void visit (HIR::IdentifierPattern &pattern) {} + virtual void visit (HIR::WildcardPattern &pattern) {} + // virtual void visit(RangePatternBound& bound) {} + virtual void visit (HIR::RangePatternBoundLiteral &bound) {} + virtual void visit (HIR::RangePatternBoundPath &bound) {} + virtual void visit (HIR::RangePatternBoundQualPath &bound) {} + virtual void visit (HIR::RangePattern &pattern) {} + virtual void visit (HIR::ReferencePattern &pattern) {} + // virtual void visit(StructPatternField& field) {} + virtual void visit (HIR::StructPatternFieldTuplePat &field) {} + virtual void visit (HIR::StructPatternFieldIdentPat &field) {} + virtual void visit (HIR::StructPatternFieldIdent &field) {} + virtual void visit (HIR::StructPattern &pattern) {} + // virtual void visit(TupleStructItems& tuple_items) {} + virtual void visit (HIR::TupleStructItemsNoRange &tuple_items) {} + virtual void visit (HIR::TupleStructItemsRange &tuple_items) {} + virtual void visit (HIR::TupleStructPattern &pattern) {} + // virtual void visit(TuplePatternItems& tuple_items) {} + virtual void visit (HIR::TuplePatternItemsMultiple &tuple_items) {} + virtual void visit (HIR::TuplePatternItemsRanged &tuple_items) {} + virtual void visit (HIR::TuplePattern &pattern) {} + virtual void visit (HIR::GroupedPattern &pattern) {} + virtual void visit (HIR::SlicePattern &pattern) {} + + // rust-stmt.h + virtual void visit (HIR::EmptyStmt &stmt) {} + virtual void visit (HIR::LetStmt &stmt) {} + virtual void visit (HIR::ExprStmtWithoutBlock &stmt) {} + virtual void visit (HIR::ExprStmtWithBlock &stmt) {} + + // rust-type.h + virtual void visit (HIR::TraitBound &bound) {} + virtual void visit (HIR::ImplTraitType &type) {} + virtual void visit (HIR::TraitObjectType &type) {} + virtual void visit (HIR::ParenthesisedType &type) {} + virtual void visit (HIR::ImplTraitTypeOneBound &type) {} + virtual void visit (HIR::TraitObjectTypeOneBound &type) {} + virtual void visit (HIR::TupleType &type) {} + virtual void visit (HIR::NeverType &type) {} + virtual void visit (HIR::RawPointerType &type) {} + virtual void visit (HIR::ReferenceType &type) {} + virtual void visit (HIR::ArrayType &type) {} + virtual void visit (HIR::SliceType &type) {} + virtual void visit (HIR::InferredType &type) {} + virtual void visit (HIR::BareFunctionType &type) {} + +protected: + TypeCheckBase () + : mappings (Analysis::Mappings::get ()), resolver (Resolver::get ()), + context (TypeCheckContext::get ()) + {} + + Analysis::Mappings *mappings; + Resolver *resolver; + TypeCheckContext *context; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_BASE diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h new file mode 100644 index 0000000..2e715e9 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -0,0 +1,173 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_EXPR +#define RUST_HIR_TYPE_CHECK_EXPR + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-tyty.h" +#include "rust-tyty-call.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckExpr : public TypeCheckBase +{ +public: + static TyTy::TyBase *Resolve (HIR::Expr *expr) + { + TypeCheckExpr resolver; + expr->accept_vis (resolver); + if (resolver.infered != nullptr) + resolver.context->insert_type (expr->get_mappings ().get_hirid (), + resolver.infered); + + return resolver.infered; + } + + void visit (HIR::ReturnExpr &expr) + { + auto ret = context->peek_return_type (); + rust_assert (ret != nullptr); + + auto expr_ty = TypeCheckExpr::Resolve (expr.get_expr ()); + infered = ret->combine (expr_ty); + } + + void visit (HIR::CallExpr &expr) + { + auto fn = expr.get_fnexpr (); + auto fn_node_id = fn->get_mappings ().get_nodeid (); + + // then lookup the reference_node_id + NodeId ref_node_id; + if (!resolver->lookup_resolved_name (fn_node_id, &ref_node_id)) + { + rust_error_at (expr.get_locus (), + "Failed to lookup reference for node: %s", + expr.as_string ().c_str ()); + return; + } + + // node back to HIR + HirId ref; + if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), + ref_node_id, &ref)) + { + rust_error_at (expr.get_locus (), "reverse lookup failure"); + return; + } + + // check if this has a type + TyTy::TyBase *lookup; + if (!context->lookup_type (ref, &lookup)) + { + // FIXME we need to be able to lookup the location info for the + // reference here + rust_error_at (expr.get_locus (), "consider giving this a type: %s", + expr.as_string ().c_str ()); + return; + } + + infered = TyTy::TypeCheckCallExpr::go (lookup, expr); + } + + void visit (HIR::AssignmentExpr &expr) + { + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + + infered = lhs->combine (rhs); + } + + void visit (HIR::IdentifierExpr &expr) + { + NodeId ast_node_id = expr.get_mappings ().get_nodeid (); + + // then lookup the reference_node_id + NodeId ref_node_id; + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + { + rust_error_at (expr.get_locus (), + "Failed to lookup reference for node: %s", + expr.as_string ().c_str ()); + return; + } + + // node back to HIR + HirId ref; + if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), + ref_node_id, &ref)) + { + rust_error_at (expr.get_locus (), "reverse lookup failure"); + return; + } + + // check if this has a type + TyTy::TyBase *lookup; + if (!context->lookup_type (ref, &lookup)) + { + // FIXME we need to be able to lookup the location info for the + // reference here + rust_error_at (expr.get_locus (), "consider giving this a type: %s", + expr.as_string ().c_str ()); + return; + } + + // FIXME this needs to be cloned for memory management later on + infered = lookup; + } + + void visit (HIR::LiteralExpr &expr) + { + switch (expr.get_lit_type ()) + { + case HIR::Literal::LitType::INT: + infered = new TyTy::IntType (expr.get_mappings ().get_hirid (), + TyTy::IntType::IntKind::I32); + break; + + case HIR::Literal::LitType::BOOL: + infered = new TyTy::BoolType (expr.get_mappings ().get_hirid ()); + break; + + default: + gcc_unreachable (); + break; + } + } + + void visit (HIR::ArithmeticOrLogicalExpr &expr) + { + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + + infered = lhs->combine (rhs); + } + +private: + TypeCheckExpr () : TypeCheckBase (), infered (nullptr) {} + + TyTy::TyBase *infered; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_EXPR diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h new file mode 100644 index 0000000..29d6db6 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -0,0 +1,90 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_ITEM +#define RUST_HIR_TYPE_CHECK_ITEM + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-type.h" +#include "rust-hir-type-check-stmt.h" +#include "rust-tyty-visitor.h" + +namespace Rust { +namespace Resolver { + +class ResolveFnType : public TyTy::TyVisitor +{ +public: + ResolveFnType (TyTy::TyBase *base) : base (base), state (nullptr) {} + + TyTy::TyBase *go () + { + base->accept_vis (*this); + if (state == nullptr) + gcc_unreachable (); + + return state; + } + + void visit (TyTy::FnType &type) override { state = type.return_type (); } + +private: + TyTy::TyBase *base; + TyTy::TyBase *state; +}; + +class TypeCheckItem : public TypeCheckBase +{ +public: + static void Resolve (HIR::Item *item) + { + TypeCheckItem resolver; + item->accept_vis (resolver); + } + + void visit (HIR::Function &function) + { + TyTy::TyBase *fnType; + if (!context->lookup_type (function.get_mappings ().get_hirid (), &fnType)) + { + rust_error_at (function.locus, "failed to lookup function type"); + return; + } + // need to get the return type from this + ResolveFnType resolve_fn_type (fnType); + context->push_return_type (resolve_fn_type.go ()); + + // walk statements to make sure they are all typed correctly and they match + // up + function.function_body->iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { + TypeCheckStmt::Resolve (s); + return true; + }); + + context->pop_return_type (); + } + +private: + TypeCheckItem () : TypeCheckBase () {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_ITEM diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h new file mode 100644 index 0000000..39c48f0 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -0,0 +1,86 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_STMT +#define RUST_HIR_TYPE_CHECK_STMT + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-type.h" +#include "rust-hir-type-check-expr.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckStmt : public TypeCheckBase +{ +public: + static void Resolve (HIR::Stmt *stmt) + { + TypeCheckStmt resolver; + stmt->accept_vis (resolver); + } + + void visit (HIR::LetStmt &stmt) + { + TyTy::TyBase *init_expr_ty = nullptr; + if (stmt.has_init_expr ()) + init_expr_ty = TypeCheckExpr::Resolve (stmt.get_init_expr ()); + + TyTy::TyBase *specified_ty = nullptr; + if (stmt.has_type ()) + specified_ty = TypeCheckType::Resolve (stmt.get_type ()); + + // let x:i32 = 123; + if (specified_ty != nullptr && init_expr_ty != nullptr) + { + context->insert_type (stmt.get_mappings ().get_hirid (), + specified_ty->combine (init_expr_ty)); + } + else + { + // let x:i32; + if (specified_ty != nullptr) + { + context->insert_type (stmt.get_mappings ().get_hirid (), + specified_ty); + } + // let x = 123; + else if (init_expr_ty != nullptr) + { + context->insert_type (stmt.get_mappings ().get_hirid (), + init_expr_ty); + } + // let x; + else + { + context->insert_type (stmt.get_mappings ().get_hirid (), + new TyTy::InferType ( + stmt.get_mappings ().get_hirid ())); + } + } + } + +private: + TypeCheckStmt () : TypeCheckBase () {} +}; // namespace Resolver + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_STMT diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h new file mode 100644 index 0000000..c15aaef --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -0,0 +1,63 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_TOPLEVEL +#define RUST_HIR_TYPE_CHECK_TOPLEVEL + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-type.h" +#include "rust-tyty.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckTopLevel : public TypeCheckBase +{ +public: + static void Resolve (HIR::Item *item) + { + TypeCheckTopLevel resolver; + item->accept_vis (resolver); + } + + void visit (HIR::Function &function) + { + TyTy::TyBase *ret_type = nullptr; + if (!function.has_function_return_type ()) + ret_type = new TyTy::UnitType (function.get_mappings ().get_hirid ()); + else + ret_type = TypeCheckType::Resolve (function.return_type.get ()); + + std::vector<TyTy::TyBase *> params; + for (auto ¶m : function.function_params) + params.push_back (TypeCheckType::Resolve (param.type.get ())); + + auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), + params, ret_type); + context->insert_type (function.get_mappings ().get_hirid (), fnType); + } + +private: + TypeCheckTopLevel () : TypeCheckBase () {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_TOPLEVEL diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h new file mode 100644 index 0000000..d8721a3 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -0,0 +1,81 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_TYPE +#define RUST_HIR_TYPE_CHECK_TYPE + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckType : public TypeCheckBase +{ +public: + static TyTy::TyBase *Resolve (HIR::Type *type) + { + TypeCheckType resolver; + type->accept_vis (resolver); + + if (resolver.translated != nullptr) + resolver.context->insert_type (type->get_mappings ().get_hirid (), + resolver.translated); + + return resolver.translated; + } + + virtual void visit (HIR::TypePath &path) + { + // check if this is already defined or not + if (context->lookup_type (path.get_mappings ().get_hirid (), &translated)) + return; + + // lookup the Node this resolves to + NodeId ref; + if (!resolver->lookup_resolved_type (path.get_mappings ().get_nodeid (), + &ref)) + { + rust_error_at (path.get_locus (), "Type was not resolved"); + return; + } + + HirId hir_lookup; + if (context->lookup_type_by_node_id (ref, &hir_lookup)) + { + // we got an HIR node + if (context->lookup_type (hir_lookup, &translated)) + return; + } + + // this might be a struct type reference + // TODO + printf ("UNREACHABLE %s\n", path.as_string ().c_str ()); + gcc_unreachable (); + } + +private: + TypeCheckType () : TypeCheckBase (), translated (nullptr) {} + + TyTy::TyBase *translated; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_TYPE diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc new file mode 100644 index 0000000..f9dbe49 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -0,0 +1,38 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-hir-type-check.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-toplevel.h" +#include "rust-hir-type-check-item.h" + +namespace Rust { +namespace Resolver { + +void +TypeResolution::Resolve (HIR::Crate &crate) +{ + for (auto it = crate.items.begin (); it != crate.items.end (); it++) + TypeCheckTopLevel::Resolve (it->get ()); + + for (auto it = crate.items.begin (); it != crate.items.end (); it++) + TypeCheckItem::Resolve (it->get ()); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h new file mode 100644 index 0000000..5a8abe1 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -0,0 +1,66 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK +#define RUST_HIR_TYPE_CHECK + +#include "rust-hir-full-decls.h" +#include "rust-hir-map.h" +#include "rust-tyty.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckContext +{ +public: + static TypeCheckContext *get (); + + ~TypeCheckContext (); + + void insert_builtin (HirId id, NodeId ref, TyTy::TyBase *type); + + void insert_type (HirId id, TyTy::TyBase *type); + bool lookup_type (HirId id, TyTy::TyBase **type); + + void insert_type_by_node_id (NodeId ref, HirId id); + bool lookup_type_by_node_id (NodeId ref, HirId *id); + + TyTy::TyBase *peek_return_type (); + void push_return_type (TyTy::TyBase *return_type); + void pop_return_type (); + +private: + TypeCheckContext (); + + std::map<NodeId, HirId> node_id_refs; + std::map<HirId, TyTy::TyBase *> resolved; + std::vector<std::unique_ptr<TyTy::TyBase> > builtins; + std::vector<TyTy::TyBase *> return_type_stack; +}; + +class TypeResolution +{ +public: + static void Resolve (HIR::Crate &crate); +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc new file mode 100644 index 0000000..195291e --- /dev/null +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -0,0 +1,104 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Resolver { + +TypeCheckContext * +TypeCheckContext::get () +{ + static TypeCheckContext *instance; + if (instance == nullptr) + instance = new TypeCheckContext (); + + return instance; +} + +TypeCheckContext::TypeCheckContext () {} + +TypeCheckContext::~TypeCheckContext () {} + +void +TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::TyBase *type) +{ + printf ("inserting builtin: hir %u node %u -> %s\n", id, ref, + type->as_string ().c_str ()); + node_id_refs[ref] = id; + resolved[id] = type; + builtins.push_back (std::unique_ptr<TyTy::TyBase> (type)); +} + +void +TypeCheckContext::insert_type (HirId id, TyTy::TyBase *type) +{ + rust_assert (resolved.find (id) == resolved.end ()); + rust_assert (type != nullptr); + resolved[id] = type; +} + +bool +TypeCheckContext::lookup_type (HirId id, TyTy::TyBase **type) +{ + auto it = resolved.find (id); + if (it == resolved.end ()) + return false; + + *type = it->second; + return true; +} + +void +TypeCheckContext::insert_type_by_node_id (NodeId ref, HirId id) +{ + rust_assert (node_id_refs.find (ref) == node_id_refs.end ()); + node_id_refs[ref] = id; +} + +bool +TypeCheckContext::lookup_type_by_node_id (NodeId ref, HirId *id) +{ + auto it = node_id_refs.find (ref); + if (it == node_id_refs.end ()) + return false; + + *id = it->second; + return true; +} + +TyTy::TyBase * +TypeCheckContext::peek_return_type () +{ + return return_type_stack.back (); +} + +void +TypeCheckContext::push_return_type (TyTy::TyBase *return_type) +{ + return_type_stack.push_back (return_type); +} + +void +TypeCheckContext::pop_return_type () +{ + return_type_stack.pop_back (); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h new file mode 100644 index 0000000..d1341df --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -0,0 +1,53 @@ +// Copyright (C) 2020 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_CALL +#define RUST_TYTY_CALL + +#include "rust-diagnostics.h" +#include "rust-hir-full.h" +#include "rust-tyty-visitor.h" +#include "rust-tyty.h" + +namespace Rust { +namespace TyTy { + +class TypeCheckCallExpr : private TyVisitor +{ +public: + static TyBase *go (TyBase *ref, HIR::CallExpr &call) + { + TypeCheckCallExpr checker (call); + ref->accept_vis (checker); + return checker.resolved; + } + ~TypeCheckCallExpr () {} + + void visit (FnType &type) override; + +private: + TypeCheckCallExpr (HIR::CallExpr &c) : resolved (nullptr), call (c) {} + + TyBase *resolved; + HIR::CallExpr &call; +}; + +} // namespace TyTy +} // namespace Rust + +#endif // RUST_TYTY_CALL diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h new file mode 100644 index 0000000..375d909 --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -0,0 +1,241 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_TYTY_RULES +#define RUST_TYTY_RULES + +#include "rust-diagnostics.h" +#include "rust-tyty.h" +#include "rust-tyty-visitor.h" +#include "rust-hir-map.h" + +namespace Rust { +namespace TyTy { + +class BaseRules : public TyVisitor +{ +public: + virtual ~BaseRules () {} + + virtual void visit (UnitType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + + virtual void visit (InferType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + + virtual void visit (FnType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + + virtual void visit (ParamType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + + virtual void visit (BoolType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + + virtual void visit (IntType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + + virtual void visit (UintType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + +protected: + BaseRules (TyBase *base) : mappings (Analysis::Mappings::get ()), base (base) + {} + + Analysis::Mappings *mappings; + +private: + TyBase *base; +}; + +class InferRules : protected BaseRules +{ +public: + InferRules (InferType *base) + : BaseRules (base), base (base), resolved (nullptr) + {} + ~InferRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + +private: + InferType *base; + TyBase *resolved; +}; + +class UnitRules : protected BaseRules +{ +public: + UnitRules (UnitType *base) : BaseRules (base), base (base), resolved (nullptr) + {} + ~UnitRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + +private: + UnitType *base; + TyBase *resolved; +}; + +class FnRules : protected BaseRules +{ +public: + FnRules (FnType *base) : BaseRules (base), base (base), resolved (nullptr) {} + ~FnRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + +private: + FnType *base; + TyBase *resolved; +}; + +class ParamRules : protected BaseRules +{ +public: + ParamRules (ParamType *base) + : BaseRules (base), base (base), resolved (nullptr) + {} + ~ParamRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + +private: + ParamType *base; + TyBase *resolved; +}; + +class BoolRules : protected BaseRules +{ +public: + BoolRules (BoolType *base) : BaseRules (base), base (base), resolved (nullptr) + {} + ~BoolRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + + void visit (BoolType &type) override + { + resolved = new BoolType (type.get_ref ()); + } + +private: + BoolType *base; + TyBase *resolved; +}; + +class IntRules : protected BaseRules +{ +public: + IntRules (IntType *base) : BaseRules (base), base (base), resolved (nullptr) + {} + ~IntRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + + void visit (IntType &type) override + { + // FIXME we should look at the IntTypeKind and check if i8 vs i16 etc.. + resolved = new IntType (type.get_ref (), type.get_kind ()); + } + +private: + IntType *base; + TyBase *resolved; +}; + +class UintRules : protected BaseRules +{ +public: + UintRules (UintType *base) : BaseRules (base), base (base), resolved (nullptr) + {} + ~UintRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + + void visit (UintType &type) override + { + // FIXME we should look at the IntTypeKind and check if u8 vs u16 etc.. + resolved = new UintType (type.get_ref (), type.get_kind ()); + } + +private: + UintType *base; + TyBase *resolved; +}; + +} // namespace TyTy +} // namespace Rust + +#endif // RUST_TYTY_RULES diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h new file mode 100644 index 0000000..68a8a43 --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -0,0 +1,42 @@ +// Copyright (C) 2020 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_VISITOR +#define RUST_TYTY_VISITOR + +#include "rust-tyty.h" + +namespace Rust { +namespace TyTy { + +class TyVisitor +{ +public: + virtual void visit (UnitType &type) {} + virtual void visit (InferType &type) {} + virtual void visit (FnType &type) {} + virtual void visit (ParamType &type) {} + virtual void visit (BoolType &type) {} + virtual void visit (IntType &type) {} + virtual void visit (UintType &type) {} +}; + +} // namespace TyTy +} // namespace Rust + +#endif // RUST_TYTY_VISITOR diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc new file mode 100644 index 0000000..2124408 --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -0,0 +1,223 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-tyty.h" +#include "rust-tyty-visitor.h" +#include "rust-tyty-call.h" +#include "rust-hir-type-check-expr.h" +#include "rust-tyty-rules.h" + +namespace Rust { +namespace TyTy { + +void +UnitType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +UnitType::as_string () const +{ + return "()"; +} + +TyBase * +UnitType::combine (TyBase *other) +{ + UnitRules r (this); + return r.combine (other); +} + +void +InferType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +InferType::as_string () const +{ + return "[_]"; +} + +TyBase * +InferType::combine (TyBase *other) +{ + InferRules r (this); + return r.combine (other); +} + +void +FnType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +FnType::as_string () const +{ + std::string params_str = ""; + for (auto ¶m : params) + { + params_str += param->as_string (); + params_str += ","; + } + + std::string ret_str = type->as_string (); + return "fn (" + params_str + ") -> " + ret_str; +} + +TyBase * +FnType::combine (TyBase *other) +{ + FnRules r (this); + return r.combine (other); +} + +void +ParamType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +ParamType::as_string () const +{ + return "(" + type->as_string () + ")"; +} + +TyBase * +ParamType::combine (TyBase *other) +{ + ParamRules r (this); + return r.combine (other); +} + +void +BoolType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +BoolType::as_string () const +{ + return "bool"; +} + +TyBase * +BoolType::combine (TyBase *other) +{ + BoolRules r (this); + return r.combine (other); +} + +void +IntType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +IntType::as_string () const +{ + switch (int_kind) + { + case I8: + return "i8"; + case I16: + return "i16"; + case I32: + return "i32"; + } + gcc_unreachable (); + return "__unknown_int_type"; +} + +TyBase * +IntType::combine (TyBase *other) +{ + IntRules r (this); + return r.combine (other); +} + +void +UintType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +UintType::as_string () const +{ + switch (uint_kind) + { + case U8: + return "u8"; + case U16: + return "u16"; + case U32: + return "u32"; + } + gcc_unreachable (); + return "__unknown_uint_type"; +} + +TyBase * +UintType::combine (TyBase *other) +{ + UintRules r (this); + return r.combine (other); +} + +void +TypeCheckCallExpr::visit (FnType &type) +{ + if (call.num_params () != type.num_params ()) + { + rust_error_at (call.get_locus (), "differing number of arguments"); + return; + } + + size_t i = 0; + call.iterate_params ([&] (HIR::Expr *p) mutable -> bool { + TyBase *pt = type.param_at (i); + auto t = Resolver::TypeCheckExpr::Resolve (p); + if (t == nullptr) + { + rust_error_at (p->get_locus_slow (), "failed to resolve type"); + return false; + } + + auto res = pt->combine (t); + if (res == nullptr) + return false; + + i++; + return true; + }); + + if (i != call.num_params ()) + return; + + resolved = type.get_return_type (); +} + +} // namespace TyTy +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h new file mode 100644 index 0000000..688643c --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty.h @@ -0,0 +1,208 @@ +// Copyright (C) 2020 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 +#define RUST_TYTY + +#include "rust-hir-map.h" + +namespace Rust { +namespace TyTy { + +// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variants +enum TypeKind +{ + INFER, + ADT, + STR, + REF, + PARAM, + ARRAY, + FNDEF, + TUPLE, + BOOL, + CHAR, + INT, + UINT, + FLOAT, + UNIT, + // there are more to add... +}; + +class TyVisitor; +class TyBase +{ +public: + ~TyBase () {} + + HirId get_ref () const { return ref; } + + virtual void accept_vis (TyVisitor &vis) = 0; + + virtual bool is_unit () const { return false; } + + virtual std::string as_string () const = 0; + + virtual TyBase *combine (TyBase *other) = 0; + +protected: + TyBase (HirId ref, TypeKind kind) : kind (kind), ref (ref) {} + + TypeKind kind; + HirId ref; +}; + +class InferType : public TyBase +{ +public: + InferType (HirId ref) : TyBase (ref, TypeKind::INFER) {} + + void accept_vis (TyVisitor &vis) override; + + bool is_unit () const override { return true; } + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; +}; + +class UnitType : public TyBase +{ +public: + UnitType (HirId ref) : TyBase (ref, TypeKind::UNIT) {} + + void accept_vis (TyVisitor &vis) override; + + bool is_unit () const override { return true; } + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; +}; + +class FnType : public TyBase +{ +public: + FnType (HirId ref, std::vector<TyBase *> params, TyBase *type) + : TyBase (ref, TypeKind::FNDEF), params (params), type (type) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *return_type () { return type; } + + TyBase *combine (TyBase *other) override; + + size_t num_params () const { return params.size (); } + + TyBase *param_at (size_t idx) { return params[idx]; } + + TyBase *get_return_type () { return type; } + +private: + std::vector<TyBase *> params; + TyBase *type; +}; + +class ParamType : public TyBase +{ +public: + ParamType (HirId ref, TyBase *type) + : TyBase (ref, TypeKind::PARAM), type (type) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + +private: + TyBase *type; +}; + +class BoolType : public TyBase +{ +public: + BoolType (HirId ref) : TyBase (ref, TypeKind::BOOL) {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; +}; + +class IntType : public TyBase +{ +public: + enum IntKind + { + I8, + I16, + I32, + }; + + IntType (HirId ref, IntKind kind) + : TyBase (ref, TypeKind::INT), int_kind (kind) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + IntKind get_kind () const { return int_kind; } + +private: + IntKind int_kind; +}; + +class UintType : public TyBase +{ +public: + enum UintKind + { + U8, + U16, + U32, + }; + + UintType (HirId ref, UintKind kind) + : TyBase (ref, TypeKind::UINT), uint_kind (kind) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + UintKind get_kind () const { return uint_kind; } + +private: + UintKind uint_kind; +}; + +} // namespace TyTy +} // namespace Rust + +#endif // RUST_TYTY diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 094d0e3..70c59f3 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -133,6 +133,8 @@ Mappings::get_current_crate () hirIdIter[currentCrateNum] = UNKNOWN_HIRID; nodeIdIter[currentCrateNum] = UNKNOWN_NODEID; localIdIter[currentCrateNum] = UNKNOWN_LOCAL_DEFID; + nodeIdToHirMappings[currentCrateNum] = {}; + locations[currentCrateNum] = {}; } return currentCrateNum; @@ -157,7 +159,7 @@ Mappings::get_next_hir_id (CrateNum crateNum) auto id = it->second + 1; hirIdIter[crateNum] = id; - return id++; + return id; } LocalDefId @@ -238,6 +240,7 @@ Mappings::insert_hir_item (CrateNum crateNum, HirId id, HIR::Item *item) rust_assert (lookup_hir_item (crateNum, id) == nullptr); hirItemMappings[crateNum][id] = item; + nodeIdToHirMappings[crateNum][item->get_mappings ().get_nodeid ()] = id; } HIR::Item * @@ -260,6 +263,8 @@ Mappings::insert_hir_expr (CrateNum crateNum, HirId id, HIR::Expr *expr) rust_assert (lookup_hir_expr (crateNum, id) == nullptr); hirExprMappings[crateNum][id] = expr; + nodeIdToHirMappings[crateNum][expr->get_mappings ().get_nodeid ()] = id; + insert_location (crateNum, id, expr->get_locus_slow ()); } HIR::Expr * @@ -277,6 +282,29 @@ Mappings::lookup_hir_expr (CrateNum crateNum, HirId id) } void +Mappings::insert_hir_type (CrateNum crateNum, HirId id, HIR::Type *type) +{ + rust_assert (lookup_hir_type (crateNum, id) == nullptr); + + hirTypeMappings[crateNum][id] = type; + nodeIdToHirMappings[crateNum][type->get_mappings ().get_nodeid ()] = id; +} + +HIR::Type * +Mappings::lookup_hir_type (CrateNum crateNum, HirId id) +{ + auto it = hirTypeMappings.find (crateNum); + if (it == hirTypeMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void Mappings::insert_local_defid_mapping (CrateNum crateNum, LocalDefId id, HIR::Item *item) { @@ -314,5 +342,40 @@ Mappings::walk_local_defids_for_crate (CrateNum crateNum, } } +bool +Mappings::lookup_node_to_hir (CrateNum crate, NodeId id, HirId *ref) +{ + auto it = nodeIdToHirMappings.find (crate); + if (it == nodeIdToHirMappings.end ()) + return false; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return false; + + *ref = iy->second; + return true; +} + +void +Mappings::insert_location (CrateNum crate, HirId id, Location locus) +{ + locations[crate][id] = locus; +} + +Location +Mappings::lookup_location (CrateNum crate, HirId id) +{ + auto it = locations.find (crate); + if (it == locations.end ()) + return Location (); + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return Location (); + + return iy->second; +} + } // namespace Analysis } // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 8929ca4..7fc8777 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -20,6 +20,7 @@ #define RUST_HIR_MAP_H #include "rust-system.h" +#include "rust-location.h" #include "rust-ast-full-decls.h" #include "rust-hir-full-decls.h" @@ -40,11 +41,11 @@ typedef uint64_t DefId; #define DEF_ID_CRATE_MASK 0xFFFFFFFF00000000 #define DEF_ID_LOCAL_DEF_MASK 0x00000000FFFFFFFF -#define UNKNOWN_CREATENUM ((uint32_t) (-1)) -#define UNKNOWN_NODEID ((uint32_t) (-1)) -#define UNKNOWN_HIRID ((uint32_t) (-1)) -#define UNKNOWN_LOCAL_DEFID ((uint32_t) (-1)) -#define UNKNOWN_DEFID ((uint64_t) (-1)) +#define UNKNOWN_CREATENUM ((uint32_t) (0)) +#define UNKNOWN_NODEID ((uint32_t) (0)) +#define UNKNOWN_HIRID ((uint32_t) (0)) +#define UNKNOWN_LOCAL_DEFID ((uint32_t) (0)) +#define UNKNOWN_DEFID ((uint64_t) (0)) namespace Analysis { @@ -86,7 +87,10 @@ public: NodeId get_next_node_id () { return get_next_node_id (get_current_crate ()); } NodeId get_next_node_id (CrateNum crateNum); + + HirId get_next_hir_id () { return get_next_hir_id (get_current_crate ()); } HirId get_next_hir_id (CrateNum crateNum); + LocalDefId get_next_localdef_id (CrateNum crateNum); AST::Crate *get_ast_crate (CrateNum crateNum); @@ -108,9 +112,21 @@ public: void insert_hir_expr (CrateNum crateNum, HirId id, HIR::Expr *expr); HIR::Expr *lookup_hir_expr (CrateNum crateNum, HirId id); + void insert_hir_type (CrateNum crateNum, HirId id, HIR::Type *type); + HIR::Type *lookup_hir_type (CrateNum crateNum, HirId id); + void walk_local_defids_for_crate (CrateNum crateNum, std::function<bool (HIR::Item *)> cb); + bool lookup_node_to_hir (CrateNum crate, NodeId id, HirId *ref); + + void insert_location (CrateNum crate, HirId id, Location locus); + Location lookup_location (CrateNum crate, HirId id); + Location lookup_location (HirId id) + { + return lookup_location (get_current_crate (), id); + } + private: Mappings (); @@ -127,8 +143,12 @@ private: std::map<DefId, HIR::Item *> defIdMappings; std::map<CrateNum, std::map<LocalDefId, HIR::Item *> > localDefIdMappings; std::map<CrateNum, std::map<HirId, HIR::Item *> > hirItemMappings; + std::map<CrateNum, std::map<HirId, HIR::Type *> > hirTypeMappings; std::map<CrateNum, std::map<HirId, HIR::Expr *> > hirExprMappings; + // location info + std::map<CrateNum, std::map<NodeId, Location> > locations; + // reverse mappings std::map<CrateNum, std::map<NodeId, HirId> > nodeIdToHirMappings; }; diff --git a/gcc/rust/util/rust-inference-var.h b/gcc/rust/util/rust-inference-var.h deleted file mode 100644 index 87decd5..0000000 --- a/gcc/rust/util/rust-inference-var.h +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (C) 2020 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#ifndef RUST_HIR_INFERENCE_VAR -#define RUST_HIR_INFERENCE_VAR - -#include "rust-system.h" -#include "rust-hir-full-decls.h" - -namespace Rust { -namespace HIR { - -class GeneralInferenceVariable; -class IntegralInferenceVariable; -class FloatInferenceVariable; -class InferenceVarVisitor -{ -public: - virtual void visit (GeneralInferenceVariable &v) {} - virtual void visit (IntegralInferenceVariable &v) {} - virtual void visit (FloatInferenceVariable &v) {} -}; - -// Base -class InferenceVariable -{ -public: - virtual ~InferenceVariable () {} - - virtual std::string as_string () const = 0; - - HIR::Type *get_type () { return resolved; } - - void set_type (HIR::Type *type) { resolved = type; } - - bool was_resolved () { return resolved != nullptr; } - - virtual void accept_vis (InferenceVarVisitor &vis) = 0; - -protected: - InferenceVariable () : resolved (nullptr) {} - - HIR::Type *resolved; -}; - -class GeneralInferenceVariable : public InferenceVariable -{ -public: - GeneralInferenceVariable () : InferenceVariable () {} - - void accept_vis (InferenceVarVisitor &vis) { vis.visit (*this); }; - - std::string as_string () const override - { - if (resolved) - return resolved->as_string (); - - return "[G::?T]"; - } -}; - -class IntegralInferenceVariable : public InferenceVariable -{ -public: - IntegralInferenceVariable () : InferenceVariable () {} - - void accept_vis (InferenceVarVisitor &vis) { vis.visit (*this); }; - - std::string as_string () const override - { - if (resolved) - return resolved->as_string (); - - return "[I::?T]"; - } -}; - -class FloatInferenceVariable : public InferenceVariable -{ -public: - FloatInferenceVariable () : InferenceVariable () {} - - void accept_vis (InferenceVarVisitor &vis) { vis.visit (*this); }; - - std::string as_string () const override - { - if (resolved) - return resolved->as_string (); - - return "[F::?T]"; - } -}; - -} // namespace HIR -} // namespace Rust - -#endif // RUST_HIR_INFERENCE_VAR |