From 505ff71ac1c427f1777805bfced50c8938029bcb Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 16 Sep 2017 02:33:41 +0300 Subject: [PATCH] Record semantic types for all syntactic types in bodies --- src/librustc_typeck/astconv.rs | 44 +++++++++++++------ src/librustc_typeck/check/mod.rs | 4 ++ src/librustc_typeck/check/writeback.rs | 7 +++ src/librustc_typeck/collect.rs | 4 ++ .../compile-fail/type-path-err-node-types.rs | 17 +++++++ 5 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 src/test/compile-fail/type-path-err-node-types.rs diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 5256bb22781..3171bd41f92 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -76,6 +76,8 @@ fn projected_ty_from_poly_trait_ref(&self, /// used to help suppress derived errors typeck might otherwise /// report. fn set_tainted_by_errors(&self); + + fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span); } struct ConvertedBinding<'tcx> { @@ -975,6 +977,14 @@ pub fn def_to_ty(&self, } } Def::Err => { + for segment in &path.segments { + for ty in &segment.parameters.types { + self.ast_ty_to_ty(ty); + } + for binding in &segment.parameters.bindings { + self.ast_ty_to_ty(&binding.ty); + } + } self.set_tainted_by_errors(); return self.tcx().types.err; } @@ -1115,6 +1125,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { } }; + self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span); result_ty } @@ -1124,8 +1135,10 @@ pub fn ty_of_arg(&self, -> Ty<'tcx> { match ty.node { - hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(), - hir::TyInfer => self.ty_infer(ty.span), + hir::TyInfer if expected_ty.is_some() => { + self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span); + expected_ty.unwrap() + } _ => self.ast_ty_to_ty(ty), } } @@ -1214,19 +1227,22 @@ pub fn ty_of_closure(&self, let expected_ret_ty = expected_sig.as_ref().map(|e| e.output()); - let is_infer = match decl.output { - hir::Return(ref output) if output.node == hir::TyInfer => true, - hir::DefaultReturn(..) => true, - _ => false - }; - let output_ty = match decl.output { - _ if is_infer && expected_ret_ty.is_some() => - expected_ret_ty.unwrap(), - _ if is_infer => self.ty_infer(decl.output.span()), - hir::Return(ref output) => - self.ast_ty_to_ty(&output), - hir::DefaultReturn(..) => bug!(), + hir::Return(ref output) => { + if let (&hir::TyInfer, Some(expected_ret_ty)) = (&output.node, expected_ret_ty) { + self.record_ty(output.hir_id, expected_ret_ty, output.span); + expected_ret_ty + } else { + self.ast_ty_to_ty(&output) + } + } + hir::DefaultReturn(span) => { + if let Some(expected_ret_ty) = expected_ret_ty { + expected_ret_ty + } else { + self.ty_infer(span) + } + } }; debug!("ty_of_closure: output_ty={:?}", output_ty); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ae2430990ba..edbdfc1a7d4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1665,6 +1665,10 @@ fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { fn set_tainted_by_errors(&self) { self.infcx.set_tainted_by_errors() } + + fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, _span: Span) { + self.write_ty(hir_id, ty) + } } /// Controls whether the arguments are tupled. This is used for the call diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 7810d9049e1..3c650718a4b 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -207,6 +207,13 @@ fn visit_local(&mut self, l: &'gcx hir::Local) { let var_ty = self.resolve(&var_ty, &l.span); self.write_ty_to_tables(l.hir_id, var_ty); } + + fn visit_ty(&mut self, hir_ty: &'gcx hir::Ty) { + intravisit::walk_ty(self, hir_ty); + let ty = self.fcx.node_ty(hir_ty.hir_id); + let ty = self.resolve(&ty, &hir_ty.span); + self.write_ty_to_tables(hir_ty.hir_id, ty); + } } impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 8d078b92275..a36594cb6e5 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -221,6 +221,10 @@ fn normalize_ty(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { fn set_tainted_by_errors(&self) { // no obvious place to track this, just let it go } + + fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) { + // no place to record types from signatures? + } } fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/test/compile-fail/type-path-err-node-types.rs b/src/test/compile-fail/type-path-err-node-types.rs new file mode 100644 index 00000000000..8f26777b441 --- /dev/null +++ b/src/test/compile-fail/type-path-err-node-types.rs @@ -0,0 +1,17 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Type arguments of unresolved types should have their types recorded + +fn main() { + let _: Nonexistent; //~ ERROR cannot find type `Nonexistent` in this scope + + let _ = |a, b: _| -> _ { 0 }; +} -- 2.44.0