Skip to content

Commit 237564f

Browse files
philbertyCohenArthur
authored andcommitted
gccrs: remove horrible hack in solving complex generics on impl blocks
We hit an assertion with range based iterators here. This code was used to solve complex generics such as: struct Foo<X,Y>(X,Y); impl<T> Foo<T, i32> { fn test<Y>(self, a: Y) { } } The impl item will have the signiture of: fn test<T,Y> (Foo<T, i32> self, a:Y) So in the case where we have: let a = Foo(123f32, 456); a.test<bool>(true); We need to solve the generic argument T from the impl block by infering the arguments there and applying them so that when we apply the generic argument bool we dont end up in the case of missing number of generics. Addresses Rust-GCC#1895 gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): remove hack Signed-off-by: Philip Herron <[email protected]>
1 parent ce40be7 commit 237564f

File tree

1 file changed

+42
-105
lines changed

1 file changed

+42
-105
lines changed

gcc/rust/typecheck/rust-hir-type-check-expr.cc

Lines changed: 42 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "rust-hir-type-check-pattern.h"
2626
#include "rust-hir-type-check-expr.h"
2727
#include "rust-hir-type-check-stmt.h"
28+
#include "rust-hir-type-check-item.h"
2829
#include "rust-type-util.h"
2930

3031
namespace Rust {
@@ -1122,58 +1123,31 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
11221123
}
11231124

11241125
fn->prepare_higher_ranked_bounds ();
1125-
auto root = receiver_tyty->get_root ();
1126-
if (root->get_kind () == TyTy::TypeKind::ADT)
1126+
rust_debug_loc (expr.get_locus (), "resolved method call to: {%u} {%s}",
1127+
candidate.candidate.ty->get_ref (),
1128+
candidate.candidate.ty->debug_str ().c_str ());
1129+
1130+
if (resolved_candidate.is_impl_candidate ())
11271131
{
1128-
const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (root);
1129-
if (adt->has_substitutions () && fn->needs_substitution ())
1132+
auto infer_arguments = TyTy::SubstitutionArgumentMappings::error ();
1133+
HIR::ImplBlock &impl = *resolved_candidate.item.impl.parent;
1134+
TyTy::BaseType *impl_self_infer
1135+
= TypeCheckItem::ResolveImplBlockSelfWithInference (impl,
1136+
expr.get_locus (),
1137+
&infer_arguments);
1138+
if (impl_self_infer->get_kind () == TyTy::TypeKind::ERROR)
11301139
{
1131-
// consider the case where we have:
1132-
//
1133-
// struct Foo<X,Y>(X,Y);
1134-
//
1135-
// impl<T> Foo<T, i32> {
1136-
// fn test<X>(self, a:X) -> (T,X) { (self.0, a) }
1137-
// }
1138-
//
1139-
// In this case we end up with an fn type of:
1140-
//
1141-
// fn <T,X> test(self:Foo<T,i32>, a:X) -> (T,X)
1142-
//
1143-
// This means the instance or self we are calling this method for
1144-
// will be substituted such that we can get the inherited type
1145-
// arguments but then need to use the turbo fish if available or
1146-
// infer the remaining arguments. Luckily rust does not allow for
1147-
// default types GenericParams on impl blocks since these must
1148-
// always be at the end of the list
1149-
1150-
auto s = fn->get_self_type ()->get_root ();
1151-
rust_assert (s->can_eq (adt, false));
1152-
rust_assert (s->get_kind () == TyTy::TypeKind::ADT);
1153-
const TyTy::ADTType *self_adt
1154-
= static_cast<const TyTy::ADTType *> (s);
1155-
1156-
// we need to grab the Self substitutions as the inherit type
1157-
// parameters for this
1158-
if (self_adt->needs_substitution ())
1159-
{
1160-
rust_assert (adt->was_substituted ());
1161-
1162-
TyTy::SubstitutionArgumentMappings used_args_in_prev_segment
1163-
= GetUsedSubstArgs::From (adt);
1164-
1165-
TyTy::SubstitutionArgumentMappings inherit_type_args
1166-
= self_adt->solve_mappings_from_receiver_for_self (
1167-
used_args_in_prev_segment);
1168-
1169-
// there may or may not be inherited type arguments
1170-
if (!inherit_type_args.is_error ())
1171-
{
1172-
// need to apply the inherited type arguments to the
1173-
// function
1174-
lookup = fn->handle_substitions (inherit_type_args);
1175-
}
1176-
}
1140+
rich_location r (line_table, expr.get_locus ());
1141+
r.add_range (impl.get_type ()->get_locus ());
1142+
rust_error_at (
1143+
r, "failed to resolve impl type for method call resolution");
1144+
return;
1145+
}
1146+
1147+
if (!infer_arguments.is_empty ())
1148+
{
1149+
lookup = SubstMapperInternal::Resolve (lookup, infer_arguments);
1150+
lookup->debug ();
11771151
}
11781152
}
11791153

