From: Philip Herron Date: Sun, 23 Apr 2023 21:41:21 +0000 (+0100) Subject: gccrs: Add mechanism use pattern information to improve type info X-Git-Tag: basepoints/gcc-15~2613 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1b810614f1e4488b6f5c53a6d195fda51fb5a5e7;p=thirdparty%2Fgcc.git gccrs: Add mechanism use pattern information to improve type info When we have an untyped closure we assumed all parameters were inference variables but we can use the pattern type to try and improve the type info so if we have a reference pattern it must be a reference to an inference variables '&_'. This patch adds a new visitor to figure this out for untyped closure parameters. Note this test case does fully type resolve into the gimple: bool test::main::{{closure}} (struct test::main::{{closure}} $closure, struct (& u8) args) { ... } Though the Rustc version does fail type-resolution but we make some assumptions during comparison expressions here that they resolve to a bool this will change when we implement the comparison lang items. Fixes #2142 gcc/rust/ChangeLog: * hir/tree/rust-hir-pattern.h: add missing get_mutability * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): use new ClosureParamInfer on untyped parameters * typecheck/rust-hir-type-check-pattern.cc (ClosureParamInfer::Resolve): interface (ClosureParamInfer::ClosureParamInfer): constructor (ClosureParamInfer::visit): visitors for each pattern * typecheck/rust-hir-type-check-pattern.h (class ClosureParamInfer): new visitor gcc/testsuite/ChangeLog: * rust/compile/issue-2142.rs: New test. Signed-off-by: Philip Herron --- diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h index f6359f94316f..5fa9a1747a86 100644 --- a/gcc/rust/hir/tree/rust-hir-pattern.h +++ b/gcc/rust/hir/tree/rust-hir-pattern.h @@ -462,6 +462,8 @@ public: bool is_mut () const { return mut == Mutability::Mut; } + Mutability get_mutability () const { return mut; } + void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRPatternVisitor &vis) override; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index f82204872c1d..3dafcd219c23 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -1471,25 +1471,20 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr) std::vector parameter_types; for (auto &p : expr.get_params ()) { + TyTy::BaseType *param_tyty = nullptr; if (p.has_type_given ()) { - TyTy::BaseType *param_tyty - = TypeCheckType::Resolve (p.get_type ().get ()); - TyTy::TyVar param_ty (param_tyty->get_ref ()); - parameter_types.push_back (param_ty); - - TypeCheckPattern::Resolve (p.get_pattern ().get (), - param_ty.get_tyty ()); + param_tyty = TypeCheckType::Resolve (p.get_type ().get ()); } else { - TyTy::TyVar param_ty - = TyTy::TyVar::get_implicit_infer_var (p.get_locus ()); - parameter_types.push_back (param_ty); - - TypeCheckPattern::Resolve (p.get_pattern ().get (), - param_ty.get_tyty ()); + param_tyty = ClosureParamInfer::Resolve (p.get_pattern ().get ()); } + + TyTy::TyVar param_ty (param_tyty->get_ref ()); + parameter_types.push_back (param_ty); + + TypeCheckPattern::Resolve (p.get_pattern ().get (), param_ty.get_tyty ()); } // we generate an implicit hirid for the closure args diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index bde707682387..1221bcc62447 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -447,5 +447,116 @@ TypeCheckPattern::visit (HIR::AltPattern &pattern) "type checking alternate patterns not supported"); } +TyTy::BaseType * +ClosureParamInfer::Resolve (HIR::Pattern *pattern) +{ + ClosureParamInfer resolver; + pattern->accept_vis (resolver); + + if (resolver.infered->get_kind () != TyTy::TypeKind::ERROR) + { + resolver.context->insert_implicit_type (resolver.infered); + resolver.mappings->insert_location (resolver.infered->get_ref (), + pattern->get_locus ()); + } + return resolver.infered; +} + +ClosureParamInfer::ClosureParamInfer () + : TypeCheckBase (), infered (new TyTy::ErrorType (0)) +{} + +void +ClosureParamInfer::visit (HIR::WildcardPattern &pattern) +{ + HirId id = pattern.get_pattern_mappings ().get_hirid (); + infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, + TyTy::InferType::TypeHint::Default (), + pattern.get_locus ()); +} + +void +ClosureParamInfer::visit (HIR::IdentifierPattern &pattern) +{ + HirId id = pattern.get_pattern_mappings ().get_hirid (); + infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, + TyTy::InferType::TypeHint::Default (), + pattern.get_locus ()); +} + +void +ClosureParamInfer::visit (HIR::ReferencePattern &pattern) +{ + TyTy::BaseType *element + = ClosureParamInfer::Resolve (pattern.get_referenced_pattern ().get ()); + + HirId id = pattern.get_pattern_mappings ().get_hirid (); + infered = new TyTy::ReferenceType (id, TyTy::TyVar (element->get_ref ()), + pattern.get_mutability ()); +} + +void +ClosureParamInfer::visit (HIR::PathInExpression &pattern) +{ + rust_sorry_at (pattern.get_locus (), + "unable to infer this kind of parameter pattern"); +} + +void +ClosureParamInfer::visit (HIR::StructPattern &pattern) +{ + rust_sorry_at (pattern.get_locus (), + "unable to infer this kind of parameter pattern"); +} + +void +ClosureParamInfer::visit (HIR::TupleStructPattern &pattern) +{ + rust_sorry_at (pattern.get_locus (), + "unable to infer this kind of parameter pattern"); +} + +void +ClosureParamInfer::visit (HIR::TuplePattern &pattern) +{ + rust_sorry_at (pattern.get_locus (), + "unable to infer this kind of parameter pattern"); +} + +void +ClosureParamInfer::visit (HIR::LiteralPattern &pattern) +{ + rust_sorry_at (pattern.get_locus (), + "unable to infer this kind of parameter pattern"); +} + +void +ClosureParamInfer::visit (HIR::RangePattern &pattern) +{ + rust_sorry_at (pattern.get_locus (), + "unable to infer this kind of parameter pattern"); +} + +void +ClosureParamInfer::visit (HIR::QualifiedPathInExpression &pattern) +{ + rust_sorry_at (pattern.get_locus (), + "unable to infer this kind of parameter pattern"); +} + +void +ClosureParamInfer::visit (HIR::SlicePattern &pattern) +{ + rust_sorry_at (pattern.get_locus (), + "unable to infer this kind of parameter pattern"); +} + +void +ClosureParamInfer::visit (HIR::AltPattern &pattern) +{ + rust_sorry_at (pattern.get_locus (), + "unable to infer this kind of parameter pattern"); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.h b/gcc/rust/typecheck/rust-hir-type-check-pattern.h index 93afe693ffd8..4bf371ffa06c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.h +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.h @@ -58,6 +58,30 @@ private: TyTy::BaseType *infered; }; +class ClosureParamInfer : private TypeCheckBase, private HIR::HIRPatternVisitor +{ +public: + static TyTy::BaseType *Resolve (HIR::Pattern *pattern); + + void visit (HIR::PathInExpression &pattern) override; + void visit (HIR::StructPattern &pattern) override; + void visit (HIR::TupleStructPattern &pattern) override; + void visit (HIR::WildcardPattern &pattern) override; + void visit (HIR::TuplePattern &pattern) override; + void visit (HIR::LiteralPattern &pattern) override; + void visit (HIR::RangePattern &pattern) override; + void visit (HIR::IdentifierPattern &pattern) override; + void visit (HIR::QualifiedPathInExpression &pattern) override; + void visit (HIR::ReferencePattern &pattern) override; + void visit (HIR::SlicePattern &pattern) override; + void visit (HIR::AltPattern &pattern) override; + +private: + ClosureParamInfer (); + + TyTy::BaseType *infered; +}; + } // namespace Resolver } // namespace Rust diff --git a/gcc/testsuite/rust/compile/issue-2142.rs b/gcc/testsuite/rust/compile/issue-2142.rs new file mode 100644 index 000000000000..7a8bb2aca502 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2142.rs @@ -0,0 +1,14 @@ +#[lang = "fn_once"] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +fn main() { + let lambda = |&c| c != b'9'; + + let a = b'1'; + lambda(&a); +}