diff options
Diffstat (limited to 'gcc/rust/typecheck/rust-hir-type-check-type.cc')
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.cc | 603 |
1 files changed, 350 insertions, 253 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 44ebc15..dff54f0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -18,6 +18,8 @@ #include "rust-hir-type-check-type.h" #include "options.h" +#include "optional.h" +#include "rust-hir-map.h" #include "rust-hir-trait-resolve.h" #include "rust-hir-type-check-expr.h" #include "rust-hir-path-probe.h" @@ -26,18 +28,19 @@ #include "rust-mapping-common.h" #include "rust-substitution-mapper.h" #include "rust-type-util.h" +#include "rust-system.h" namespace Rust { namespace Resolver { HIR::GenericArgs -TypeCheckResolveGenericArguments::resolve (HIR::TypePathSegment *segment) +TypeCheckResolveGenericArguments::resolve (HIR::TypePathSegment &segment) { - TypeCheckResolveGenericArguments resolver (segment->get_locus ()); - switch (segment->get_type ()) + TypeCheckResolveGenericArguments resolver (segment.get_locus ()); + switch (segment.get_type ()) { case HIR::TypePathSegment::SegmentType::GENERIC: - resolver.visit (static_cast<HIR::TypePathSegmentGeneric &> (*segment)); + resolver.visit (static_cast<HIR::TypePathSegmentGeneric &> (segment)); break; default: @@ -53,20 +56,20 @@ TypeCheckResolveGenericArguments::visit (HIR::TypePathSegmentGeneric &generic) } TyTy::BaseType * -TypeCheckType::Resolve (HIR::Type *type) +TypeCheckType::Resolve (HIR::Type &type) { // is it already resolved? auto context = TypeCheckContext::get (); TyTy::BaseType *resolved = nullptr; bool already_resolved - = context->lookup_type (type->get_mappings ().get_hirid (), &resolved); + = context->lookup_type (type.get_mappings ().get_hirid (), &resolved); if (already_resolved) return resolved; - TypeCheckType resolver (type->get_mappings ().get_hirid ()); - type->accept_vis (resolver); + TypeCheckType resolver (type.get_mappings ().get_hirid ()); + type.accept_vis (resolver); rust_assert (resolver.translated != nullptr); - resolver.context->insert_type (type->get_mappings (), resolver.translated); + resolver.context->insert_type (type.get_mappings (), resolver.translated); return resolver.translated; } @@ -82,20 +85,20 @@ TypeCheckType::visit (HIR::BareFunctionType &fntype) TyTy::BaseType *return_type; if (fntype.has_return_type ()) { - return_type = TypeCheckType::Resolve (fntype.get_return_type ().get ()); + return_type = TypeCheckType::Resolve (fntype.get_return_type ()); } else { // needs a new implicit ID - HirId ref = mappings->get_next_hir_id (); - return_type = TyTy::TupleType::get_unit_type (ref); + HirId ref = mappings.get_next_hir_id (); + return_type = TyTy::TupleType::get_unit_type (); context->insert_implicit_type (ref, return_type); } std::vector<TyTy::TyVar> params; for (auto ¶m : fntype.get_function_params ()) { - TyTy::BaseType *ptype = TypeCheckType::Resolve (param.get_type ().get ()); + TyTy::BaseType *ptype = TypeCheckType::Resolve (param.get_type ()); params.push_back (TyTy::TyVar (ptype->get_ref ())); } @@ -109,19 +112,14 @@ TypeCheckType::visit (HIR::TupleType &tuple) { if (tuple.is_unit_type ()) { - auto unit_node_id = resolver->get_unit_type_node_id (); - if (!context->lookup_builtin (unit_node_id, &translated)) - { - rust_error_at (tuple.get_locus (), - "failed to lookup builtin unit type"); - } + translated = TyTy::TupleType::get_unit_type (); return; } std::vector<TyTy::TyVar> fields; for (auto &elem : tuple.get_elems ()) { - auto field_ty = TypeCheckType::Resolve (elem.get ()); + auto field_ty = TypeCheckType::Resolve (*elem); fields.push_back (TyTy::TyVar (field_ty->get_ref ())); } @@ -136,11 +134,14 @@ TypeCheckType::visit (HIR::TypePath &path) // this can happen so we need to look up the root then resolve the // remaining segments if possible + bool wasBigSelf = false; size_t offset = 0; - NodeId resolved_node_id = UNKNOWN_NODEID; - TyTy::BaseType *root = resolve_root_path (path, &offset, &resolved_node_id); + TyTy::BaseType *root = resolve_root_path (path, &offset, &wasBigSelf); if (root->get_kind () == TyTy::TypeKind::ERROR) - return; + { + rust_debug_loc (path.get_locus (), "failed to resolve type-path type"); + return; + } TyTy::BaseType *path_type = root->clone (); path_type->set_ref (path.get_mappings ().get_hirid ()); @@ -150,21 +151,25 @@ TypeCheckType::visit (HIR::TypePath &path) if (fully_resolved) { translated = path_type; + rust_debug_loc (path.get_locus (), "root resolved type-path to: [%s]", + translated->debug_str ().c_str ()); return; } translated - = resolve_segments (resolved_node_id, path.get_mappings ().get_hirid (), - path.get_segments (), offset, path_type, - path.get_mappings (), path.get_locus ()); + = resolve_segments (path.get_mappings ().get_hirid (), path.get_segments (), + offset, path_type, path.get_mappings (), + path.get_locus (), wasBigSelf); + + rust_debug_loc (path.get_locus (), "resolved type-path to: [%s]", + translated->debug_str ().c_str ()); } void TypeCheckType::visit (HIR::QualifiedPathInType &path) { HIR::QualifiedPathType qual_path_type = path.get_path_type (); - TyTy::BaseType *root - = TypeCheckType::Resolve (qual_path_type.get_type ().get ()); + TyTy::BaseType *root = TypeCheckType::Resolve (qual_path_type.get_type ()); if (root->get_kind () == TyTy::TypeKind::ERROR) { rust_debug_loc (path.get_locus (), "failed to resolve the root"); @@ -173,39 +178,25 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path) if (!qual_path_type.has_as_clause ()) { - // then this is just a normal path-in-expression - NodeId root_resolved_node_id = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type ( - qual_path_type.get_type ()->get_mappings ().get_nodeid (), - &root_resolved_node_id); - rust_assert (ok); - - translated = resolve_segments (root_resolved_node_id, - path.get_mappings ().get_hirid (), - path.get_segments (), 0, translated, - path.get_mappings (), path.get_locus ()); + translated + = resolve_segments (path.get_mappings ().get_hirid (), + path.get_segments (), 0, translated, + path.get_mappings (), path.get_locus (), false); return; } // Resolve the trait now - std::unique_ptr<HIR::TypePath> &trait_path_ref = qual_path_type.get_trait (); - TraitReference *trait_ref = TraitResolver::Resolve (*trait_path_ref.get ()); + auto &trait_path_ref = qual_path_type.get_trait (); + TraitReference *trait_ref = TraitResolver::Resolve (trait_path_ref); if (trait_ref->is_error ()) return; - // does this type actually implement this type-bound? - if (!TypeBoundsProbe::is_bound_satisfied_for_type (root, trait_ref)) - { - rust_error_at (qual_path_type.get_locus (), - "root does not satisfy specified trait-bound"); - return; - } - // get the predicate for the bound auto specified_bound - = get_predicate_from_bound (*qual_path_type.get_trait ().get (), - qual_path_type.get_type ().get ()); + = get_predicate_from_bound (qual_path_type.get_trait (), + qual_path_type.get_type (), + BoundPolarity::RegularBound, true); if (specified_bound.is_error ()) return; @@ -213,14 +204,23 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path) root->inherit_bounds ({specified_bound}); // lookup the associated item from the specified bound - std::unique_ptr<HIR::TypePathSegment> &item_seg - = path.get_associated_segment (); - HIR::PathIdentSegment item_seg_identifier = item_seg->get_ident_segment (); + HIR::TypePathSegment &item_seg = path.get_associated_segment (); + HIR::PathIdentSegment item_seg_identifier = item_seg.get_ident_segment (); TyTy::TypeBoundPredicateItem item = specified_bound.lookup_associated_item (item_seg_identifier.as_string ()); if (item.is_error ()) { - rust_error_at (item_seg->get_locus (), "unknown associated item"); + std::string item_seg_ident_name, rich_msg; + item_seg_ident_name = qual_path_type.get_trait ().as_string (); + rich_msg = "not found in `" + item_seg_ident_name + "`"; + + rich_location richloc (line_table, item_seg.get_locus ()); + richloc.add_fixit_replace (rich_msg.c_str ()); + + rust_error_at (richloc, ErrorCode::E0576, + "cannot find associated type %qs in trait %qs", + item_seg_identifier.as_string ().c_str (), + item_seg_ident_name.c_str ()); return; } @@ -254,7 +254,6 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path) } } - NodeId root_resolved_node_id = UNKNOWN_NODEID; if (impl_item == nullptr) { // this may be valid as there could be a default trait implementation here @@ -262,41 +261,32 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path) // not because this will have already been validated as part of the trait // impl block translated = item.get_tyty_for_receiver (root); - root_resolved_node_id - = item.get_raw_item ()->get_mappings ().get_nodeid (); } else { HirId impl_item_id = impl_item->get_impl_mappings ().get_hirid (); bool ok = query_type (impl_item_id, &translated); if (!ok) - { - // FIXME - // I think query_type should error if required here anyway - return; - } + return; if (!args.is_error ()) { // apply the args translated = SubstMapperInternal::Resolve (translated, args); } - - root_resolved_node_id = impl_item->get_impl_mappings ().get_nodeid (); } // turbo-fish segment path::<ty> - if (item_seg->get_type () == HIR::TypePathSegment::SegmentType::GENERIC) + if (item_seg.get_type () == HIR::TypePathSegment::SegmentType::GENERIC) { - HIR::TypePathSegmentGeneric &generic_seg - = static_cast<HIR::TypePathSegmentGeneric &> (*item_seg.get ()); + auto &generic_seg = static_cast<HIR::TypePathSegmentGeneric &> (item_seg); // turbo-fish segment path::<ty> if (generic_seg.has_generic_args ()) { if (!translated->has_substitutions_defined ()) { - rust_error_at (item_seg->get_locus (), + rust_error_at (item_seg.get_locus (), "substitutions not supported for %s", translated->as_string ().c_str ()); translated @@ -314,25 +304,21 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path) // continue on as a path-in-expression bool fully_resolved = path.get_segments ().empty (); if (fully_resolved) - { - resolver->insert_resolved_type (path.get_mappings ().get_nodeid (), - root_resolved_node_id); - context->insert_receiver (path.get_mappings ().get_hirid (), root); - return; - } + return; translated - = resolve_segments (root_resolved_node_id, - path.get_mappings ().get_hirid (), path.get_segments (), - 0, translated, path.get_mappings (), path.get_locus ()); + = resolve_segments (path.get_mappings ().get_hirid (), path.get_segments (), + 0, translated, path.get_mappings (), path.get_locus (), + false); } TyTy::BaseType * TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, - NodeId *root_resolved_node_id) + bool *wasBigSelf) { TyTy::BaseType *root_tyty = nullptr; *offset = 0; + for (size_t i = 0; i < path.get_num_segments (); i++) { std::unique_ptr<HIR::TypePathSegment> &seg = path.get_segments ().at (i); @@ -344,19 +330,25 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, // then lookup the reference_node_id NodeId ref_node_id = UNKNOWN_NODEID; - // FIXME: HACK: ARTHUR: Remove this - if (flag_name_resolution_2_0) + if (seg->is_lang_item ()) + ref_node_id = Analysis::Mappings::get ().get_lang_item_node ( + seg->get_lang_item ()); + else { - auto nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - // assign the ref_node_id if we've found something - nr_ctx.lookup (path.get_mappings ().get_nodeid ()) - .map ([&ref_node_id, &path] (NodeId resolved) { - ref_node_id = resolved; - }); + // FIXME: HACK: ARTHUR: Remove this + if (flag_name_resolution_2_0) + { + auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get () + .resolver (); + + // assign the ref_node_id if we've found something + nr_ctx.lookup (ast_node_id) + .map ( + [&ref_node_id] (NodeId resolved) { ref_node_id = resolved; }); + } + else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + resolver->lookup_resolved_type (ast_node_id, &ref_node_id); } - else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - resolver->lookup_resolved_type (ast_node_id, &ref_node_id); // ref_node_id is the NodeId that the segments refers to. if (ref_node_id == UNKNOWN_NODEID) @@ -365,15 +357,25 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, { rust_error_at (seg->get_locus (), "unknown reference for resolved name: %qs", - seg->get_ident_segment ().as_string ().c_str ()); + seg->as_string ().c_str ()); + return new TyTy::ErrorType (path.get_mappings ().get_hirid ()); + } + else if (root_tyty == nullptr) + { + rust_error_at (seg->get_locus (), + "unknown reference for resolved name: %qs", + seg->as_string ().c_str ()); return new TyTy::ErrorType (path.get_mappings ().get_hirid ()); } return root_tyty; } + if (seg->is_ident_only () && seg->as_string () == "Self") + *wasBigSelf = true; + // node back to HIR - HirId ref = UNKNOWN_HIRID; - if (!mappings->lookup_node_to_hir (ref_node_id, &ref)) + tl::optional<HirId> hid = mappings.lookup_node_to_hir (ref_node_id); + if (!hid.has_value ()) { if (is_root) { @@ -389,9 +391,10 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, return root_tyty; } + auto ref = hid.value (); - auto seg_is_module = (nullptr != mappings->lookup_module (ref)); - auto seg_is_crate = mappings->is_local_hirid_crate (ref); + auto seg_is_module = mappings.lookup_module (ref).has_value (); + auto seg_is_crate = mappings.is_local_hirid_crate (ref); if (seg_is_module || seg_is_crate) { // A::B::C::this_is_a_module::D::E::F @@ -414,12 +417,14 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, TyTy::BaseType *lookup = nullptr; if (!query_type (ref, &lookup)) { - if (is_root) + if (is_root || root_tyty == nullptr) { rust_error_at (seg->get_locus (), - "failed to resolve root segment"); + "failed to resolve type path segment: %qs", + seg->as_string ().c_str ()); return new TyTy::ErrorType (path.get_mappings ().get_hirid ()); } + return root_tyty; } @@ -446,13 +451,13 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, // turbo-fish segment path::<ty> if (seg->is_generic_segment ()) { - HIR::TypePathSegmentGeneric *generic_segment - = static_cast<HIR::TypePathSegmentGeneric *> (seg.get ()); + auto &generic_segment + = static_cast<HIR::TypePathSegmentGeneric &> (*seg); auto regions = context->regions_from_generic_args ( - generic_segment->get_generic_args ()); + generic_segment.get_generic_args ()); lookup = SubstMapper::Resolve (lookup, path.get_locus (), - &generic_segment->get_generic_args (), + &generic_segment.get_generic_args (), regions); if (lookup->get_kind () == TyTy::TypeKind::ERROR) return new TyTy::ErrorType (seg->get_mappings ().get_hirid ()); @@ -466,7 +471,6 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, context->regions_from_generic_args (empty)); } - *root_resolved_node_id = ref_node_id; *offset = *offset + 1; root_tyty = lookup; @@ -479,14 +483,58 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, return root_tyty; } +bool +TypeCheckType::resolve_associated_type (const std::string &search, + TypeCheckBlockContextItem &ctx, + TyTy::BaseType **result) +{ + if (ctx.is_trait_block ()) + { + HIR::Trait &trait = ctx.get_trait (); + for (auto &item : trait.get_trait_items ()) + { + if (item->get_item_kind () != HIR::TraitItem::TraitItemKind::TYPE) + continue; + + if (item->trait_identifier () == search) + { + HirId item_id = item->get_mappings ().get_hirid (); + if (query_type (item_id, result)) + return true; + } + } + + // FIXME + // query any parent trait? + + return false; + } + + // look for any segment in here which matches + HIR::ImplBlock &block = ctx.get_impl_block (); + for (auto &item : block.get_impl_items ()) + { + if (item->get_impl_item_type () != HIR::ImplItem::TYPE_ALIAS) + continue; + + if (item->get_impl_item_name () == search) + { + HirId item_id = item->get_impl_mappings ().get_hirid (); + if (query_type (item_id, result)) + return true; + } + } + + return false; +} + TyTy::BaseType * TypeCheckType::resolve_segments ( - NodeId root_resolved_node_id, HirId expr_id, - std::vector<std::unique_ptr<HIR::TypePathSegment>> &segments, size_t offset, - TyTy::BaseType *tyseg, const Analysis::NodeMapping &expr_mappings, - location_t expr_locus) + HirId expr_id, std::vector<std::unique_ptr<HIR::TypePathSegment>> &segments, + size_t offset, TyTy::BaseType *tyseg, + const Analysis::NodeMapping &expr_mappings, location_t expr_locus, + bool tySegIsBigSelf) { - NodeId resolved_node_id = root_resolved_node_id; TyTy::BaseType *prev_segment = tyseg; for (size_t i = offset; i < segments.size (); i++) { @@ -497,76 +545,84 @@ TypeCheckType::resolve_segments ( bool probe_bounds = true; bool probe_impls = !reciever_is_generic; bool ignore_mandatory_trait_items = !reciever_is_generic; + bool first_segment = i == offset; + bool selfResolveOk = false; - // probe the path is done in two parts one where we search impls if no - // candidate is found then we search extensions from traits - auto candidates - = PathProbeType::Probe (prev_segment, seg->get_ident_segment (), - probe_impls, false, - ignore_mandatory_trait_items); - if (candidates.size () == 0) + if (first_segment && tySegIsBigSelf + && context->block_context ().is_in_context () + && context->block_context ().peek ().is_impl_block ()) + { + TypeCheckBlockContextItem ctx = context->block_context ().peek (); + TyTy::BaseType *lookup = nullptr; + selfResolveOk + = resolve_associated_type (seg->as_string (), ctx, &lookup); + if (selfResolveOk) + { + prev_segment = tyseg; + tyseg = lookup; + } + } + if (!selfResolveOk) { - candidates + // probe the path is done in two parts one where we search impls if no + // candidate is found then we search extensions from traits + auto candidates = PathProbeType::Probe (prev_segment, seg->get_ident_segment (), - false, probe_bounds, + probe_impls, false, ignore_mandatory_trait_items); - if (candidates.size () == 0) { - rust_error_at ( - seg->get_locus (), - "failed to resolve path segment using an impl Probe"); + candidates + = PathProbeType::Probe (prev_segment, seg->get_ident_segment (), + false, probe_bounds, + ignore_mandatory_trait_items); + if (candidates.size () == 0) + { + prev_segment->debug (); + rust_error_at ( + seg->get_locus (), + "failed to resolve path segment using an impl Probe"); + return new TyTy::ErrorType (expr_id); + } + } + + if (candidates.size () > 1) + { + ReportMultipleCandidateError::Report (candidates, + seg->get_ident_segment (), + seg->get_locus ()); return new TyTy::ErrorType (expr_id); } - } - if (candidates.size () > 1) - { - ReportMultipleCandidateError::Report (candidates, - seg->get_ident_segment (), - seg->get_locus ()); - return new TyTy::ErrorType (expr_id); - } + auto &candidate = *candidates.begin (); + prev_segment = tyseg; + tyseg = candidate.ty; - auto &candidate = *candidates.begin (); - prev_segment = tyseg; - tyseg = candidate.ty; + if (candidate.is_enum_candidate ()) + { + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyseg); + auto last_variant = adt->get_variants (); + TyTy::VariantDef *variant = last_variant.back (); - if (candidate.is_enum_candidate ()) - { - TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyseg); - auto last_variant = adt->get_variants (); - TyTy::VariantDef *variant = last_variant.back (); - - rich_location richloc (line_table, seg->get_locus ()); - richloc.add_fixit_replace ("not a type"); - - rust_error_at (richloc, ErrorCode::E0573, - "expected type, found variant of %<%s::%s%>", - adt->get_name ().c_str (), - variant->get_identifier ().c_str ()); - return new TyTy::ErrorType (expr_id); - } + rich_location richloc (line_table, seg->get_locus ()); + richloc.add_fixit_replace ("not a type"); - if (candidate.is_impl_candidate ()) - { - resolved_node_id - = candidate.item.impl.impl_item->get_impl_mappings ().get_nodeid (); - } - else - { - resolved_node_id - = candidate.item.trait.item_ref->get_mappings ().get_nodeid (); + rust_error_at (richloc, ErrorCode::E0573, + "expected type, found variant of %<%s::%s%>", + adt->get_name ().c_str (), + variant->get_identifier ().c_str ()); + return new TyTy::ErrorType (expr_id); + } } if (seg->is_generic_segment ()) { - auto *generic_segment - = static_cast<HIR::TypePathSegmentGeneric *> (seg.get ()); + auto &generic_segment + = static_cast<HIR::TypePathSegmentGeneric &> (*seg); std::vector<TyTy::Region> regions; for (auto &lifetime : - generic_segment->get_generic_args ().get_lifetime_args ()) + generic_segment.get_generic_args ().get_lifetime_args ()) { auto region = context->lookup_and_resolve_lifetime (lifetime); if (!region.has_value ()) @@ -579,46 +635,13 @@ TypeCheckType::resolve_segments ( } tyseg = SubstMapper::Resolve (tyseg, expr_locus, - &generic_segment->get_generic_args (), + &generic_segment.get_generic_args (), regions); if (tyseg->get_kind () == TyTy::TypeKind::ERROR) return new TyTy::ErrorType (expr_id); } } - context->insert_receiver (expr_mappings.get_hirid (), prev_segment); - rust_assert (resolved_node_id != UNKNOWN_NODEID); - - // lookup if the name resolver was able to canonically resolve this or not - NodeId path_resolved_id = UNKNOWN_NODEID; - if (resolver->lookup_resolved_name (expr_mappings.get_nodeid (), - &path_resolved_id)) - { - rust_assert (path_resolved_id == resolved_node_id); - } - // check the type scope - else if (resolver->lookup_resolved_type (expr_mappings.get_nodeid (), - &path_resolved_id)) - { - rust_assert (path_resolved_id == resolved_node_id); - } - else - { - // name scope first - if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) - { - resolver->insert_resolved_name (expr_mappings.get_nodeid (), - resolved_node_id); - } - // check the type scope - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node_id)) - { - resolver->insert_resolved_type (expr_mappings.get_nodeid (), - resolved_node_id); - } - } - return tyseg; } @@ -628,6 +651,11 @@ TypeCheckType::visit (HIR::TraitObjectType &type) std::vector<TyTy::TypeBoundPredicate> specified_bounds; for (auto &bound : type.get_type_param_bounds ()) { + // TODO: here we need to check if there are additional bounds that aren't + // auto traits. this is an error. for example, `dyn A + Sized + Sync` is + // okay, because Sized and Sync are both auto traits but `dyn A + Copy + + // Clone` is not okay and should error out. + if (bound->get_bound_type () != HIR::TypeParamBound::BoundType::TRAITBOUND) continue; @@ -643,7 +671,7 @@ TypeCheckType::visit (HIR::TraitObjectType &type) TyTy::TypeBoundPredicate predicate = get_predicate_from_bound ( trait_bound.get_path (), - nullptr /*this will setup a PLACEHOLDER for self*/); + tl::nullopt /*this will setup a PLACEHOLDER for self*/); if (!predicate.is_error () && predicate.is_object_safe (true, type.get_locus ())) @@ -657,35 +685,41 @@ TypeCheckType::visit (HIR::TraitObjectType &type) } void +TypeCheckType::visit (HIR::ParenthesisedType &type) +{ + // I think this really needs to be a tuple.. but will sort that out when we + // fix the parser issue + translated = TypeCheckType::Resolve (type.get_type_in_parens ()); +} + +void TypeCheckType::visit (HIR::ArrayType &type) { - auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr ().get ()); + auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr ()); if (capacity_type->get_kind () == TyTy::TypeKind::ERROR) return; TyTy::BaseType *expected_ty = nullptr; bool ok = context->lookup_builtin ("usize", &expected_ty); rust_assert (ok); - context->insert_type (type.get_size_expr ()->get_mappings (), expected_ty); + context->insert_type (type.get_size_expr ().get_mappings (), expected_ty); - unify_site (type.get_size_expr ()->get_mappings ().get_hirid (), + unify_site (type.get_size_expr ().get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty), TyTy::TyWithLocation (capacity_type, - type.get_size_expr ()->get_locus ()), - type.get_size_expr ()->get_locus ()); + type.get_size_expr ().get_locus ()), + type.get_size_expr ().get_locus ()); - TyTy::BaseType *base - = TypeCheckType::Resolve (type.get_element_type ().get ()); + TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ()); translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (), - type.get_locus (), *type.get_size_expr (), + type.get_locus (), type.get_size_expr (), TyTy::TyVar (base->get_ref ())); } void TypeCheckType::visit (HIR::SliceType &type) { - TyTy::BaseType *base - = TypeCheckType::Resolve (type.get_element_type ().get ()); + TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ()); translated = new TyTy::SliceType (type.get_mappings ().get_hirid (), type.get_locus (), TyTy::TyVar (base->get_ref ())); @@ -693,7 +727,7 @@ TypeCheckType::visit (HIR::SliceType &type) void TypeCheckType::visit (HIR::ReferenceType &type) { - TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ().get ()); + TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ()); rust_assert (type.has_lifetime ()); auto region = context->lookup_and_resolve_lifetime (type.get_lifetime ()); if (!region.has_value ()) @@ -705,12 +739,12 @@ TypeCheckType::visit (HIR::ReferenceType &type) translated = new TyTy::ReferenceType (type.get_mappings ().get_hirid (), TyTy::TyVar (base->get_ref ()), type.get_mut (), region.value ()); -} // namespace Resolver +} void TypeCheckType::visit (HIR::RawPointerType &type) { - TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ().get ()); + TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ()); translated = new TyTy::PointerType (type.get_mappings ().get_hirid (), TyTy::TyVar (base->get_ref ()), type.get_mut ()); @@ -735,28 +769,70 @@ TypeCheckType::visit (HIR::NeverType &type) translated = lookup->clone (); } +void +TypeCheckType::visit (HIR::ImplTraitType &type) +{ + std::vector<TyTy::TypeBoundPredicate> specified_bounds; + for (auto &bound : type.get_type_param_bounds ()) + { + if (bound->get_bound_type () + != HIR::TypeParamBound::BoundType::TRAITBOUND) + continue; + + HIR::TypeParamBound &b = *bound.get (); + HIR::TraitBound &trait_bound = static_cast<HIR::TraitBound &> (b); + + auto binder_pin = context->push_lifetime_binder (); + for (auto &lifetime_param : trait_bound.get_for_lifetimes ()) + { + context->intern_and_insert_lifetime (lifetime_param.get_lifetime ()); + } + + TyTy::TypeBoundPredicate predicate = get_predicate_from_bound ( + trait_bound.get_path (), + tl::nullopt /*this will setup a PLACEHOLDER for self*/); + + if (!predicate.is_error () + && predicate.is_object_safe (true, type.get_locus ())) + specified_bounds.push_back (std::move (predicate)); + } + + translated = new TyTy::OpaqueType (type.get_locus (), + type.get_mappings ().get_hirid (), + specified_bounds); +} + TyTy::ParamType * -TypeResolveGenericParam::Resolve (HIR::GenericParam *param, bool apply_sized) +TypeResolveGenericParam::Resolve (HIR::GenericParam ¶m, + bool resolve_trait_bounds, bool apply_sized) { - TypeResolveGenericParam resolver (apply_sized); - switch (param->get_kind ()) + TypeResolveGenericParam resolver (apply_sized, resolve_trait_bounds); + switch (param.get_kind ()) { case HIR::GenericParam::GenericKind::TYPE: - resolver.visit (static_cast<HIR::TypeParam &> (*param)); + resolver.visit (static_cast<HIR::TypeParam &> (param)); break; case HIR::GenericParam::GenericKind::CONST: - resolver.visit (static_cast<HIR::ConstGenericParam &> (*param)); + resolver.visit (static_cast<HIR::ConstGenericParam &> (param)); break; case HIR::GenericParam::GenericKind::LIFETIME: - resolver.visit (static_cast<HIR::LifetimeParam &> (*param)); + resolver.visit (static_cast<HIR::LifetimeParam &> (param)); break; } return resolver.resolved; } void +TypeResolveGenericParam::ApplyAnyTraitBounds (HIR::TypeParam ¶m, + TyTy::ParamType *pty) +{ + TypeResolveGenericParam resolver (true, true); + resolver.apply_trait_bounds (param, pty); +} + +void TypeResolveGenericParam::visit (HIR::LifetimeParam ¶m) { // nothing to do @@ -772,15 +848,28 @@ void TypeResolveGenericParam::visit (HIR::TypeParam ¶m) { if (param.has_type ()) - TypeCheckType::Resolve (param.get_type ().get ()); + TypeCheckType::Resolve (param.get_type ()); + + resolved + = new TyTy::ParamType (param.get_type_representation ().as_string (), + param.get_locus (), + param.get_mappings ().get_hirid (), param, {}); + + if (resolve_trait_bounds) + apply_trait_bounds (param, resolved); +} - HIR::Type *implicit_self_bound = nullptr; +void +TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam ¶m, + TyTy::ParamType *pty) +{ + std::unique_ptr<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 (); + HirId implicit_id = mappings.get_next_hir_id (); TyTy::ParamType *p = new TyTy::ParamType (param.get_type_representation ().as_string (), param.get_locus (), implicit_id, param, @@ -792,8 +881,8 @@ TypeResolveGenericParam::visit (HIR::TypeParam ¶m) param.get_mappings ().get_nodeid (), implicit_id, param.get_mappings ().get_local_defid ()); - implicit_self_bound - = new HIR::TypePath (mappings, {}, BUILTINS_LOCATION, false); + implicit_self_bound = std::make_unique<HIR::TypePath> ( + HIR::TypePath (mappings, {}, BUILTINS_LOCATION, false)); } std::map<DefId, std::vector<TyTy::TypeBoundPredicate>> predicates; @@ -804,8 +893,6 @@ TypeResolveGenericParam::visit (HIR::TypeParam ¶m) // // We can only do this when we are not resolving the implicit Self for Sized // itself - rust_debug_loc (param.get_locus (), "apply_sized: %s", - apply_sized ? "true" : "false"); if (apply_sized) { TyTy::TypeBoundPredicate sized_predicate @@ -822,13 +909,13 @@ TypeResolveGenericParam::visit (HIR::TypeParam ¶m) switch (bound->get_bound_type ()) { case HIR::TypeParamBound::BoundType::TRAITBOUND: { - HIR::TraitBound *b - = static_cast<HIR::TraitBound *> (bound.get ()); + HIR::TraitBound &b = static_cast<HIR::TraitBound &> (*bound); - TyTy::TypeBoundPredicate predicate - = get_predicate_from_bound (b->get_path (), - implicit_self_bound, - b->get_polarity ()); + TyTy::TypeBoundPredicate predicate = get_predicate_from_bound ( + b.get_path (), + tl::optional<std::reference_wrapper<HIR::Type>> ( + std::ref (*implicit_self_bound)), + b.get_polarity ()); if (!predicate.is_error ()) { switch (predicate.get_polarity ()) @@ -841,7 +928,7 @@ TypeResolveGenericParam::visit (HIR::TypeParam ¶m) else { // emit error message - rich_location r (line_table, b->get_locus ()); + rich_location r (line_table, b.get_locus ()); r.add_range (predicate.get ()->get_locus ()); rust_error_at ( r, "antibound for %s is not applied here", @@ -880,10 +967,8 @@ TypeResolveGenericParam::visit (HIR::TypeParam ¶m) } } - resolved = new TyTy::ParamType (param.get_type_representation ().as_string (), - param.get_locus (), - param.get_mappings ().get_hirid (), param, - specified_bounds); + // inherit them + pty->inherit_bounds (specified_bounds); } void @@ -939,7 +1024,7 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item) } auto &binding_type_path = item.get_bound_type (); - TyTy::BaseType *binding = TypeCheckType::Resolve (binding_type_path.get ()); + TyTy::BaseType *binding = TypeCheckType::Resolve (binding_type_path); // FIXME double check there might be a trait cycle here see TypeParam handling @@ -952,8 +1037,7 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item) auto *b = static_cast<HIR::TraitBound *> (bound.get ()); TyTy::TypeBoundPredicate predicate - = get_predicate_from_bound (b->get_path (), - binding_type_path.get ()); + = get_predicate_from_bound (b->get_path (), binding_type_path); if (!predicate.is_error ()) specified_bounds.push_back (std::move (predicate)); } @@ -983,41 +1067,54 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item) // When we apply these bounds we must lookup which type this binding // resolves to, as this is the type which will be used during resolution // of the block. - NodeId ast_node_id = binding_type_path->get_mappings ().get_nodeid (); + NodeId ast_node_id = binding_type_path.get_mappings ().get_nodeid (); // then lookup the reference_node_id NodeId ref_node_id = UNKNOWN_NODEID; - if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id)) + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + if (auto id = nr_ctx.lookup (ast_node_id)) + ref_node_id = *id; + } + else + { + NodeId id = UNKNOWN_NODEID; + + if (resolver->lookup_resolved_type (ast_node_id, &id)) + ref_node_id = id; + } + + if (ref_node_id == UNKNOWN_NODEID) { // FIXME rust_error_at (UNDEF_LOCATION, "Failed to lookup type reference for node: %s", - binding_type_path->as_string ().c_str ()); + binding_type_path.as_string ().c_str ()); return; } // node back to HIR - HirId ref; - if (!mappings->lookup_node_to_hir (ref_node_id, &ref)) + if (auto hid = mappings.lookup_node_to_hir (ref_node_id)) { - // FIXME - rust_error_at (UNDEF_LOCATION, "where-clause reverse lookup failure"); - return; - } + // the base reference for this name _must_ have a type set + TyTy::BaseType *lookup; + if (!context->lookup_type (*hid, &lookup)) + { + rust_error_at (mappings.lookup_location (*hid), + "Failed to resolve where-clause binding type: %s", + binding_type_path.as_string ().c_str ()); + return; + } - // the base reference for this name _must_ have a type set - TyTy::BaseType *lookup; - if (!context->lookup_type (ref, &lookup)) - { - rust_error_at (mappings->lookup_location (ref), - "Failed to resolve where-clause binding type: %s", - binding_type_path->as_string ().c_str ()); + // FIXME + // rust_assert (binding->is_equal (*lookup)); + lookup->inherit_bounds (specified_bounds); return; } - - // FIXME - // rust_assert (binding->is_equal (*lookup)); - lookup->inherit_bounds (specified_bounds); + rust_error_at (UNDEF_LOCATION, "where-clause reverse lookup failure"); } } // namespace Resolver |