@@ -1687,6 +1661,24 @@ TypeCheckExpr::resolve_operator_overload (
16871661
rust_debug ("is_impl_item_candidate: %s",
16881662
resolved_candidate.is_impl_candidate () ? "true" : "false");
16891663

1664+
if (resolved_candidate.is_impl_candidate ())
1665+
{
1666+
auto infer_arguments = TyTy::SubstitutionArgumentMappings::error ();
1667+
HIR::ImplBlock &impl = *resolved_candidate.item.impl.parent;
1668+
TyTy::BaseType *impl_self_infer
1669+
= TypeCheckItem::ResolveImplBlockSelfWithInference (impl,
1670+
expr.get_locus (),
1671+
&infer_arguments);
1672+
if (impl_self_infer->get_kind () == TyTy::TypeKind::ERROR)
1673+
{
1674+
return false;
1675+
}
1676+
if (!infer_arguments.is_empty ())
1677+
{
1678+
lookup = SubstMapperInternal::Resolve (lookup, infer_arguments);
1679+
}
1680+
}
1681+
16901682
// in the case where we resolve to a trait bound we have to be careful we are
16911683
// able to do so there is a case where we are currently resolving the deref
16921684
// operator overload function which is generic and this might resolve to the
@@ -1735,61 +1727,6 @@ TypeCheckExpr::resolve_operator_overload (
17351727
candidate.candidate.ty->get_ref (),
17361728
candidate.candidate.ty->debug_str ().c_str ());
17371729

1738-
auto root = lhs->get_root ();
1739-
if (root->get_kind () == TyTy::TypeKind::ADT)
1740-
{
1741-
const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (root);
1742-
if (adt->has_substitutions () && fn->needs_substitution ())
1743-
{
1744-
// consider the case where we have:
1745-
//
1746-
// struct Foo<X,Y>(X,Y);
1747-
//
1748-
// impl<T> Foo<T, i32> {
1749-
// fn test<X>(self, a:X) -> (T,X) { (self.0, a) }
1750-
// }
1751-
//
1752-
// In this case we end up with an fn type of:
1753-
//
1754-
// fn <T,X> test(self:Foo<T,i32>, a:X) -> (T,X)
1755-
//
1756-
// This means the instance or self we are calling this method for
1757-
// will be substituted such that we can get the inherited type
1758-
// arguments but then need to use the turbo fish if available or
1759-
// infer the remaining arguments. Luckily rust does not allow for
1760-
// default types GenericParams on impl blocks since these must
1761-
// always be at the end of the list
1762-
1763-
auto s = fn->get_self_type ()->get_root ();
1764-
rust_assert (s->can_eq (adt, false));
1765-
rust_assert (s->get_kind () == TyTy::TypeKind::ADT);
1766-
const TyTy::ADTType *self_adt
1767-
= static_cast<const TyTy::ADTType *> (s);
1768-
1769-
// we need to grab the Self substitutions as the inherit type
1770-
// parameters for this
1771-
if (self_adt->needs_substitution ())
1772-
{
1773-
rust_assert (adt->was_substituted ());
1774-
1775-
TyTy::SubstitutionArgumentMappings used_args_in_prev_segment
1776-
= GetUsedSubstArgs::From (adt);
1777-
1778-
TyTy::SubstitutionArgumentMappings inherit_type_args
1779-
= self_adt->solve_mappings_from_receiver_for_self (
1780-
used_args_in_prev_segment);
1781-
1782-
// there may or may not be inherited type arguments
1783-
if (!inherit_type_args.is_error ())
1784-
{
1785-
// need to apply the inherited type arguments to the
1786-
// function
1787-
lookup = fn->handle_substitions (inherit_type_args);
1788-
}
1789-
}
1790-
}
1791-
}
1792-
17931730
// handle generics
17941731
if (lookup->needs_generic_substitutions ())
17951732
lookup = SubstMapper::InferSubst (lookup, expr.get_locus ());

0 commit comments

Comments
 (0)