From 367487fe88dca78cffad5138673d5259f7f7ba6b Mon Sep 17 00:00:00 2001 From: robojumper Date: Thu, 28 May 2020 21:42:22 +0200 Subject: Support raw_ref_op's raw reference operator --- crates/ra_hir_ty/src/infer/expr.rs | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'crates/ra_hir_ty/src/infer') diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index b28724f0e..54bab3476 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -17,8 +17,8 @@ use crate::{ autoderef, method_resolution, op, traits::InEnvironment, utils::{generics, variant_data, Generics}, - ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, - Ty, TypeCtor, Uncertain, + ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, + TraitRef, Ty, TypeCtor, Uncertain, }; use super::{ @@ -350,19 +350,28 @@ impl<'a> InferenceContext<'a> { // FIXME check the cast... cast_ty } - Expr::Ref { expr, mutability } => { - let expectation = - if let Some((exp_inner, exp_mutability)) = &expected.ty.as_reference() { - if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { - // FIXME: throw type error - expected mut reference but found shared ref, - // which cannot be coerced - } - Expectation::rvalue_hint(Ty::clone(exp_inner)) - } else { - Expectation::none() - }; + Expr::Ref { expr, rawness, mutability } => { + let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = + &expected.ty.as_reference_or_ptr() + { + if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { + // FIXME: throw type error - expected mut reference but found shared ref, + // which cannot be coerced + } + if *exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr { + // FIXME: throw type error - expected reference but found ptr, + // which cannot be coerced + } + Expectation::rvalue_hint(Ty::clone(exp_inner)) + } else { + Expectation::none() + }; let inner_ty = self.infer_expr_inner(*expr, &expectation); - Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) + let ty = match rawness { + Rawness::RawPtr => TypeCtor::RawPtr(*mutability), + Rawness::Ref => TypeCtor::Ref(*mutability), + }; + Ty::apply_one(ty, inner_ty) } Expr::Box { expr } => { let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); -- cgit v1.2.3 From 7d0586cb15000193941f93d4b5281e56ef751edd Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 29 May 2020 16:03:06 +0200 Subject: Use first match branch in case of type mismatch, not last The comment says this was intentional, but I do agree with #4304 that it makes more sense the other way around (for if/else as well). Fixes #4304. --- crates/ra_hir_ty/src/infer/coerce.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'crates/ra_hir_ty/src/infer') diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 2ee9adb16..32c7c57cd 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs @@ -45,9 +45,7 @@ impl<'a> InferenceContext<'a> { self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) } else { mark::hit!(coerce_merge_fail_fallback); - // For incompatible types, we use the latter one as result - // to be better recovery for `if` without `else`. - ty2.clone() + ty1.clone() } } } -- cgit v1.2.3 From 6f67a46a6a264ac7985a10ee19fbf9bbaef924bc Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 29 May 2020 17:35:57 +0200 Subject: Fix match ergonomics in closure parameters Fixes #4476. --- crates/ra_hir_ty/src/infer/expr.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'crates/ra_hir_ty/src/infer') diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 54bab3476..78084cb57 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -140,13 +140,13 @@ impl<'a> InferenceContext<'a> { let mut sig_tys = Vec::new(); - for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { - let expected = if let Some(type_ref) = arg_type { + // collect explicitly written argument types + for arg_type in arg_types.iter() { + let arg_ty = if let Some(type_ref) = arg_type { self.make_ty(type_ref) } else { - Ty::Unknown + self.table.new_type_var() }; - let arg_ty = self.infer_pat(*arg_pat, &expected, BindingMode::default()); sig_tys.push(arg_ty); } @@ -158,7 +158,7 @@ impl<'a> InferenceContext<'a> { sig_tys.push(ret_ty.clone()); let sig_ty = Ty::apply( TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, - Substs(sig_tys.into()), + Substs(sig_tys.clone().into()), ); let closure_ty = Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); @@ -168,6 +168,12 @@ impl<'a> InferenceContext<'a> { // infer the body. self.coerce(&closure_ty, &expected.ty); + // Now go through the argument patterns + for (arg_pat, arg_ty) in args.iter().zip(sig_tys) { + let resolved = self.resolve_ty_as_possible(arg_ty); + self.infer_pat(*arg_pat, &resolved, BindingMode::default()); + } + let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); -- cgit v1.2.3 From 1cd78a3355ea70d3070cabb00c80a5d195499752 Mon Sep 17 00:00:00 2001 From: robojumper Date: Sun, 31 May 2020 10:59:40 +0200 Subject: correctly infer labelled breaks --- crates/ra_hir_ty/src/infer/expr.rs | 45 ++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 16 deletions(-) (limited to 'crates/ra_hir_ty/src/infer') diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 78084cb57..4a98e2deb 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -22,8 +22,8 @@ use crate::{ }; use super::{ - BindingMode, BreakableContext, Diverges, Expectation, InferenceContext, InferenceDiagnostic, - TypeMismatch, + find_breakable, BindingMode, BreakableContext, Diverges, Expectation, InferenceContext, + InferenceDiagnostic, TypeMismatch, }; impl<'a> InferenceContext<'a> { @@ -86,16 +86,20 @@ impl<'a> InferenceContext<'a> { self.coerce_merge_branch(&then_ty, &else_ty) } - Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), + Expr::Block { statements, tail, .. } => { + // FIXME: Breakable block inference + self.infer_block(statements, *tail, expected) + } Expr::TryBlock { body } => { let _inner = self.infer_expr(*body, expected); // FIXME should be std::result::Result<{inner}, _> Ty::Unknown } - Expr::Loop { body } => { + Expr::Loop { body, label } => { self.breakables.push(BreakableContext { may_break: false, break_ty: self.table.new_type_var(), + label: label.clone(), }); self.infer_expr(*body, &Expectation::has_type(Ty::unit())); @@ -110,8 +114,12 @@ impl<'a> InferenceContext<'a> { Ty::simple(TypeCtor::Never) } } - Expr::While { condition, body } => { - self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown }); + Expr::While { condition, body, label } => { + self.breakables.push(BreakableContext { + may_break: false, + break_ty: Ty::Unknown, + label: label.clone(), + }); // while let is desugared to a match loop, so this is always simple while self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); self.infer_expr(*body, &Expectation::has_type(Ty::unit())); @@ -120,10 +128,14 @@ impl<'a> InferenceContext<'a> { self.diverges = Diverges::Maybe; Ty::unit() } - Expr::For { iterable, body, pat } => { + Expr::For { iterable, body, pat, label } => { let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); - self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown }); + self.breakables.push(BreakableContext { + may_break: false, + break_ty: Ty::Unknown, + label: label.clone(), + }); let pat_ty = self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); @@ -236,23 +248,24 @@ impl<'a> InferenceContext<'a> { let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) } - Expr::Continue => Ty::simple(TypeCtor::Never), - Expr::Break { expr } => { + Expr::Continue { .. } => Ty::simple(TypeCtor::Never), + Expr::Break { expr, label } => { let val_ty = if let Some(expr) = expr { self.infer_expr(*expr, &Expectation::none()) } else { Ty::unit() }; - let last_ty = if let Some(ctxt) = self.breakables.last() { - ctxt.break_ty.clone() - } else { - Ty::Unknown - }; + let last_ty = + if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { + ctxt.break_ty.clone() + } else { + Ty::Unknown + }; let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); - if let Some(ctxt) = self.breakables.last_mut() { + if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { ctxt.break_ty = merged_type; ctxt.may_break = true; } else { -- cgit v1.2.3