diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-04-17 18:34:43 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-04-19 16:29:18 +0100 |
commit | b3dfc9f1f929443eac055291119d13615d375267 (patch) | |
tree | 1d21ccf65a1f4b7837ff41028e0757ed46c5920f /gcc | |
parent | 498758a1c238a539b364ac2c632742a9b64ab4a5 (diff) | |
download | gcc-b3dfc9f1f929443eac055291119d13615d375267.zip gcc-b3dfc9f1f929443eac055291119d13615d375267.tar.gz gcc-b3dfc9f1f929443eac055291119d13615d375267.tar.bz2 |
Fix crash on empty parameters to generic data type
When no parameters are passed to generic data types we cannot properly
infer the usage of the generic block.
This brings in a canonicalized check for `rustc --explain E0107`
Fixes #379
Diffstat (limited to 'gcc')
6 files changed, 71 insertions, 54 deletions
diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index d6f9fc0..262a04a 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -165,11 +165,11 @@ public: GenericArgs &operator= (GenericArgs &&other) = default; // Creates an empty GenericArgs (no arguments) - static GenericArgs create_empty () + static GenericArgs create_empty (Location locus = Location ()) { return GenericArgs (std::vector<Lifetime> (), std::vector<std::unique_ptr<Type> > (), - std::vector<GenericArgsBinding> ()); + std::vector<GenericArgsBinding> (), locus); } bool is_empty () const diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 356faa6..8b23920 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -214,10 +214,7 @@ public: auto self = TypeCheckType::Resolve (impl_block.get_type ().get (), &substitutions); if (self == nullptr || self->get_kind () == TyTy::TypeKind::ERROR) - { - rust_error_at (impl_block.get_locus (), "failed to resolve impl type"); - return; - } + return; for (auto &impl_item : impl_block.get_impl_items ()) TypeCheckTopLevelImplItem::Resolve (impl_item.get (), self, diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 6556947..5c21d5a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -72,7 +72,7 @@ class TypeCheckResolveGenericArguments : public TypeCheckBase public: static HIR::GenericArgs resolve (HIR::TypePathSegment *segment) { - TypeCheckResolveGenericArguments resolver; + TypeCheckResolveGenericArguments resolver (segment->get_locus ()); segment->accept_vis (resolver); return resolver.args; }; @@ -83,8 +83,8 @@ public: } private: - TypeCheckResolveGenericArguments () - : TypeCheckBase (), args (HIR::GenericArgs::create_empty ()) + TypeCheckResolveGenericArguments (Location locus) + : TypeCheckBase (), args (HIR::GenericArgs::create_empty (locus)) {} HIR::GenericArgs args; @@ -165,57 +165,57 @@ public: return; } - // reverse lookup the hir node from ast node id HirId hir_lookup; - if (context->lookup_type_by_node_id (ref, &hir_lookup)) + if (!context->lookup_type_by_node_id (ref, &hir_lookup)) { - // we got an HIR node - if (context->lookup_type (hir_lookup, &translated)) - { - translated = translated->clone (); - auto ref = path.get_mappings ().get_hirid (); - translated->set_ref (ref); - - HIR::TypePathSegment *final_seg = path.get_final_segment (); - HIR::GenericArgs args - = TypeCheckResolveGenericArguments::resolve (final_seg); - - bool path_declared_generic_arguments = !args.is_empty (); - if (path_declared_generic_arguments) - { - if (translated->has_subsititions_defined ()) - { - translated - = SubstMapper::Resolve (translated, path.get_locus (), - &args); - if (translated->get_kind () != TyTy::TypeKind::ERROR - && mappings != nullptr) - { - check_for_unconstrained (args.get_type_args ()); - } - } - else - { - rust_error_at ( - path.get_locus (), - "TypePath %s declares generic argument's but " - "the type %s does not have any", - path.as_string ().c_str (), - translated->as_string ().c_str ()); - } - } - else if (translated->has_subsititions_defined ()) - { - translated - = SubstMapper::InferSubst (translated, path.get_locus ()); - } + rust_error_at (path.get_locus (), "failed to lookup HIR node"); + return; + } + + TyTy::BaseType *lookup = nullptr; + if (!context->lookup_type (hir_lookup, &lookup)) + { + rust_error_at (path.get_locus (), "failed to lookup HIR TyTy"); + return; + } + + TyTy::BaseType *path_type = lookup->clone (); + path_type->set_ref (path.get_mappings ().get_hirid ()); + + HIR::TypePathSegment *final_seg = path.get_final_segment (); + HIR::GenericArgs args + = TypeCheckResolveGenericArguments::resolve (final_seg); + + bool is_big_self = final_seg->is_ident_only () + && (final_seg->as_string ().compare ("Self") == 0); + if (path_type->needs_generic_substitutions ()) + { + if (is_big_self) + { + translated = path_type; return; } - } - rust_error_at (path.get_locus (), "failed to type-resolve TypePath: %s", - path.as_string ().c_str ()); + translated = SubstMapper::Resolve (path_type, path.get_locus (), &args); + if (translated->get_kind () != TyTy::TypeKind::ERROR + && mappings != nullptr) + { + check_for_unconstrained (args.get_type_args ()); + } + } + else if (!args.is_empty ()) + { + rust_error_at (path.get_locus (), + "TypePath %s declares generic argument's but " + "the type %s does not have any", + path.as_string ().c_str (), + translated->as_string ().c_str ()); + } + else + { + translated = path_type; + } } void visit (HIR::ArrayType &type) override diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index bc20e4b..cd04b0e 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -57,6 +57,9 @@ public: { TyTy::SubstitutionArgumentMappings mappings = type.get_mappings_from_generic_args (*generics); + if (mappings.is_error ()) + return; + concrete = type.handle_substitions (mappings); } @@ -77,6 +80,9 @@ public: { TyTy::SubstitutionArgumentMappings mappings = type.get_mappings_from_generic_args (*generics); + if (mappings.is_error ()) + return; + concrete = type.handle_substitions (mappings); } diff --git a/gcc/testsuite/rust.test/xfail_compile/expected_type_args2.rs b/gcc/testsuite/rust.test/xfail_compile/expected_type_args2.rs new file mode 100644 index 0000000..b92c48f --- /dev/null +++ b/gcc/testsuite/rust.test/xfail_compile/expected_type_args2.rs @@ -0,0 +1,6 @@ +struct Foo<A>(A); + +fn main() { + let a: Foo = Foo::<i32>(123); + // { dg-error "Invalid number of generic arguments to generic type" "" { target { *-*-* } } .-1 } +} diff --git a/gcc/testsuite/rust.test/xfail_compile/expected_type_args3.rs b/gcc/testsuite/rust.test/xfail_compile/expected_type_args3.rs new file mode 100644 index 0000000..4c164ff --- /dev/null +++ b/gcc/testsuite/rust.test/xfail_compile/expected_type_args3.rs @@ -0,0 +1,8 @@ +struct Foo<A>(A); + +impl Foo { + // { dg-error "Invalid number of generic arguments to generic type" "" { target { *-*-* } } .-1 } + fn test() -> i32 { + 123 + } +} |