summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2019-04-24 12:21:20 +0800
committerJohn Hodge <tpg@ucc.asn.au>2019-04-24 12:21:20 +0800
commit444f4915d27837ac3d6515f081519f4fe2e07eed (patch)
treed8e481fb43b805c86b8cd423104b65f6add00f8b /src
parent17ca4b82d5c8af93e95e04a549153656e494cdae (diff)
downloadmrust-444f4915d27837ac3d6515f081519f4fe2e07eed.tar.gz
Typecheck Expressions - Add an unsize target instead of hard equality in match ergonoics
Diffstat (limited to 'src')
-rw-r--r--src/hir/hir_ops.cpp8
-rw-r--r--src/hir_typeck/expr_cs.cpp172
-rw-r--r--src/hir_typeck/helpers.cpp2
3 files changed, 113 insertions, 69 deletions
diff --git a/src/hir/hir_ops.cpp b/src/hir/hir_ops.cpp
index 4b35a0f0..b09dbdf7 100644
--- a/src/hir/hir_ops.cpp
+++ b/src/hir/hir_ops.cpp
@@ -215,9 +215,9 @@ namespace {
namespace {
bool is_unbounded_infer(const ::HIR::TypeRef& type) {
- TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Infer, e,
- return e.ty_class == ::HIR::InferClass::None || e.ty_class == ::HIR::InferClass::Diverge;
- )
+ if( const auto* e = type.m_data.opt_Infer() ) {
+ return e->ty_class == ::HIR::InferClass::None || e->ty_class == ::HIR::InferClass::Diverge;
+ }
else {
return false;
}
@@ -229,6 +229,8 @@ bool ::HIR::TraitImpl::matches_type(const ::HIR::TypeRef& type, ::HIR::t_cb_reso
// NOTE: Don't return any impls when the type is an unbouned ivar. Wouldn't be able to pick anything anyway
// TODO: For `Unbound`, it could be valid, if the target is a generic.
// - Pure infer could also be useful (for knowing if there's any other potential impls)
+
+ // TODO: Allow unbounded types iff there's some non-unbounded parameters?
if( is_unbounded_infer(type) || TU_TEST1(type.m_data, Path, .binding.is_Unbound()) ) {
return false;
}
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 7f910415..762adf5a 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -2324,6 +2324,9 @@ namespace {
do {
const auto& ty = this->context.get_type(*current_ty);
DEBUG("(Index): (: " << ty << ")[: " << trait_pp.m_types[0] << "]");
+ if( ty.m_data.is_Infer() ) {
+ return ;
+ }
::HIR::TypeRef possible_index_type;
::HIR::TypeRef possible_res_type;
@@ -3951,6 +3954,7 @@ void Context::handle_pattern(const Span& sp, ::HIR::Pattern& pat, const ::HIR::T
::HIR::PatternBinding::Type m_outer_mode;
mutable ::std::vector<::HIR::TypeRef> m_temp_ivars;
+ mutable ::HIR::TypeRef m_possible_type;
MatchErgonomicsRevisit(Span sp, ::HIR::TypeRef outer, ::HIR::Pattern& pat, ::HIR::PatternBinding::Type binding_mode=::HIR::PatternBinding::Type::Move):
sp(mv$(sp)), m_outer_ty(mv$(outer)),
@@ -3983,6 +3987,78 @@ void Context::handle_pattern(const Span& sp, ::HIR::Pattern& pat, const ::HIR::T
}
return true;
}
+ const ::HIR::TypeRef& get_possible_type(Context& context, ::HIR::Pattern& pattern) const
+ {
+ if( m_possible_type == ::HIR::TypeRef() )
+ {
+ ::HIR::TypeRef possible_type;
+ // Get a potential type from the pattern, and set as a possibility.
+ // - Note, this is only if no derefs were applied
+ TU_MATCH_HDR( (pattern.m_data), { )
+ TU_ARM(pattern.m_data, Any, pe) {
+ // No type information.
+ }
+ TU_ARM(pattern.m_data, Value, pe) {
+ // TODO: Get type info
+ }
+ TU_ARM(pattern.m_data, Range, pe) {
+ // TODO: Get type info (same as Value)
+ }
+ TU_ARM(pattern.m_data, Box, pe) {
+ // TODO: Get type info (Box<_>)
+ }
+ TU_ARM(pattern.m_data, Ref, pe) {
+ BUG(sp, "Match ergonomics - & pattern");
+ }
+ TU_ARM(pattern.m_data, Tuple, e) {
+ // Get type info `(T, U, ...)`
+ if( m_temp_ivars.size() != e.sub_patterns.size() ) {
+ for(size_t i = 0; i < e.sub_patterns.size(); i ++)
+ m_temp_ivars.push_back( context.m_ivars.new_ivar_tr() );
+ }
+ decltype(m_temp_ivars) tuple;
+ for(const auto& ty : m_temp_ivars)
+ tuple.push_back(ty.clone());
+ possible_type = ::HIR::TypeRef( ::std::move(tuple) );
+ }
+ TU_ARM(pattern.m_data, SplitTuple, pe) {
+ // Can't get type information, tuple size is unkown
+ }
+ TU_ARM(pattern.m_data, Slice, e) {
+ // Can be either a [T] or [T; n]. Can't provide a hint
+ }
+ TU_ARM(pattern.m_data, SplitSlice, pe) {
+ // Can be either a [T] or [T; n]. Can't provide a hint
+ }
+ TU_ARM(pattern.m_data, StructValue, e) {
+ context.add_ivars_params( e.path.m_params );
+ possible_type = ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding));
+ }
+ TU_ARM(pattern.m_data, StructTuple, e) {
+ context.add_ivars_params( e.path.m_params );
+ possible_type = ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding));
+ }
+ TU_ARM(pattern.m_data, Struct, e) {
+ context.add_ivars_params( e.path.m_params );
+ possible_type = ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding));
+ }
+ TU_ARM(pattern.m_data, EnumValue, e) {
+ context.add_ivars_params( e.path.m_params );
+ possible_type = ::HIR::TypeRef::new_path(get_parent_path(e.path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr));
+ }
+ TU_ARM(pattern.m_data, EnumTuple, e) {
+ context.add_ivars_params( e.path.m_params );
+ possible_type = ::HIR::TypeRef::new_path(get_parent_path(e.path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr));
+ }
+ TU_ARM(pattern.m_data, EnumStruct, e) {
+ context.add_ivars_params( e.path.m_params );
+ possible_type = ::HIR::TypeRef::new_path(get_parent_path(e.path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr));
+ }
+ }
+ m_possible_type = ::std::move(possible_type);
+ }
+ return m_possible_type;
+ }
bool revisit_inner_real(Context& context, ::HIR::Pattern& pattern, const ::HIR::TypeRef& type, ::HIR::PatternBinding::Type binding_mode, bool is_fallback) const
{
TRACE_FUNCTION_F(pattern << " : " << type);
@@ -4046,76 +4122,30 @@ void Context::handle_pattern(const Span& sp, ::HIR::Pattern& pat, const ::HIR::T
}
}
- if( n_deref == 0 && is_fallback )
+ // If there's no dereferences done, then
+ if( n_deref == 0 )
{
- ::HIR::TypeRef possible_type;
- // Get a potential type from the pattern, and set as a possibility.
- // - Note, this is only if no derefs were applied
- TU_MATCH_HDR( (pattern.m_data), { )
- TU_ARM(pattern.m_data, Any, pe) {
- // No type information.
- }
- TU_ARM(pattern.m_data, Value, pe) {
- // TODO: Get type info
- }
- TU_ARM(pattern.m_data, Range, pe) {
- // TODO: Get type info (same as Value)
- }
- TU_ARM(pattern.m_data, Box, pe) {
- // TODO: Get type info (Box<_>)
- }
- TU_ARM(pattern.m_data, Ref, pe) {
- BUG(sp, "Match ergonomics - & pattern");
- }
- TU_ARM(pattern.m_data, Tuple, e) {
- // Get type info `(T, U, ...)`
- if( m_temp_ivars.size() != e.sub_patterns.size() ) {
- for(size_t i = 0; i < e.sub_patterns.size(); i ++)
- m_temp_ivars.push_back( context.m_ivars.new_ivar_tr() );
- }
- decltype(m_temp_ivars) tuple;
- for(const auto& ty : m_temp_ivars)
- tuple.push_back(ty.clone());
- possible_type = ::HIR::TypeRef( ::std::move(tuple) );
- }
- TU_ARM(pattern.m_data, SplitTuple, pe) {
- // Can't get type information, tuple size is unkown
- }
- TU_ARM(pattern.m_data, Slice, e) {
- // Can be either a [T] or [T; n]. Can't provide a hint
- }
- TU_ARM(pattern.m_data, SplitSlice, pe) {
- // Can be either a [T] or [T; n]. Can't provide a hint
- }
- TU_ARM(pattern.m_data, StructValue, e) {
- context.add_ivars_params( e.path.m_params );
- possible_type = ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding));
- }
- TU_ARM(pattern.m_data, StructTuple, e) {
- context.add_ivars_params( e.path.m_params );
- possible_type = ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding));
- }
- TU_ARM(pattern.m_data, Struct, e) {
- context.add_ivars_params( e.path.m_params );
- possible_type = ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding));
- }
- TU_ARM(pattern.m_data, EnumValue, e) {
- context.add_ivars_params( e.path.m_params );
- possible_type = ::HIR::TypeRef::new_path(get_parent_path(e.path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr));
+ const ::HIR::TypeRef& possible_type = get_possible_type(context, pattern);
+ if( possible_type != ::HIR::TypeRef() )
+ {
+ if( const auto* te = ty_p->m_data.opt_Infer() )
+ {
+ context.possible_equate_type_unsize_to(te->index, possible_type);
}
- TU_ARM(pattern.m_data, EnumTuple, e) {
- context.add_ivars_params( e.path.m_params );
- possible_type = ::HIR::TypeRef::new_path(get_parent_path(e.path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr));
+ else if( is_fallback )
+ {
+ DEBUG("Fallback equate " << possible_type);
+ context.equate_types(sp, *ty_p, possible_type);
}
- TU_ARM(pattern.m_data, EnumStruct, e) {
- context.add_ivars_params( e.path.m_params );
- possible_type = ::HIR::TypeRef::new_path(get_parent_path(e.path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr));
+ else
+ {
}
- }
- if( possible_type != ::HIR::TypeRef() )
- {
- DEBUG("Possible equate " << possible_type);
- context.equate_types( sp, *ty_p, possible_type );
+
+ //if( is_fallback )
+ //{
+ // DEBUG("Possible equate " << possible_type);
+ // context.equate_types( sp, *ty_p, possible_type );
+ //}
}
}
@@ -6444,6 +6474,16 @@ namespace {
context.equate_types_to_shadow(sp, t);
}
+ // If the impl type is an unbounded ivar, and there's no trait args - don't bother searching
+ if( const auto* e = context.m_ivars.get_type(v.impl_ty).m_data.opt_Infer() )
+ {
+ // TODO: ?
+ if( !e->is_lit() && v.params.m_types.empty() )
+ {
+ return false;
+ }
+ }
+
// Locate applicable trait impl
unsigned int count = 0;
DEBUG("Searching for impl " << v.trait << v.params << " for " << context.m_ivars.fmt_type(v.impl_ty));
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index 5db296ea..f94cdf26 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -2445,6 +2445,8 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
t_cb_trait_impl_r callback
) const
{
+ // TODO: Have a global cache of impls that don't reference either generics or ivars
+
static ::std::map< ::std::string, ::HIR::TypeRef> null_assoc;
TRACE_FUNCTION_F(trait << FMT_CB(ss, if(params_ptr) { ss << *params_ptr; } else { ss << "<?>"; }) << " for " << type);