Switch on TyEmpty
Parse -> ! as FnConverging(!) Add AdjustEmptyToAny coercion to all ! expressions Some fixes
This commit is contained in:
parent
9f9f8567eb
commit
104963c539
11 changed files with 88 additions and 54 deletions
|
@ -379,7 +379,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||||
|
|
||||||
let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
|
let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
|
||||||
let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
|
let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
|
||||||
if fn_ty.fn_ret().diverges() {
|
if fn_ty.fn_ret().diverges(self.tcx) {
|
||||||
self.add_unreachable_node()
|
self.add_unreachable_node()
|
||||||
} else {
|
} else {
|
||||||
ret
|
ret
|
||||||
|
|
|
@ -1112,7 +1112,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||||
|
|
||||||
hir::ExprCall(ref f, ref args) => {
|
hir::ExprCall(ref f, ref args) => {
|
||||||
let diverges = !self.ir.tcx.is_method_call(expr.id) &&
|
let diverges = !self.ir.tcx.is_method_call(expr.id) &&
|
||||||
self.ir.tcx.expr_ty_adjusted(&f).fn_ret().diverges();
|
self.ir.tcx.expr_ty_adjusted(&f).fn_ret().diverges(self.ir.tcx);
|
||||||
let succ = if diverges {
|
let succ = if diverges {
|
||||||
self.s.exit_ln
|
self.s.exit_ln
|
||||||
} else {
|
} else {
|
||||||
|
@ -1125,7 +1125,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||||
hir::ExprMethodCall(_, _, ref args) => {
|
hir::ExprMethodCall(_, _, ref args) => {
|
||||||
let method_call = ty::MethodCall::expr(expr.id);
|
let method_call = ty::MethodCall::expr(expr.id);
|
||||||
let method_ty = self.ir.tcx.tables.borrow().method_map[&method_call].ty;
|
let method_ty = self.ir.tcx.tables.borrow().method_map[&method_call].ty;
|
||||||
let succ = if method_ty.fn_ret().diverges() {
|
let succ = if method_ty.fn_ret().diverges(self.ir.tcx) {
|
||||||
self.s.exit_ln
|
self.s.exit_ln
|
||||||
} else {
|
} else {
|
||||||
succ
|
succ
|
||||||
|
|
|
@ -484,8 +484,11 @@ pub enum FnOutput<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> FnOutput<'tcx> {
|
impl<'tcx> FnOutput<'tcx> {
|
||||||
pub fn diverges(&self) -> bool {
|
pub fn diverges(&self, tcx: TyCtxt) -> bool {
|
||||||
*self == FnDiverging
|
match *self {
|
||||||
|
FnConverging(ref ty) => ty.is_empty(tcx),
|
||||||
|
FnDiverging => true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unwrap(self) -> Ty<'tcx> {
|
pub fn unwrap(self) -> Ty<'tcx> {
|
||||||
|
@ -513,8 +516,8 @@ impl<'tcx> FnOutput<'tcx> {
|
||||||
pub type PolyFnOutput<'tcx> = Binder<FnOutput<'tcx>>;
|
pub type PolyFnOutput<'tcx> = Binder<FnOutput<'tcx>>;
|
||||||
|
|
||||||
impl<'tcx> PolyFnOutput<'tcx> {
|
impl<'tcx> PolyFnOutput<'tcx> {
|
||||||
pub fn diverges(&self) -> bool {
|
pub fn diverges(&self, tcx: TyCtxt) -> bool {
|
||||||
self.0.diverges()
|
self.0.diverges(tcx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -936,11 +939,15 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self, _cx: TyCtxt) -> bool {
|
pub fn is_empty(&self, cx: TyCtxt) -> bool {
|
||||||
// FIXME(#24885): be smarter here
|
// FIXME(#24885): be smarter here
|
||||||
match self.sty {
|
match self.sty {
|
||||||
TyEnum(def, _) | TyStruct(def, _) => def.is_empty(),
|
TyEnum(def, _) | TyStruct(def, _) => def.is_empty(),
|
||||||
_ => false
|
TyEmpty => true,
|
||||||
|
TyTuple(ref tys) => tys.iter().any(|ty| ty.is_empty(cx)),
|
||||||
|
// FIXME (canndrew): this line breaks core::fmt
|
||||||
|
//TyRef(_, ref tm) => tm.ty.is_empty(cx),
|
||||||
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -210,7 +210,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
ExprKind::Call { ty, fun, args } => {
|
ExprKind::Call { ty, fun, args } => {
|
||||||
let diverges = match ty.sty {
|
let diverges = match ty.sty {
|
||||||
ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => {
|
ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => {
|
||||||
f.sig.0.output.diverges()
|
f.sig.0.output.diverges(this.hir.tcx())
|
||||||
}
|
}
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
|
|
|
@ -504,11 +504,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(&None, ty::FnDiverging) => {}
|
(&None, ty::FnDiverging) => {}
|
||||||
(&None, ty::FnConverging(..)) => {
|
(&None, ty::FnConverging(ref ty)) => {
|
||||||
|
if !ty.is_empty(tcx) {
|
||||||
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
|
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check_call_inputs(&self,
|
fn check_call_inputs(&self,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
|
|
@ -171,6 +171,7 @@ impl<'tcx> TypeMap<'tcx> {
|
||||||
unique_type_id.push('{');
|
unique_type_id.push('{');
|
||||||
|
|
||||||
match type_.sty {
|
match type_.sty {
|
||||||
|
ty::TyEmpty |
|
||||||
ty::TyBool |
|
ty::TyBool |
|
||||||
ty::TyChar |
|
ty::TyChar |
|
||||||
ty::TyStr |
|
ty::TyStr |
|
||||||
|
@ -704,6 +705,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
|
|
||||||
let sty = &t.sty;
|
let sty = &t.sty;
|
||||||
let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
|
let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
|
||||||
|
ty::TyEmpty |
|
||||||
ty::TyBool |
|
ty::TyBool |
|
||||||
ty::TyChar |
|
ty::TyChar |
|
||||||
ty::TyInt(_) |
|
ty::TyInt(_) |
|
||||||
|
@ -931,6 +933,7 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
debug!("basic_type_metadata: {:?}", t);
|
debug!("basic_type_metadata: {:?}", t);
|
||||||
|
|
||||||
let (name, encoding) = match t.sty {
|
let (name, encoding) = match t.sty {
|
||||||
|
ty::TyEmpty => ("!", DW_ATE_unsigned),
|
||||||
ty::TyTuple(ref elements) if elements.is_empty() =>
|
ty::TyTuple(ref elements) if elements.is_empty() =>
|
||||||
("()", DW_ATE_unsigned),
|
("()", DW_ATE_unsigned),
|
||||||
ty::TyBool => ("bool", DW_ATE_boolean),
|
ty::TyBool => ("bool", DW_ATE_boolean),
|
||||||
|
|
|
@ -473,7 +473,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
self.write_ty(expr.id, result_ty);
|
self.write_ty_expr(expr.id, result_ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,7 +550,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let scheme = tcx.lookup_item_type(def.def_id());
|
let scheme = tcx.lookup_item_type(def.def_id());
|
||||||
let predicates = tcx.lookup_predicates(def.def_id());
|
let predicates = tcx.lookup_predicates(def.def_id());
|
||||||
let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
|
let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
|
||||||
opt_ty, def, pat.span, pat.id);
|
opt_ty, def, pat.span, pat.id, false);
|
||||||
self.demand_suptype(pat.span, expected, pat_ty);
|
self.demand_suptype(pat.span, expected, pat_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,7 +618,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
};
|
};
|
||||||
let predicates = tcx.lookup_predicates(def.def_id());
|
let predicates = tcx.lookup_predicates(def.def_id());
|
||||||
let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
|
let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
|
||||||
opt_ty, def, pat.span, pat.id);
|
opt_ty, def, pat.span, pat.id, false);
|
||||||
self.demand_eqtype(pat.span, expected, pat_ty);
|
self.demand_eqtype(pat.span, expected, pat_ty);
|
||||||
|
|
||||||
// Type check subpatterns.
|
// Type check subpatterns.
|
||||||
|
|
|
@ -106,7 +106,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
|
||||||
};
|
};
|
||||||
(n_tps, inputs, ty::FnConverging(output))
|
(n_tps, inputs, ty::FnConverging(output))
|
||||||
} else if &name[..] == "abort" || &name[..] == "unreachable" {
|
} else if &name[..] == "abort" || &name[..] == "unreachable" {
|
||||||
(0, Vec::new(), ty::FnDiverging)
|
(0, Vec::new(), ty::FnConverging(tcx.mk_empty()))
|
||||||
} else {
|
} else {
|
||||||
let (n_tps, inputs, output) = match &name[..] {
|
let (n_tps, inputs, output) = match &name[..] {
|
||||||
"breakpoint" => (0, Vec::new(), tcx.mk_nil()),
|
"breakpoint" => (0, Vec::new(), tcx.mk_nil()),
|
||||||
|
|
|
@ -93,7 +93,7 @@ use rustc::traits::{self, Reveal};
|
||||||
use rustc::ty::{GenericPredicates, TypeScheme};
|
use rustc::ty::{GenericPredicates, TypeScheme};
|
||||||
use rustc::ty::{ParamTy, ParameterEnvironment};
|
use rustc::ty::{ParamTy, ParameterEnvironment};
|
||||||
use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
|
use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
|
||||||
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, Visibility};
|
use rustc::ty::{self, ToPolyTraitRef, Ty, TypeVariants, TyCtxt, Visibility};
|
||||||
use rustc::ty::{MethodCall, MethodCallee};
|
use rustc::ty::{MethodCall, MethodCallee};
|
||||||
use rustc::ty::adjustment;
|
use rustc::ty::adjustment;
|
||||||
use rustc::ty::fold::{BottomUpFolder, TypeFoldable};
|
use rustc::ty::fold::{BottomUpFolder, TypeFoldable};
|
||||||
|
@ -1561,6 +1561,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.tables.borrow_mut().node_types.insert(node_id, ty);
|
self.tables.borrow_mut().node_types.insert(node_id, ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn write_ty_expr(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
|
||||||
|
self.write_ty(node_id, ty);
|
||||||
|
if let TypeVariants::TyEmpty = ty.sty {
|
||||||
|
self.write_adjustment(node_id, adjustment::AdjustEmptyToAny(self.next_diverging_ty_var()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
|
pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
|
||||||
if !substs.substs.is_noop() {
|
if !substs.substs.is_noop() {
|
||||||
debug!("write_substs({}, {:?}) in fcx {}",
|
debug!("write_substs({}, {:?}) in fcx {}",
|
||||||
|
@ -1731,6 +1739,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn write_nil(&self, node_id: ast::NodeId) {
|
pub fn write_nil(&self, node_id: ast::NodeId) {
|
||||||
self.write_ty(node_id, self.tcx.mk_nil());
|
self.write_ty(node_id, self.tcx.mk_nil());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_empty(&self, node_id: ast::NodeId) {
|
||||||
|
self.write_ty_expr(node_id, self.tcx.mk_empty());
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_error(&self, node_id: ast::NodeId) {
|
pub fn write_error(&self, node_id: ast::NodeId) {
|
||||||
self.write_ty(node_id, self.tcx.types.err);
|
self.write_ty(node_id, self.tcx.types.err);
|
||||||
}
|
}
|
||||||
|
@ -1788,6 +1801,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> {
|
pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> {
|
||||||
|
if let Some(&adjustment::AdjustEmptyToAny(ref t))
|
||||||
|
= self.tables.borrow().adjustments.get(&ex.id) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
match self.tables.borrow().node_types.get(&ex.id) {
|
match self.tables.borrow().node_types.get(&ex.id) {
|
||||||
Some(&t) => t,
|
Some(&t) => t,
|
||||||
None => {
|
None => {
|
||||||
|
@ -1966,9 +1983,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
for ty in &self.unsolved_variables() {
|
for ty in &self.unsolved_variables() {
|
||||||
let resolved = self.resolve_type_vars_if_possible(ty);
|
let resolved = self.resolve_type_vars_if_possible(ty);
|
||||||
if self.type_var_diverges(resolved) {
|
if self.type_var_diverges(resolved) {
|
||||||
debug!("default_type_parameters: defaulting `{:?}` to `()` because it diverges",
|
debug!("default_type_parameters: defaulting `{:?}` to `!` because it diverges",
|
||||||
resolved);
|
resolved);
|
||||||
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.mk_nil());
|
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.mk_empty());
|
||||||
} else {
|
} else {
|
||||||
match self.type_is_unconstrained_numeric(resolved) {
|
match self.type_is_unconstrained_numeric(resolved) {
|
||||||
UnconstrainedInt => {
|
UnconstrainedInt => {
|
||||||
|
@ -2042,7 +2059,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
for ty in &unsolved_variables {
|
for ty in &unsolved_variables {
|
||||||
let resolved = self.resolve_type_vars_if_possible(ty);
|
let resolved = self.resolve_type_vars_if_possible(ty);
|
||||||
if self.type_var_diverges(resolved) {
|
if self.type_var_diverges(resolved) {
|
||||||
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.mk_nil());
|
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.mk_empty());
|
||||||
} else {
|
} else {
|
||||||
match self.type_is_unconstrained_numeric(resolved) {
|
match self.type_is_unconstrained_numeric(resolved) {
|
||||||
UnconstrainedInt | UnconstrainedFloat => {
|
UnconstrainedInt | UnconstrainedFloat => {
|
||||||
|
@ -2100,7 +2117,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let _ = self.commit_if_ok(|_: &infer::CombinedSnapshot| {
|
let _ = self.commit_if_ok(|_: &infer::CombinedSnapshot| {
|
||||||
for ty in &unbound_tyvars {
|
for ty in &unbound_tyvars {
|
||||||
if self.type_var_diverges(ty) {
|
if self.type_var_diverges(ty) {
|
||||||
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.mk_nil());
|
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.mk_empty());
|
||||||
} else {
|
} else {
|
||||||
match self.type_is_unconstrained_numeric(ty) {
|
match self.type_is_unconstrained_numeric(ty) {
|
||||||
UnconstrainedInt => {
|
UnconstrainedInt => {
|
||||||
|
@ -2196,7 +2213,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// reporting for more then one conflict.
|
// reporting for more then one conflict.
|
||||||
for ty in &unbound_tyvars {
|
for ty in &unbound_tyvars {
|
||||||
if self.type_var_diverges(ty) {
|
if self.type_var_diverges(ty) {
|
||||||
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.mk_nil());
|
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.mk_empty());
|
||||||
} else {
|
} else {
|
||||||
match self.type_is_unconstrained_numeric(ty) {
|
match self.type_is_unconstrained_numeric(ty) {
|
||||||
UnconstrainedInt => {
|
UnconstrainedInt => {
|
||||||
|
@ -2601,7 +2618,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(&arg_ty) = self.tables.borrow().node_types.get(&arg.id) {
|
if let Some(&arg_ty) = self.tables.borrow().node_types.get(&arg.id) {
|
||||||
any_diverges = any_diverges || self.type_var_diverges(arg_ty);
|
any_diverges = any_diverges ||
|
||||||
|
self.type_var_diverges(arg_ty) ||
|
||||||
|
arg_ty.is_empty(self.tcx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if any_diverges && !warned {
|
if any_diverges && !warned {
|
||||||
|
@ -2670,7 +2689,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
fn write_call(&self,
|
fn write_call(&self,
|
||||||
call_expr: &hir::Expr,
|
call_expr: &hir::Expr,
|
||||||
output: ty::FnOutput<'tcx>) {
|
output: ty::FnOutput<'tcx>) {
|
||||||
self.write_ty(call_expr.id, match output {
|
self.write_ty_expr(call_expr.id, match output {
|
||||||
ty::FnConverging(output_ty) => output_ty,
|
ty::FnConverging(output_ty) => output_ty,
|
||||||
ty::FnDiverging => self.next_diverging_ty_var()
|
ty::FnDiverging => self.next_diverging_ty_var()
|
||||||
});
|
});
|
||||||
|
@ -2910,7 +2929,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// the type of the block, because old trans still uses it.
|
// the type of the block, because old trans still uses it.
|
||||||
let adj = self.tables.borrow().adjustments.get(&then.id).cloned();
|
let adj = self.tables.borrow().adjustments.get(&then.id).cloned();
|
||||||
if res.is_ok() && adj.is_some() {
|
if res.is_ok() && adj.is_some() {
|
||||||
self.write_ty(then_blk.id, self.adjust_expr_ty(then, adj.as_ref()));
|
self.write_ty_expr(then_blk.id, self.adjust_expr_ty(then, adj.as_ref()));
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
|
@ -2951,7 +2970,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.write_ty(id, if_ty);
|
self.write_ty_expr(id, if_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check field access expressions
|
// Check field access expressions
|
||||||
|
@ -2972,7 +2991,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let field_ty = self.field_ty(expr.span, field, substs);
|
let field_ty = self.field_ty(expr.span, field, substs);
|
||||||
if field.vis.is_accessible_from(self.body_id, &self.tcx().map) {
|
if field.vis.is_accessible_from(self.body_id, &self.tcx().map) {
|
||||||
autoderef.finalize(lvalue_pref, Some(base));
|
autoderef.finalize(lvalue_pref, Some(base));
|
||||||
self.write_ty(expr.id, field_ty);
|
self.write_ty_expr(expr.id, field_ty);
|
||||||
self.write_autoderef_adjustment(base.id, autoderefs);
|
self.write_autoderef_adjustment(base.id, autoderefs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2984,7 +3003,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
if let Some((did, field_ty)) = private_candidate {
|
if let Some((did, field_ty)) = private_candidate {
|
||||||
let struct_path = self.tcx().item_path_str(did);
|
let struct_path = self.tcx().item_path_str(did);
|
||||||
self.write_ty(expr.id, field_ty);
|
self.write_ty_expr(expr.id, field_ty);
|
||||||
let msg = format!("field `{}` of struct `{}` is private", field.node, struct_path);
|
let msg = format!("field `{}` of struct `{}` is private", field.node, struct_path);
|
||||||
let mut err = self.tcx().sess.struct_span_err(expr.span, &msg);
|
let mut err = self.tcx().sess.struct_span_err(expr.span, &msg);
|
||||||
// Also check if an accessible method exists, which is often what is meant.
|
// Also check if an accessible method exists, which is often what is meant.
|
||||||
|
@ -3079,7 +3098,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
if let Some(field_ty) = field {
|
if let Some(field_ty) = field {
|
||||||
autoderef.finalize(lvalue_pref, Some(base));
|
autoderef.finalize(lvalue_pref, Some(base));
|
||||||
self.write_ty(expr.id, field_ty);
|
self.write_ty_expr(expr.id, field_ty);
|
||||||
self.write_autoderef_adjustment(base.id, autoderefs);
|
self.write_autoderef_adjustment(base.id, autoderefs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3090,7 +3109,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let struct_path = self.tcx().item_path_str(did);
|
let struct_path = self.tcx().item_path_str(did);
|
||||||
let msg = format!("field `{}` of struct `{}` is private", idx.node, struct_path);
|
let msg = format!("field `{}` of struct `{}` is private", idx.node, struct_path);
|
||||||
self.tcx().sess.span_err(expr.span, &msg);
|
self.tcx().sess.span_err(expr.span, &msg);
|
||||||
self.write_ty(expr.id, field_ty);
|
self.write_ty_expr(expr.id, field_ty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3343,7 +3362,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
hir::ExprLit(ref lit) => {
|
hir::ExprLit(ref lit) => {
|
||||||
let typ = self.check_lit(&lit, expected);
|
let typ = self.check_lit(&lit, expected);
|
||||||
self.write_ty(id, typ);
|
self.write_ty_expr(id, typ);
|
||||||
}
|
}
|
||||||
hir::ExprBinary(op, ref lhs, ref rhs) => {
|
hir::ExprBinary(op, ref lhs, ref rhs) => {
|
||||||
self.check_binop(expr, op, lhs, rhs);
|
self.check_binop(expr, op, lhs, rhs);
|
||||||
|
@ -3409,7 +3428,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.write_ty(id, oprnd_t);
|
self.write_ty_expr(id, oprnd_t);
|
||||||
}
|
}
|
||||||
hir::ExprAddrOf(mutbl, ref oprnd) => {
|
hir::ExprAddrOf(mutbl, ref oprnd) => {
|
||||||
let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
|
let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
|
||||||
|
@ -3460,7 +3479,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span,
|
let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span,
|
||||||
def);
|
def);
|
||||||
self.instantiate_value_path(segments, scheme, &predicates,
|
self.instantiate_value_path(segments, scheme, &predicates,
|
||||||
opt_ty, def, expr.span, id);
|
opt_ty, def, expr.span, id, true);
|
||||||
} else {
|
} else {
|
||||||
self.set_tainted_by_errors();
|
self.set_tainted_by_errors();
|
||||||
self.write_error(id);
|
self.write_error(id);
|
||||||
|
@ -3481,8 +3500,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
self.write_nil(id);
|
self.write_nil(id);
|
||||||
}
|
}
|
||||||
hir::ExprBreak(_) => { self.write_ty(id, self.next_diverging_ty_var()); }
|
hir::ExprBreak(_) => { self.write_empty(id); }
|
||||||
hir::ExprAgain(_) => { self.write_ty(id, self.next_diverging_ty_var()); }
|
hir::ExprAgain(_) => { self.write_empty(id); }
|
||||||
hir::ExprRet(ref expr_opt) => {
|
hir::ExprRet(ref expr_opt) => {
|
||||||
match self.ret_ty {
|
match self.ret_ty {
|
||||||
ty::FnConverging(result_type) => {
|
ty::FnConverging(result_type) => {
|
||||||
|
@ -3513,7 +3532,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.write_ty(id, self.next_diverging_ty_var());
|
self.write_empty(id);
|
||||||
}
|
}
|
||||||
hir::ExprAssign(ref lhs, ref rhs) => {
|
hir::ExprAssign(ref lhs, ref rhs) => {
|
||||||
self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue);
|
self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue);
|
||||||
|
@ -3555,7 +3574,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
hir::ExprLoop(ref body, _) => {
|
hir::ExprLoop(ref body, _) => {
|
||||||
self.check_block_no_value(&body);
|
self.check_block_no_value(&body);
|
||||||
if !may_break(tcx, expr.id, &body) {
|
if !may_break(tcx, expr.id, &body) {
|
||||||
self.write_ty(id, self.next_diverging_ty_var());
|
self.write_empty(id);
|
||||||
} else {
|
} else {
|
||||||
self.write_nil(id);
|
self.write_nil(id);
|
||||||
}
|
}
|
||||||
|
@ -3568,7 +3587,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
hir::ExprBlock(ref b) => {
|
hir::ExprBlock(ref b) => {
|
||||||
self.check_block_with_expected(&b, expected);
|
self.check_block_with_expected(&b, expected);
|
||||||
self.write_ty(id, self.node_ty(b.id));
|
self.write_ty_expr(id, self.node_ty(b.id));
|
||||||
}
|
}
|
||||||
hir::ExprCall(ref callee, ref args) => {
|
hir::ExprCall(ref callee, ref args) => {
|
||||||
self.check_call(expr, &callee, &args[..], expected);
|
self.check_call(expr, &callee, &args[..], expected);
|
||||||
|
@ -3604,7 +3623,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
// Write a type for the whole expression, assuming everything is going
|
// Write a type for the whole expression, assuming everything is going
|
||||||
// to work out Ok.
|
// to work out Ok.
|
||||||
self.write_ty(id, t_cast);
|
self.write_ty_expr(id, t_cast);
|
||||||
|
|
||||||
// Defer other checks until we're done type checking.
|
// Defer other checks until we're done type checking.
|
||||||
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
|
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
|
||||||
|
@ -3621,7 +3640,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
hir::ExprType(ref e, ref t) => {
|
hir::ExprType(ref e, ref t) => {
|
||||||
let typ = self.to_ty(&t);
|
let typ = self.to_ty(&t);
|
||||||
self.check_expr_eq_type(&e, typ);
|
self.check_expr_eq_type(&e, typ);
|
||||||
self.write_ty(id, typ);
|
self.write_ty_expr(id, typ);
|
||||||
}
|
}
|
||||||
hir::ExprVec(ref args) => {
|
hir::ExprVec(ref args) => {
|
||||||
let uty = expected.to_option(self).and_then(|uty| {
|
let uty = expected.to_option(self).and_then(|uty| {
|
||||||
|
@ -3755,7 +3774,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
Some((index_ty, element_ty)) => {
|
Some((index_ty, element_ty)) => {
|
||||||
let idx_expr_ty = self.expr_ty(idx);
|
let idx_expr_ty = self.expr_ty(idx);
|
||||||
self.demand_eqtype(expr.span, index_ty, idx_expr_ty);
|
self.demand_eqtype(expr.span, index_ty, idx_expr_ty);
|
||||||
self.write_ty(id, element_ty);
|
self.write_ty_expr(id, element_ty);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.check_expr_has_type(&idx, self.tcx.types.err);
|
self.check_expr_has_type(&idx, self.tcx.types.err);
|
||||||
|
@ -4011,7 +4030,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
"unreachable statement".to_string());
|
"unreachable statement".to_string());
|
||||||
warned = true;
|
warned = true;
|
||||||
}
|
}
|
||||||
any_diverges = any_diverges || self.type_var_diverges(s_ty);
|
any_diverges = any_diverges ||
|
||||||
|
self.type_var_diverges(s_ty) ||
|
||||||
|
s_ty.is_empty(self.tcx);
|
||||||
any_err = any_err || s_ty.references_error();
|
any_err = any_err || s_ty.references_error();
|
||||||
}
|
}
|
||||||
match blk.expr {
|
match blk.expr {
|
||||||
|
@ -4047,7 +4068,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
} else if any_diverges {
|
} else if any_diverges {
|
||||||
self.write_ty(blk.id, self.next_diverging_ty_var());
|
self.write_ty(blk.id, self.next_diverging_ty_var());
|
||||||
} else {
|
} else {
|
||||||
self.write_ty(blk.id, ety);
|
self.write_ty_expr(blk.id, ety);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -4096,7 +4117,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
opt_self_ty: Option<Ty<'tcx>>,
|
opt_self_ty: Option<Ty<'tcx>>,
|
||||||
def: Def,
|
def: Def,
|
||||||
span: Span,
|
span: Span,
|
||||||
node_id: ast::NodeId)
|
node_id: ast::NodeId,
|
||||||
|
node_is_expr: bool) {
|
||||||
-> Ty<'tcx> {
|
-> Ty<'tcx> {
|
||||||
debug!("instantiate_value_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
|
debug!("instantiate_value_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
|
||||||
segments,
|
segments,
|
||||||
|
@ -4360,7 +4382,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
debug!("instantiate_value_path: type of {:?} is {:?}",
|
debug!("instantiate_value_path: type of {:?} is {:?}",
|
||||||
node_id,
|
node_id,
|
||||||
ty_substituted);
|
ty_substituted);
|
||||||
|
if node_is_expr {
|
||||||
|
self.write_ty_expr(node_id, ty_substituted);
|
||||||
|
} else {
|
||||||
self.write_ty(node_id, ty_substituted);
|
self.write_ty(node_id, ty_substituted);
|
||||||
|
}
|
||||||
self.write_substs(node_id, ty::ItemSubsts {
|
self.write_substs(node_id, ty::ItemSubsts {
|
||||||
substs: substs
|
substs: substs
|
||||||
});
|
});
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.enforce_builtin_binop_types(lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
|
self.enforce_builtin_binop_types(lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
|
||||||
self.write_nil(expr.id);
|
self.write_nil(expr.id);
|
||||||
} else {
|
} else {
|
||||||
self.write_ty(expr.id, return_ty);
|
self.write_ty_expr(expr.id, return_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
@ -69,7 +69,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// && and || are a simple case.
|
// && and || are a simple case.
|
||||||
self.demand_suptype(lhs_expr.span, tcx.mk_bool(), lhs_ty);
|
self.demand_suptype(lhs_expr.span, tcx.mk_bool(), lhs_ty);
|
||||||
self.check_expr_coercable_to_type(rhs_expr, tcx.mk_bool());
|
self.check_expr_coercable_to_type(rhs_expr, tcx.mk_bool());
|
||||||
self.write_ty(expr.id, tcx.mk_bool());
|
self.write_ty_expr(expr.id, tcx.mk_bool());
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Otherwise, we always treat operators as if they are
|
// Otherwise, we always treat operators as if they are
|
||||||
|
@ -101,7 +101,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.demand_suptype(expr.span, builtin_return_ty, return_ty);
|
self.demand_suptype(expr.span, builtin_return_ty, return_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.write_ty(expr.id, return_ty);
|
self.write_ty_expr(expr.id, return_ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1332,11 +1332,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Parse optional return type [ -> TY ] in function decl
|
/// Parse optional return type [ -> TY ] in function decl
|
||||||
pub fn parse_ret_ty(&mut self) -> PResult<'a, FunctionRetTy> {
|
pub fn parse_ret_ty(&mut self) -> PResult<'a, FunctionRetTy> {
|
||||||
if self.eat(&token::RArrow) {
|
if self.eat(&token::RArrow) {
|
||||||
if self.eat(&token::Not) {
|
|
||||||
Ok(FunctionRetTy::None(self.last_span))
|
|
||||||
} else {
|
|
||||||
Ok(FunctionRetTy::Ty(self.parse_ty()?))
|
Ok(FunctionRetTy::Ty(self.parse_ty()?))
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let pos = self.span.lo;
|
let pos = self.span.lo;
|
||||||
Ok(FunctionRetTy::Default(mk_sp(pos, pos)))
|
Ok(FunctionRetTy::Default(mk_sp(pos, pos)))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue