From 56f503b88a240f1d77c8d6564656bc22269b4842 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 22 Aug 2022 12:43:53 +0100 Subject: Qualified paths can have an optional as clause Qualified paths can look like ::bla with an associated impl block for dynamic trait objects. If we implement similar fine grained visitors that we use in the HIR this will help solve issues like this where we have missing visitors. Fixes #1249 --- gcc/rust/resolve/rust-ast-resolve-path.cc | 3 +- gcc/rust/resolve/rust-ast-resolve-type.cc | 21 +++++++++++++ gcc/rust/resolve/rust-ast-resolve-type.h | 4 +++ gcc/rust/typecheck/rust-hir-type-check-path.cc | 6 ---- gcc/testsuite/rust/execute/torture/issue-1249.rs | 39 ++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/rust/execute/torture/issue-1249.rs (limited to 'gcc') diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc index 27f32aa..b139c6a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-path.cc +++ b/gcc/rust/resolve/rust-ast-resolve-path.cc @@ -242,8 +242,9 @@ void ResolvePath::resolve_path (AST::QualifiedPathInExpression *expr) { AST::QualifiedPathType &root_segment = expr->get_qualified_path_type (); - ResolveType::go (&root_segment.get_as_type_path ()); ResolveType::go (root_segment.get_type ().get ()); + if (root_segment.has_as_clause ()) + ResolveType::go (&root_segment.get_as_type_path ()); for (auto &segment : expr->get_segments ()) { diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc index a8931ce..6b08613 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ b/gcc/rust/resolve/rust-ast-resolve-type.cc @@ -477,6 +477,27 @@ ResolveTypeToCanonicalPath::visit (AST::SliceType &type) } } +void +ResolveTypeToCanonicalPath::visit (AST::TraitObjectTypeOneBound &type) +{ + CanonicalPath path = CanonicalPath::create_empty (); + bool ok + = ResolveTypeToCanonicalPath::go (&type.get_trait_bound ().get_type_path (), + path); + if (ok) + { + std::string slice_path = ""; + result = CanonicalPath::new_seg (type.get_node_id (), slice_path); + } +} + +void +ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &type) +{ + // FIXME is this actually allowed? dyn A+B + gcc_unreachable (); +} + ResolveTypeToCanonicalPath::ResolveTypeToCanonicalPath () : ResolverBase (), result (CanonicalPath::create_empty ()) {} diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index b57b513..5a71268 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -242,6 +242,10 @@ public: void visit (AST::SliceType &type) override; + void visit (AST::TraitObjectTypeOneBound &type) override; + + void visit (AST::TraitObjectType &type) override; + private: ResolveTypeToCanonicalPath (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index fd0ca3e..84f3b6e 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -34,13 +34,7 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr) if (!qual_path_type.has_as_clause ()) { - // then this is just a normal path-in-expression NodeId root_resolved_node_id = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type ( - qual_path_type.get_type ()->get_mappings ().get_nodeid (), - &root_resolved_node_id); - rust_assert (ok); - resolve_segments (root_resolved_node_id, expr.get_segments (), 0, root, expr.get_mappings (), expr.get_locus ()); return; diff --git a/gcc/testsuite/rust/execute/torture/issue-1249.rs b/gcc/testsuite/rust/execute/torture/issue-1249.rs new file mode 100644 index 0000000..072204e --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-1249.rs @@ -0,0 +1,39 @@ +// { dg-options "-w" } +// { dg-output "1\n2\n" } + +extern "C" { + fn printf(s: *const i8, ...); +} + +trait T { + fn foo(&self); +} + +impl dyn T { + fn bar(&self) { + unsafe { + let a = "1\n\0"; + let b = a as *const str; + let c = b as *const i8; + printf(c); + } + self.foo() + } +} + +struct S; +impl T for S { + fn foo(&self) { + unsafe { + let a = "2\n\0"; + let b = a as *const str; + let c = b as *const i8; + printf(c); + } + } +} + +pub fn main() -> i32 { + ::bar(&S); + 0 +} -- cgit v1.1