LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-inherent-impl-overlap.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 98.3 % 58 57
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 5 5
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #ifndef RUST_HIR_INHERENT_IMPL_ITEM_OVERLAP_H
      20              : #define RUST_HIR_INHERENT_IMPL_ITEM_OVERLAP_H
      21              : 
      22              : #include "rust-hir-type-check-base.h"
      23              : #include "rust-type-util.h"
      24              : 
      25              : namespace Rust {
      26              : namespace Resolver {
      27              : 
      28         8260 : class OverlappingImplItemPass : public TypeCheckBase
      29              : {
      30              : public:
      31         4130 :   static void go ()
      32              :   {
      33         8260 :     OverlappingImplItemPass pass;
      34              : 
      35              :     // generate mappings
      36         4130 :     pass.mappings.iterate_impl_items (
      37         4130 :       [&] (HirId id, HIR::ImplItem *impl_item, HIR::ImplBlock *impl) -> bool {
      38              :         // ignoring trait-impls might need thought later on
      39         8036 :         if (impl->has_trait_ref ())
      40              :           return true;
      41              : 
      42         2716 :         pass.process_impl_item (id, impl_item, impl);
      43         2716 :         return true;
      44              :       });
      45              : 
      46         4130 :     pass.scan ();
      47         4130 :   }
      48              : 
      49         2716 :   void process_impl_item (HirId id, HIR::ImplItem *impl_item,
      50              :                           HIR::ImplBlock *impl)
      51              :   {
      52              :     // lets make a mapping of impl-item Self type to (impl-item,name):
      53              :     // {
      54              :     //   impl-type -> [ (item, name), ... ]
      55              :     // }
      56              : 
      57         2716 :     HirId impl_type_id = impl->get_type ().get_mappings ().get_hirid ();
      58         2716 :     TyTy::BaseType *impl_type = nullptr;
      59         2716 :     bool ok = query_type (impl_type_id, &impl_type);
      60         2716 :     if (!ok)
      61            0 :       return;
      62              : 
      63         2716 :     std::string impl_item_name = impl_item->get_impl_item_name ();
      64         2716 :     std::pair<HIR::ImplItem *, std::string> elem (impl_item, impl_item_name);
      65         2716 :     impl_mappings[impl_type].insert (std::move (elem));
      66         2716 :   }
      67              : 
      68         4130 :   void scan ()
      69              :   {
      70              :     // we can now brute force the map looking for can_eq on each of the
      71              :     // impl_items_types to look for possible colliding impl blocks;
      72         5054 :     for (auto it = impl_mappings.begin (); it != impl_mappings.end (); it++)
      73              :       {
      74          924 :         TyTy::BaseType *query = it->first;
      75              : 
      76         4194 :         for (auto iy = impl_mappings.begin (); iy != impl_mappings.end (); iy++)
      77              :           {
      78         3270 :             TyTy::BaseType *candidate = iy->first;
      79          924 :             if (query == candidate)
      80          924 :               continue;
      81              : 
      82         2346 :             if (!types_compatable (TyTy::TyWithLocation (query),
      83         2346 :                                    TyTy::TyWithLocation (candidate),
      84              :                                    UNKNOWN_LOCATION, false))
      85         2302 :               continue;
      86              : 
      87              :             // we might be in the case that we have:
      88              :             //
      89              :             // *const T vs *const [T]
      90              :             //
      91              :             // so lets use an equality check when the
      92              :             // candidates are both generic to be sure we dont emit a false
      93              :             // positive
      94              : 
      95           44 :             bool a = query->is_concrete ();
      96           44 :             bool b = candidate->is_concrete ();
      97           44 :             bool both_generic = !a && !b;
      98           44 :             if (both_generic)
      99              :               {
     100           28 :                 if (!query->is_equal (*candidate))
     101           28 :                   continue;
     102              :               }
     103              : 
     104           16 :             possible_collision (it->second, iy->second);
     105              :           }
     106              :       }
     107         4130 :   }
     108              : 
     109           16 :   void possible_collision (
     110              :     std::set<std::pair<HIR::ImplItem *, std::string> > query,
     111              :     std::set<std::pair<HIR::ImplItem *, std::string> > candidate)
     112              :   {
     113           32 :     for (auto &q : query)
     114              :       {
     115           16 :         HIR::ImplItem *query_impl_item = q.first;
     116           16 :         std::string query_impl_item_name = q.second;
     117              : 
     118           32 :         for (auto &c : candidate)
     119              :           {
     120           16 :             HIR::ImplItem *candidate_impl_item = c.first;
     121           16 :             std::string candidate_impl_item_name = c.second;
     122              : 
     123           16 :             if (query_impl_item_name.compare (candidate_impl_item_name) == 0)
     124            2 :               collision_detected (query_impl_item, candidate_impl_item,
     125              :                                   candidate_impl_item_name);
     126           16 :           }
     127           16 :       }
     128           16 :   }
     129              : 
     130            2 :   void collision_detected (HIR::ImplItem *query, HIR::ImplItem *dup,
     131              :                            const std::string &name)
     132              :   {
     133            2 :     rich_location r (line_table, dup->get_locus ());
     134            2 :     std::string msg = "duplicate definitions for " + name;
     135            2 :     r.add_fixit_replace (query->get_locus (), msg.c_str ());
     136            2 :     r.add_range (query->get_locus ());
     137            2 :     rust_error_at (r, ErrorCode::E0592, "duplicate definitions with name %qs",
     138              :                    name.c_str ());
     139            2 :   }
     140              : 
     141              : private:
     142         4130 :   OverlappingImplItemPass () : TypeCheckBase () {}
     143              : 
     144              :   std::map<TyTy::BaseType *,
     145              :            std::set<std::pair<HIR::ImplItem *, std::string> > >
     146              :     impl_mappings;
     147              : };
     148              : 
     149              : } // namespace Resolver
     150              : } // namespace Rust
     151              : 
     152              : #endif // RUST_HIR_INHERENT_IMPL_ITEM_OVERLAP_H
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.