From 72483b1ca912dca78543f5cc2a7e9d1380ef5784 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sun, 8 Aug 2021 22:29:55 +0100 Subject: Improve the error message for bad type bounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We emit one error for all unsatisfied bounds such as: test.rs:26:31: error: bounds not satisfied for Test ‘Bar, Baz’ is not satisfied 21 | fn type_bound_test() -> i32 { | ~ ~ ...... 26 | let a = type_bound_test::(); | ^ --- gcc/rust/typecheck/rust-hir-type-check-type.h | 2 +- gcc/rust/typecheck/rust-tyty-bounds.cc | 6 ++++ gcc/rust/typecheck/rust-tyty.cc | 43 +++++++++++++++++++++++++++ gcc/rust/typecheck/rust-tyty.h | 38 +++++++---------------- 4 files changed, 60 insertions(+), 29 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index ef1510e..fff86be 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -283,7 +283,7 @@ public: TraitReference *trait = resolve_trait_path (b->get_path ()); TyTy::TypeBoundPredicate predicate ( - trait->get_mappings ().get_defid ()); + trait->get_mappings ().get_defid (), b->get_locus ()); specified_bounds.push_back (std::move (predicate)); } diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index 3562e85..008dc19 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -83,5 +83,11 @@ TypeBoundPredicate::get () const return ref; } +std::string +TypeBoundPredicate::get_name () const +{ + return get ()->get_name (); +} + } // namespace TyTy } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 88b6c35..2d165c3 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -62,6 +62,49 @@ BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const return false; } +bool +BaseType::bounds_compatible (const BaseType &other, Location locus) const +{ + std::vector> + unsatisfied_bounds; + for (auto &bound : get_specified_bounds ()) + { + if (!other.satisfies_bound (bound)) + unsatisfied_bounds.push_back (bound); + } + + // lets emit a single error for this + if (unsatisfied_bounds.size () > 0) + { + RichLocation r (locus); + std::string missing_preds; + for (size_t i = 0; i < unsatisfied_bounds.size (); i++) + { + const TypeBoundPredicate &pred = unsatisfied_bounds.at (i); + r.add_range (pred.get_locus ()); + missing_preds += pred.get_name (); + + bool have_next = (i + 1) < unsatisfied_bounds.size (); + if (have_next) + missing_preds += ", "; + } + + rust_error_at (r, "bounds not satisfied for %s %<%s%> is not satisfied", + other.get_name ().c_str (), missing_preds.c_str ()); + } + + return unsatisfied_bounds.size () == 0; +} + +void +BaseType::inherit_bounds (const BaseType &other) +{ + for (auto &bound : other.get_specified_bounds ()) + { + add_bound (bound); + } +} + TyVar::TyVar (HirId ref) : ref (ref) { // ensure this reference is defined within the context diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index f6f9579..c1afa14 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -132,14 +132,21 @@ public: class TypeBoundPredicate { public: - TypeBoundPredicate (DefId reference) : reference (reference) {} + TypeBoundPredicate (DefId reference, Location locus) + : reference (reference), locus (locus) + {} std::string as_string () const; const Resolver::TraitReference *get () const; + Location get_locus () const { return locus; } + + std::string get_name () const; + private: DefId reference; + Location locus; }; class TypeBoundsMappings @@ -241,34 +248,9 @@ public: bool satisfies_bound (const TypeBoundPredicate &predicate) const; - bool bounds_compatible (const BaseType &other, Location locus) const - { - std::vector> - unsatisfied_bounds; - for (auto &bound : get_specified_bounds ()) - { - if (!other.satisfies_bound (bound)) - unsatisfied_bounds.push_back (bound); - } - - if (unsatisfied_bounds.size () > 0) - { - RichLocation r (locus); - rust_error_at (r, "bounds not satisfied for %s", - other.as_string ().c_str ()); - return false; - } - - return unsatisfied_bounds.size () == 0; - } + bool bounds_compatible (const BaseType &other, Location locus) const; - void inherit_bounds (const BaseType &other) - { - for (auto &bound : other.get_specified_bounds ()) - { - add_bound (bound); - } - } + void inherit_bounds (const BaseType &other); virtual bool is_unit () const { return false; } -- cgit v1.1