We just had an assertion here for this case where we expect a trait.
This changes the assertion into error handling producing the correct
error code with fixit suggestion like rustc.
Fixes #2499
gcc/rust/ChangeLog:
* typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_path_to_trait):
use error handling instead of assertion
* typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): reuse trait reference
* typecheck/rust-hir-type-check-item.h: update prototype
gcc/testsuite/ChangeLog:
* rust/compile/nr2/exclude: nr2 cant handle this
* rust/compile/issue-2499.rs: New test.
Signed-off-by: Philip Herron <herron.philip@googlemail.com>
return false;
}
- if (auto hid = mappings.lookup_node_to_hir (ref))
+ auto hid = mappings.lookup_node_to_hir (ref);
+ if (!hid)
{
- tl::optional<HIR::Item *> resolved_item
- = mappings.lookup_hir_item (hid.value ());
- rust_assert (resolved_item.has_value ());
- rust_assert (resolved_item.value ()->get_item_kind ()
- == HIR::Item::ItemKind::Trait);
- *resolved = static_cast<HIR::Trait *> (*resolved_item);
+ rust_error_at (path.get_locus (), "Failed to resolve path to hir-id");
+ return false;
+ }
- return true;
+ auto resolved_item = mappings.lookup_hir_item (hid.value ());
+ rust_assert (resolved_item.has_value ());
+ if (resolved_item.value ()->get_item_kind () != HIR::Item::ItemKind::Trait)
+ {
+ rich_location r (line_table, path.get_locus ());
+ r.add_fixit_replace ("not a trait");
+ rust_error_at (r, ErrorCode::E0404, "Expected a trait found %qs",
+ path.as_simple_path ().as_string ().c_str ());
+ return false;
}
- rust_error_at (path.get_locus (), "Failed to resolve path to hir-id");
- return false;
+
+ *resolved = static_cast<HIR::Trait *> (*resolved_item);
+ return true;
}
TraitReference *
{
auto binder_pin = context->push_clean_lifetime_resolver (true);
+ TraitReference *trait_reference = &TraitReference::error_node ();
+ if (impl_block.has_trait_ref ())
+ {
+ std::unique_ptr<HIR::TypePath> &ref = impl_block.get_trait_ref ();
+ trait_reference = TraitResolver::Resolve (*ref);
+ if (trait_reference->is_error ())
+ return;
+ }
+
bool failed_flag = false;
auto result = resolve_impl_block_substitutions (impl_block, failed_flag);
if (failed_flag)
}
// validate the impl items
- validate_trait_impl_block (impl_block, self, substitutions);
+ validate_trait_impl_block (trait_reference, impl_block, self, substitutions);
}
TyTy::BaseType *
void
TypeCheckItem::validate_trait_impl_block (
- HIR::ImplBlock &impl_block, TyTy::BaseType *self,
+ TraitReference *trait_reference, HIR::ImplBlock &impl_block,
+ TyTy::BaseType *self,
std::vector<TyTy::SubstitutionParamMapping> &substitutions)
{
auto specified_bound = TyTy::TypeBoundPredicate::error ();
- TraitReference *trait_reference = &TraitReference::error_node ();
if (impl_block.has_trait_ref ())
{
std::unique_ptr<HIR::TypePath> &ref = impl_block.get_trait_ref ();
- trait_reference = TraitResolver::Resolve (*ref);
- rust_assert (!trait_reference->is_error ());
+ if (trait_reference->is_error ())
+ return;
// we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
// for example
bool &failure_flag);
void validate_trait_impl_block (
- HIR::ImplBlock &impl_block, TyTy::BaseType *self,
+ TraitReference *trait_reference, HIR::ImplBlock &impl_block,
+ TyTy::BaseType *self,
std::vector<TyTy::SubstitutionParamMapping> &substitutions);
TyTy::BaseType *resolve_impl_item (HIR::ImplBlock &impl_block,
--- /dev/null
+#[lang = "sized"]
+pub trait Sized {}
+
+struct Foo;
+struct Bar;
+
+impl Foo for Bar {}
+// { dg-error "Expected a trait found .Foo. .E0404." "" { target *-*-* } .-1 }
+
+fn baz<T: Foo>(t: T) {}
+// { dg-error "Expected a trait found .Foo. .E0404." "" { target *-*-* } .-1 }
issue-3139-3.rs
issue-3036.rs
issue-2951.rs
-issue-2203.rs
\ No newline at end of file
+issue-2203.rs
+issue-2499.rs
\ No newline at end of file