diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-item.h | 6 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-implitem.h | 10 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 31 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.h | 105 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/traits10.rs | 5 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/trait11.rs | 41 |
6 files changed, 195 insertions, 3 deletions
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 4fdd764..21f0781 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -1387,6 +1387,8 @@ public: return generic_params; } + WhereClause &get_where_clause () { return where_clause; } + protected: Struct (Analysis::NodeMapping mappings, Identifier struct_name, std::vector<std::unique_ptr<GenericParam>> generic_params, @@ -1994,6 +1996,8 @@ public: } } + WhereClause &get_where_clause () { return where_clause; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2704,6 +2708,8 @@ public: return trait_ref; } + WhereClause &get_where_clause () { return where_clause; } + protected: ImplBlock *clone_item_impl () const override { return new ImplBlock (*this); } }; diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index 501ce3f..062d60b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -150,6 +150,11 @@ public: = TypeCheckType::Resolve (alias.get_type_aliased ().get ()); context->insert_type (alias.get_mappings (), actual_type); + + for (auto &where_clause_item : alias.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } } void visit (HIR::ConstantItem &constant) override @@ -191,6 +196,11 @@ public: } } + for (auto &where_clause_item : function.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + TyTy::BaseType *ret_type = nullptr; if (!function.has_function_return_type ()) ret_type = new TyTy::TupleType (function.get_mappings ().get_hirid ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index a85fe66..a32d4a4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -46,6 +46,11 @@ public: = TypeCheckType::Resolve (alias.get_type_aliased ().get ()); context->insert_type (alias.get_mappings (), actual_type); + + for (auto &where_clause_item : alias.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } } void visit (HIR::TupleStruct &struct_decl) override @@ -76,6 +81,11 @@ public: } } + for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + std::vector<TyTy::StructFieldType *> fields; size_t idx = 0; @@ -136,6 +146,11 @@ public: } } + for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + std::vector<TyTy::StructFieldType *> fields; for (auto &field : struct_decl.get_fields ()) @@ -188,6 +203,11 @@ public: } } + for (auto &where_clause_item : union_decl.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + std::vector<TyTy::StructFieldType *> variants; union_decl.iterate ([&] (HIR::StructField &variant) mutable -> bool { TyTy::BaseType *variant_type @@ -259,6 +279,11 @@ public: } } + for (auto &where_clause_item : function.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + TyTy::BaseType *ret_type = nullptr; if (!function.has_function_return_type ()) ret_type = new TyTy::TupleType (function.get_mappings ().get_hirid ()); @@ -296,6 +321,7 @@ public: TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST, std::move (params), ret_type, std::move (substitutions)); + context->insert_type (function.get_mappings (), fnType); } @@ -327,6 +353,11 @@ public: } } + for (auto &where_clause_item : impl_block.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + auto self = TypeCheckType::Resolve (impl_block.get_type ().get (), &substitutions); if (self == nullptr || self->get_kind () == TyTy::TypeKind::ERROR) diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index b56b5a2..c2b6d7c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -277,6 +277,111 @@ private: TyTy::ParamType *resolved; }; +class ResolveWhereClauseItem : public TypeCheckBase +{ + using Rust::Resolver::TypeCheckBase::visit; + +public: + static void Resolve (HIR::WhereClauseItem &item) + { + ResolveWhereClauseItem resolver; + item.accept_vis (resolver); + } + + void visit (HIR::LifetimeWhereClauseItem &) override {} + + void visit (HIR::TypeBoundWhereClauseItem &item) override + { + auto &binding_type_path = item.get_bound_type (); + TyTy::BaseType *binding = TypeCheckType::Resolve (binding_type_path.get ()); + + std::vector<TyTy::TypeBoundPredicate> specified_bounds; + for (auto &bound : item.get_type_param_bounds ()) + { + switch (bound->get_bound_type ()) + { + case HIR::TypeParamBound::BoundType::TRAITBOUND: { + HIR::TraitBound *b + = static_cast<HIR::TraitBound *> (bound.get ()); + + auto &type_path = b->get_path (); + TraitReference *trait = resolve_trait_path (type_path); + TyTy::TypeBoundPredicate predicate ( + trait->get_mappings ().get_defid (), b->get_locus ()); + + auto &final_seg = type_path.get_final_segment (); + if (final_seg->is_generic_segment ()) + { + auto final_generic_seg + = static_cast<HIR::TypePathSegmentGeneric *> ( + final_seg.get ()); + if (final_generic_seg->has_generic_args ()) + { + HIR::GenericArgs &generic_args + = final_generic_seg->get_generic_args (); + + // this is applying generic arguments to a trait + // reference + predicate.apply_generic_arguments (&generic_args); + } + } + + specified_bounds.push_back (std::move (predicate)); + } + break; + + default: + break; + } + } + binding->inherit_bounds (specified_bounds); + + // When we apply these bounds we must lookup which type this binding + // resolves to, as this is the type which will be used during resolution of + // the block. + NodeId ast_node_id = binding_type_path->get_mappings ().get_nodeid (); + + // then lookup the reference_node_id + NodeId ref_node_id = UNKNOWN_NODEID; + if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id)) + { + // FIXME + rust_error_at (Location (), + "Failed to lookup type reference for node: %s", + binding_type_path->as_string ().c_str ()); + return; + } + + // node back to HIR + HirId ref; + if (!mappings->lookup_node_to_hir ( + binding_type_path->get_mappings ().get_crate_num (), ref_node_id, + &ref)) + { + // FIXME + rust_error_at (Location (), "where-clause reverse lookup failure"); + return; + } + + // the base reference for this name _must_ have a type set + TyTy::BaseType *lookup; + if (!context->lookup_type (ref, &lookup)) + { + rust_error_at (mappings->lookup_location (ref), + "Failed to resolve where-clause binding type: %s", + binding_type_path->as_string ().c_str ()); + return; + } + + // FIXME + // rust_assert (binding->is_equal (*lookup)); + lookup->inherit_bounds (specified_bounds); + } + +private: + ResolveWhereClauseItem () : TypeCheckBase () {} +}; + } // namespace Resolver } // namespace Rust diff --git a/gcc/testsuite/rust/compile/torture/traits10.rs b/gcc/testsuite/rust/compile/torture/traits10.rs index 3e47b1b..a492ec3 100644 --- a/gcc/testsuite/rust/compile/torture/traits10.rs +++ b/gcc/testsuite/rust/compile/torture/traits10.rs @@ -1,6 +1,5 @@ -trait Foo -where - Self: Sized, +trait Foo // where +// Self: Sized, { fn get(self) -> i32; // { dg-warning "unused name" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/execute/torture/trait11.rs b/gcc/testsuite/rust/execute/torture/trait11.rs new file mode 100644 index 0000000..53a8a8e --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/trait11.rs @@ -0,0 +1,41 @@ +/* { dg-output "3\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +trait FnLike<A, R> { + fn call(&self, arg: A) -> R; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .arg." "" { target *-*-* } .-2 } +} + +struct S; +impl<'a, T> FnLike<&'a T, &'a T> for S { + fn call(&self, arg: &'a T) -> &'a T { + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name" "" { target *-*-* } .-2 } + arg + } +} + +fn indirect<F>(f: F) +where + F: for<'a> FnLike<&'a isize, &'a isize>, +{ + let x = 3; + let y = f.call(&x); + + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, *y); + } +} + +fn main() -> i32 { + indirect(S); + + 0 +} |