HIR::TraitBound *b
= static_cast<HIR::TraitBound *> (bound.get ());
- auto predicate = get_predicate_from_bound (b->get_path ());
+ auto predicate = get_predicate_from_bound (
+ b->get_path (),
+ nullptr /*this will setup a PLACEHOLDER for self*/);
if (predicate.is_error ())
return &TraitReference::error_node ();
// infer the arguments on the predicate
std::vector<TyTy::BaseType *> impl_trait_predicate_args;
- for (const auto &arg : impl_predicate.get_substs ())
+
+ for (size_t i = 0; i < impl_predicate.get_substs ().size (); i++)
{
- const TyTy::ParamType *p = arg.get_param_ty ();
- if (p->get_symbol ().compare ("Self") == 0)
+ const auto &arg = impl_predicate.get_substs ().at (i);
+ if (i == 0)
continue;
+ const TyTy::ParamType *p = arg.get_param_ty ();
TyTy::BaseType *r = p->resolve ();
- r = SubstMapperInternal::Resolve (r, infer_arguments);
+ if (!r->is_concrete ())
+ {
+ r = SubstMapperInternal::Resolve (r, infer_arguments);
+ }
impl_trait_predicate_args.push_back (r);
}
// unify the bounds arguments
std::vector<TyTy::BaseType *> hrtb_bound_arguments;
- for (const auto &arg : bound.get_substs ())
+ for (size_t i = 0; i < bound.get_substs ().size (); i++)
{
- const TyTy::ParamType *p = arg.get_param_ty ();
- if (p->get_symbol ().compare ("Self") == 0)
+ const auto &arg = bound.get_substs ().at (i);
+ if (i == 0)
continue;
+ const TyTy::ParamType *p = arg.get_param_ty ();
TyTy::BaseType *r = p->resolve ();
+ if (!r->is_concrete ())
+ {
+ r = SubstMapperInternal::Resolve (r, infer_arguments);
+ }
hrtb_bound_arguments.push_back (r);
}
TraitReference *resolve_trait_path (HIR::TypePath &);
- TyTy::TypeBoundPredicate get_predicate_from_bound (HIR::TypePath &path);
+ TyTy::TypeBoundPredicate
+ get_predicate_from_bound (HIR::TypePath &path, HIR::Type *associated_self);
bool check_for_unconstrained (
const std::vector<TyTy::SubstitutionParamMapping> ¶ms_to_constrain,
args.get_type_args ().push_back (std::unique_ptr<HIR::Type> (implicit_tuple));
// apply the arguments
- predicate.apply_generic_arguments (&args);
+ predicate.apply_generic_arguments (&args, false);
// finally inherit the trait bound
infered->inherit_bounds ({predicate});
// we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
// for example
- specified_bound = get_predicate_from_bound (*ref.get ());
+ specified_bound
+ = get_predicate_from_bound (*ref.get (), impl_block.get_type ().get ());
}
TyTy::BaseType *self = TypeCheckType::Resolve (impl_block.get_type ().get ());
// we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
// for example
- specified_bound = get_predicate_from_bound (*ref.get ());
+ specified_bound
+ = get_predicate_from_bound (*ref.get (), impl_block.get_type ().get ());
}
bool is_trait_impl_block = !trait_reference->is_error ();
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-type.h"
+#include "rust-hir-type-check-item.h"
#include "rust-hir-trait-resolve.h"
#include "rust-substitution-mapper.h"
#include "rust-hir-path-probe.h"
return;
// get the predicate for the bound
- auto specified_bound = get_predicate_from_bound (*trait_path_ref.get ());
+ auto specified_bound
+ = get_predicate_from_bound (*trait_path_ref.get (),
+ qual_path_type.get_type ().get ());
if (specified_bound.is_error ())
return;
bool found_impl_trait
= context->lookup_associated_trait_impl (impl_block_id,
&associated);
- TyTy::BaseType *impl_block_ty = nullptr;
- if (found_impl_trait)
- {
- TyTy::TypeBoundPredicate predicate (*associated->get_trait (),
- seg.get_locus ());
- impl_block_ty
- = associated->setup_associated_types (prev_segment, predicate);
- }
- else
- {
- // get the type of the parent Self
- HirId impl_ty_id = associated_impl_block->get_type ()
- ->get_mappings ()
- .get_hirid ();
-
- bool ok = query_type (impl_ty_id, &impl_block_ty);
- rust_assert (ok);
+ TyTy::BaseType *impl_block_ty
+ = TypeCheckItem::ResolveImplBlockSelf (*associated_impl_block);
- if (impl_block_ty->needs_generic_substitutions ())
- impl_block_ty
- = SubstMapper::InferSubst (impl_block_ty, seg.get_locus ());
- }
+ if (impl_block_ty->needs_generic_substitutions ())
+ impl_block_ty
+ = SubstMapper::InferSubst (impl_block_ty, seg.get_locus ());
prev_segment = unify_site (seg.get_mappings ().get_hirid (),
TyTy::TyWithLocation (prev_segment),
TyTy::TyWithLocation (impl_block_ty),
seg.get_locus ());
+
+ if (found_impl_trait)
+ {
+ // we need to setup with apropriate bounds
+ HIR::TypePath &bound_path
+ = *associated->get_impl_block ()->get_trait_ref ().get ();
+
+ // generate an implicit HIR Type we can apply to the predicate
+ HirId implicit_id = mappings->get_next_hir_id ();
+ context->insert_implicit_type (implicit_id, impl_block_ty);
+
+ Analysis::NodeMapping mappings (expr_mappings.get_crate_num (),
+ expr_mappings.get_nodeid (),
+ implicit_id,
+ expr_mappings.get_local_defid ());
+ HIR::TypePath *implicit_self_bound
+ = new HIR::TypePath (mappings, {},
+ Linemap::predeclared_location (), false);
+
+ TyTy::TypeBoundPredicate predicate
+ = get_predicate_from_bound (bound_path, implicit_self_bound);
+ impl_block_ty
+ = associated->setup_associated_types (prev_segment, predicate);
+ }
}
if (tyseg->needs_generic_substitutions ())
// get the predicate for the bound
auto specified_bound
- = get_predicate_from_bound (*qual_path_type.get_trait ().get ());
+ = get_predicate_from_bound (*qual_path_type.get_trait ().get (),
+ qual_path_type.get_type ().get ());
if (specified_bound.is_error ())
return;
HIR::TypeParamBound &b = *bound.get ();
HIR::TraitBound &trait_bound = static_cast<HIR::TraitBound &> (b);
- TyTy::TypeBoundPredicate predicate
- = get_predicate_from_bound (trait_bound.get_path ());
+ TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
+ trait_bound.get_path (),
+ nullptr /*this will setup a PLACEHOLDER for self*/);
if (!predicate.is_error ()
&& predicate.is_object_safe (true, type.get_locus ()))
if (param.has_type ())
TypeCheckType::Resolve (param.get_type ().get ());
+ HIR::Type *implicit_self_bound = nullptr;
+ if (param.has_type_param_bounds ())
+ {
+ // We need two possible parameter types. One with no Bounds and one with
+ // the bounds. the Self type for the bounds cannot itself contain the
+ // bounds otherwise it will be a trait cycle
+ HirId implicit_id = mappings->get_next_hir_id ();
+ TyTy::ParamType *p
+ = new TyTy::ParamType (param.get_type_representation (),
+ param.get_locus (), implicit_id, param,
+ {} /*empty specified bounds*/);
+ context->insert_implicit_type (implicit_id, p);
+
+ // generate an implicit HIR Type we can apply to the predicate
+ Analysis::NodeMapping mappings (param.get_mappings ().get_crate_num (),
+ param.get_mappings ().get_nodeid (),
+ implicit_id,
+ param.get_mappings ().get_local_defid ());
+ implicit_self_bound
+ = new HIR::TypePath (mappings, {}, Linemap::predeclared_location (),
+ false);
+ }
+
+ // resolve the bounds
std::vector<TyTy::TypeBoundPredicate> specified_bounds;
if (param.has_type_param_bounds ())
{
= static_cast<HIR::TraitBound *> (bound.get ());
TyTy::TypeBoundPredicate predicate
- = get_predicate_from_bound (b->get_path ());
+ = get_predicate_from_bound (b->get_path (),
+ implicit_self_bound);
if (!predicate.is_error ())
specified_bounds.push_back (std::move (predicate));
}
auto &binding_type_path = item.get_bound_type ();
TyTy::BaseType *binding = TypeCheckType::Resolve (binding_type_path.get ());
+ // FIXME double check there might be a trait cycle here see TypeParam handling
+
std::vector<TyTy::TypeBoundPredicate> specified_bounds;
for (auto &bound : item.get_type_param_bounds ())
{
HIR::TraitBound *b = static_cast<HIR::TraitBound *> (bound.get ());
TyTy::TypeBoundPredicate predicate
- = get_predicate_from_bound (b->get_path ());
+ = get_predicate_from_bound (b->get_path (),
+ binding_type_path.get ());
if (!predicate.is_error ())
specified_bounds.push_back (std::move (predicate));
}
}
TyTy::TypeBoundPredicate
-TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path)
+TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path,
+ HIR::Type *associated_self)
{
TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error ();
bool already_resolved
break;
}
+ if (associated_self != nullptr)
+ {
+ std::vector<std::unique_ptr<HIR::Type>> type_args;
+ type_args.push_back (
+ std::unique_ptr<HIR::Type> (associated_self->clone_type ()));
+ for (auto &arg : args.get_type_args ())
+ {
+ type_args.push_back (std::unique_ptr<HIR::Type> (arg->clone_type ()));
+ }
+
+ args = HIR::GenericArgs (args.get_lifetime_args (), std::move (type_args),
+ args.get_binding_args (), args.get_const_args (),
+ args.get_locus ());
+ }
+
// we try to apply generic arguments when they are non empty and or when the
// predicate requires them so that we get the relevant Foo expects x number
// arguments but got zero see test case rust/compile/traits12.rs
if (!args.is_empty () || predicate.requires_generic_args ())
{
// this is applying generic arguments to a trait reference
- predicate.apply_generic_arguments (&args);
+ predicate.apply_generic_arguments (&args, associated_self != nullptr);
}
context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (),
predicate);
+
return predicate;
}
}
void
-TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args)
+TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
+ bool has_associated_self)
{
- // we need to get the substitutions argument mappings but also remember that
- // we have an implicit Self argument which we must be careful to respect
- rust_assert (!used_arguments.is_empty ());
rust_assert (!substitutions.empty ());
+ if (has_associated_self)
+ {
+ used_arguments = SubstitutionArgumentMappings::empty ();
+ }
+ else
+ {
+ // we need to get the substitutions argument mappings but also remember
+ // that we have an implicit Self argument which we must be careful to
+ // respect
+ rust_assert (!used_arguments.is_empty ());
+ }
// now actually perform a substitution
used_arguments = get_mappings_from_generic_args (*generic_args);
return specified_bounds;
}
+TypeBoundPredicate
+TypeBoundsMappings::lookup_predicate (DefId id)
+{
+ for (auto &b : specified_bounds)
+ {
+ if (b.get_id () == id)
+ return b;
+ }
+ return TypeBoundPredicate::error ();
+}
+
size_t
TypeBoundsMappings::num_specified_bounds () const
{
#define RUST_TYTY_BOUNDS_H
#include "rust-location.h"
+#include "rust-mapping-common.h"
namespace Rust {
const std::vector<TypeBoundPredicate> &get_specified_bounds () const;
+ TypeBoundPredicate lookup_predicate (DefId id);
+
size_t num_specified_bounds () const;
std::string raw_bounds_as_string () const;
// https://doc.rust-lang.org/reference/items/traits.html#object-safety
bool is_object_safe (bool emit_error, Location locus) const;
- void apply_generic_arguments (HIR::GenericArgs *generic_args);
+ void apply_generic_arguments (HIR::GenericArgs *generic_args,
+ bool has_associated_self);
bool contains_item (const std::string &search) const;
+// { dg-additional-options "-frust-compile-until=nameresolution" }
pub enum Option<T> {
None,
Some(T),
}
impl<T> A for Foo<usize> {
- // { dg-error "generic item takes at least 1 type arguments but 0 were supplied" "" { target *-*-* } .-1 }
+ // { dg-error "generic item takes at least 2 type arguments but 1 were supplied" "" { target *-*-* } .-1 }
// { dg-error "unconstrained type parameter" "" { target *-*-* } .-2 }
type Output = T;
fn main() {
let a = Foo::test();
- // { dg-error "Failed to resolve expression of function call" "" { target *-*-* } .-1 }
- // { dg-error "failed to type resolve expression" "" { target *-*-* } .-2 }
+ // { dg-error "expected" "" { target *-*-* } .-1 }
+ // { dg-error "Failed to resolve expression of function call" "" { target *-*-* } .-2 }
+ // { dg-error "failed to type resolve expression" "" { target *-*-* } .-3 }
}