fixes #40013
This commit is contained in:
parent
c398efc53f
commit
6383de15b1
14 changed files with 260 additions and 275 deletions
|
|
@ -1807,6 +1807,58 @@ makes a difference in practice.)
|
||||||
[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
|
[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
E0101: r##"
|
||||||
|
#### Note: this error code is no longer emitted by the compiler.
|
||||||
|
|
||||||
|
You hit this error because the compiler lacks the information to
|
||||||
|
determine a type for this expression. Erroneous code example:
|
||||||
|
|
||||||
|
```ignore
|
||||||
|
let x = |_| {}; // error: cannot determine a type for this expression
|
||||||
|
```
|
||||||
|
|
||||||
|
You have two possibilities to solve this situation:
|
||||||
|
|
||||||
|
* Give an explicit definition of the expression
|
||||||
|
* Infer the expression
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```
|
||||||
|
let x = |_ : u32| {}; // ok!
|
||||||
|
// or:
|
||||||
|
let x = |_| {};
|
||||||
|
x(0u32);
|
||||||
|
```
|
||||||
|
"##,
|
||||||
|
|
||||||
|
E0102: r##"
|
||||||
|
#### Note: this error code is no longer emitted by the compiler.
|
||||||
|
|
||||||
|
You hit this error because the compiler lacks the information to
|
||||||
|
determine the type of this variable. Erroneous code example:
|
||||||
|
|
||||||
|
```ignore
|
||||||
|
// could be an array of anything
|
||||||
|
let x = []; // error: cannot determine a type for this local variable
|
||||||
|
```
|
||||||
|
|
||||||
|
To solve this situation, constrain the type of the variable.
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: [u8; 0] = [];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
"##,
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ use super::{
|
||||||
|
|
||||||
use errors::DiagnosticBuilder;
|
use errors::DiagnosticBuilder;
|
||||||
use fmt_macros::{Parser, Piece, Position};
|
use fmt_macros::{Parser, Piece, Position};
|
||||||
use hir::{intravisit, Local, Pat};
|
use hir::{self, intravisit, Local, Pat, Body};
|
||||||
use hir::intravisit::{Visitor, NestedVisitorMap};
|
use hir::intravisit::{Visitor, NestedVisitorMap};
|
||||||
use hir::map::NodeExpr;
|
use hir::map::NodeExpr;
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
|
|
@ -33,8 +33,8 @@ use infer::{self, InferCtxt};
|
||||||
use infer::type_variable::TypeVariableOrigin;
|
use infer::type_variable::TypeVariableOrigin;
|
||||||
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
|
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use syntax::ast;
|
use syntax::ast::{self, NodeId};
|
||||||
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, TyInfer, TyVar};
|
||||||
use ty::error::ExpectedFound;
|
use ty::error::ExpectedFound;
|
||||||
use ty::fast_reject;
|
use ty::fast_reject;
|
||||||
use ty::fold::TypeFolder;
|
use ty::fold::TypeFolder;
|
||||||
|
|
@ -66,38 +66,53 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
|
||||||
struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
target_ty: &'a Ty<'tcx>,
|
target_ty: &'a Ty<'tcx>,
|
||||||
found_pattern: Option<&'a Pat>,
|
hir_map: &'a hir::map::Map<'gcx>,
|
||||||
|
found_local_pattern: Option<&'gcx Pat>,
|
||||||
|
found_arg_pattern: Option<&'gcx Pat>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
|
||||||
fn is_match(&self, ty: Ty<'tcx>) -> bool {
|
fn node_matches_type(&mut self, node_id: &'gcx NodeId) -> bool {
|
||||||
ty == *self.target_ty || match (&ty.sty, &self.target_ty.sty) {
|
match self.infcx.tables.borrow().node_types.get(node_id) {
|
||||||
(&ty::TyInfer(ty::TyVar(a_vid)), &ty::TyInfer(ty::TyVar(b_vid))) =>
|
Some(&ty) => {
|
||||||
self.infcx.type_variables
|
let ty = self.infcx.resolve_type_vars_if_possible(&ty);
|
||||||
.borrow_mut()
|
ty.walk().any(|inner_ty| {
|
||||||
.sub_unified(a_vid, b_vid),
|
inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) {
|
||||||
|
(&TyInfer(TyVar(a_vid)), &TyInfer(TyVar(b_vid))) => {
|
||||||
|
self.infcx
|
||||||
|
.type_variables
|
||||||
|
.borrow_mut()
|
||||||
|
.sub_unified(a_vid, b_vid)
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> Visitor<'a> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
|
||||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
|
||||||
NestedVisitorMap::None
|
NestedVisitorMap::OnlyBodies(&self.hir_map)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_local(&mut self, local: &'a Local) {
|
fn visit_local(&mut self, local: &'gcx Local) {
|
||||||
if let Some(&ty) = self.infcx.tables.borrow().node_types.get(&local.id) {
|
if self.found_local_pattern.is_none() && self.node_matches_type(&local.id) {
|
||||||
let ty = self.infcx.resolve_type_vars_if_possible(&ty);
|
self.found_local_pattern = Some(&*local.pat);
|
||||||
let is_match = ty.walk().any(|t| self.is_match(t));
|
|
||||||
|
|
||||||
if is_match && self.found_pattern.is_none() {
|
|
||||||
self.found_pattern = Some(&*local.pat);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
intravisit::walk_local(self, local);
|
intravisit::walk_local(self, local);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_body(&mut self, body: &'gcx Body) {
|
||||||
|
for argument in &body.arguments {
|
||||||
|
if self.found_arg_pattern.is_none() && self.node_matches_type(&argument.id) {
|
||||||
|
self.found_arg_pattern = Some(&*argument.pat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
intravisit::walk_body(self, body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
@ -721,6 +736,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
// coherence violation, so we don't report it here.
|
// coherence violation, so we don't report it here.
|
||||||
|
|
||||||
let predicate = self.resolve_type_vars_if_possible(&obligation.predicate);
|
let predicate = self.resolve_type_vars_if_possible(&obligation.predicate);
|
||||||
|
let body_id = hir::BodyId { node_id: obligation.cause.body_id };
|
||||||
|
let span = obligation.cause.span;
|
||||||
|
|
||||||
debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
|
debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
|
||||||
predicate,
|
predicate,
|
||||||
|
|
@ -768,10 +785,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.tcx.lang_items.sized_trait()
|
self.tcx.lang_items.sized_trait()
|
||||||
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
|
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
|
||||||
{
|
{
|
||||||
self.need_type_info(obligation, self_ty);
|
self.need_type_info(body_id, span, self_ty);
|
||||||
} else {
|
} else {
|
||||||
let mut err = struct_span_err!(self.tcx.sess,
|
let mut err = struct_span_err!(self.tcx.sess,
|
||||||
obligation.cause.span, E0283,
|
span, E0283,
|
||||||
"type annotations required: \
|
"type annotations required: \
|
||||||
cannot resolve `{}`",
|
cannot resolve `{}`",
|
||||||
predicate);
|
predicate);
|
||||||
|
|
@ -785,7 +802,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
// Same hacky approach as above to avoid deluging user
|
// Same hacky approach as above to avoid deluging user
|
||||||
// with error messages.
|
// with error messages.
|
||||||
if !ty.references_error() && !self.tcx.sess.has_errors() {
|
if !ty.references_error() && !self.tcx.sess.has_errors() {
|
||||||
self.need_type_info(obligation, ty);
|
self.need_type_info(body_id, span, ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -796,7 +813,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
|
let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
|
||||||
// both must be type variables, or the other would've been instantiated
|
// both must be type variables, or the other would've been instantiated
|
||||||
assert!(a.is_ty_var() && b.is_ty_var());
|
assert!(a.is_ty_var() && b.is_ty_var());
|
||||||
self.need_type_info(obligation, a);
|
self.need_type_info(hir::BodyId { node_id: obligation.cause.body_id },
|
||||||
|
obligation.cause.span,
|
||||||
|
a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -874,42 +893,66 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn need_type_info(&self, obligation: &PredicateObligation<'tcx>, ty: Ty<'tcx>) {
|
pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) {
|
||||||
let ty = self.resolve_type_vars_if_possible(&ty);
|
let ty = self.resolve_type_vars_if_possible(&ty);
|
||||||
let name = self.extract_type_name(&ty);
|
let name = self.extract_type_name(&ty);
|
||||||
let ref cause = obligation.cause;
|
|
||||||
|
|
||||||
let mut err = struct_span_err!(self.tcx.sess,
|
let mut err_span = span;
|
||||||
cause.span,
|
let mut labels = vec![(span, format!("cannot infer type for `{}`", name))];
|
||||||
E0282,
|
|
||||||
"type annotations needed");
|
|
||||||
|
|
||||||
err.span_label(cause.span, &format!("cannot infer type for `{}`", name));
|
|
||||||
|
|
||||||
let mut local_visitor = FindLocalByTypeVisitor {
|
let mut local_visitor = FindLocalByTypeVisitor {
|
||||||
infcx: &self,
|
infcx: &self,
|
||||||
target_ty: &ty,
|
target_ty: &ty,
|
||||||
found_pattern: None,
|
hir_map: &self.tcx.hir,
|
||||||
|
found_local_pattern: None,
|
||||||
|
found_arg_pattern: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// #40294: cause.body_id can also be a fn declaration.
|
// #40294: cause.body_id can also be a fn declaration.
|
||||||
// Currently, if it's anything other than NodeExpr, we just ignore it
|
// Currently, if it's anything other than NodeExpr, we just ignore it
|
||||||
match self.tcx.hir.find(cause.body_id) {
|
match self.tcx.hir.find(body_id.node_id) {
|
||||||
Some(NodeExpr(expr)) => local_visitor.visit_expr(expr),
|
Some(NodeExpr(expr)) => local_visitor.visit_expr(expr),
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(pattern) = local_visitor.found_pattern {
|
if let Some(pattern) = local_visitor.found_arg_pattern {
|
||||||
let pattern_span = pattern.span;
|
err_span = pattern.span;
|
||||||
|
// We don't want to show the default label for closures.
|
||||||
|
//
|
||||||
|
// So, before clearing, the output would look something like this:
|
||||||
|
// ```
|
||||||
|
// let x = |_| { };
|
||||||
|
// - ^^^^ cannot infer type for `[_; 0]`
|
||||||
|
// |
|
||||||
|
// consider giving this closure parameter a type
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// After clearing, it looks something like this:
|
||||||
|
// ```
|
||||||
|
// let x = |_| { };
|
||||||
|
// ^ consider giving this closure parameter a type
|
||||||
|
// ```
|
||||||
|
labels.clear();
|
||||||
|
labels.push((pattern.span, format!("consider giving this closure parameter a type")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(pattern) = local_visitor.found_local_pattern {
|
||||||
if let Some(simple_name) = pattern.simple_name() {
|
if let Some(simple_name) = pattern.simple_name() {
|
||||||
err.span_label(pattern_span,
|
labels.push((pattern.span, format!("consider giving `{}` a type", simple_name)));
|
||||||
&format!("consider giving `{}` a type",
|
|
||||||
simple_name));
|
|
||||||
} else {
|
} else {
|
||||||
err.span_label(pattern_span, &format!("consider giving a type to pattern"));
|
labels.push((pattern.span, format!("consider giving a type to pattern")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut err = struct_span_err!(self.tcx.sess,
|
||||||
|
err_span,
|
||||||
|
E0282,
|
||||||
|
"type annotations needed");
|
||||||
|
|
||||||
|
for (target_span, label_message) in labels {
|
||||||
|
err.span_label(target_span, &label_message);
|
||||||
|
}
|
||||||
|
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,22 +11,18 @@
|
||||||
// Type resolution: the phase that finds all the types in the AST with
|
// Type resolution: the phase that finds all the types in the AST with
|
||||||
// unresolved type variables and replaces "ty_var" types with their
|
// unresolved type variables and replaces "ty_var" types with their
|
||||||
// substitutions.
|
// substitutions.
|
||||||
use self::ResolveReason::*;
|
|
||||||
|
|
||||||
use check::FnCtxt;
|
use check::FnCtxt;
|
||||||
|
use rustc::hir;
|
||||||
|
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||||
|
use rustc::infer::{InferCtxt};
|
||||||
use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee};
|
use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee};
|
||||||
use rustc::ty::adjustment;
|
use rustc::ty::adjustment;
|
||||||
use rustc::ty::fold::{TypeFolder,TypeFoldable};
|
use rustc::ty::fold::{TypeFolder,TypeFoldable};
|
||||||
use rustc::infer::{InferCtxt, FixupError};
|
|
||||||
use rustc::util::nodemap::{DefIdMap, DefIdSet};
|
use rustc::util::nodemap::{DefIdMap, DefIdSet};
|
||||||
|
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
use std::mem;
|
||||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
|
||||||
use rustc::hir;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Entry point
|
// Entry point
|
||||||
|
|
@ -37,9 +33,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let item_id = self.tcx.hir.body_owner(body.id());
|
let item_id = self.tcx.hir.body_owner(body.id());
|
||||||
let item_def_id = self.tcx.hir.local_def_id(item_id);
|
let item_def_id = self.tcx.hir.local_def_id(item_id);
|
||||||
|
|
||||||
let mut wbcx = WritebackCx::new(self);
|
let mut wbcx = WritebackCx::new(self, body);
|
||||||
for arg in &body.arguments {
|
for arg in &body.arguments {
|
||||||
wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id);
|
wbcx.visit_node_id(arg.pat.span, arg.id);
|
||||||
}
|
}
|
||||||
wbcx.visit_body(body);
|
wbcx.visit_body(body);
|
||||||
wbcx.visit_upvar_borrow_map();
|
wbcx.visit_upvar_borrow_map();
|
||||||
|
|
@ -80,15 +76,19 @@ struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
|
||||||
// early-bound versions of them, visible from the
|
// early-bound versions of them, visible from the
|
||||||
// outside of the function. This is needed by, and
|
// outside of the function. This is needed by, and
|
||||||
// only populated if there are any `impl Trait`.
|
// only populated if there are any `impl Trait`.
|
||||||
free_to_bound_regions: DefIdMap<&'gcx ty::Region>
|
free_to_bound_regions: DefIdMap<&'gcx ty::Region>,
|
||||||
|
|
||||||
|
body: &'gcx hir::Body,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>) -> WritebackCx<'cx, 'gcx, 'tcx> {
|
fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, body: &'gcx hir::Body)
|
||||||
|
-> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
let mut wbcx = WritebackCx {
|
let mut wbcx = WritebackCx {
|
||||||
fcx: fcx,
|
fcx: fcx,
|
||||||
tables: ty::TypeckTables::empty(),
|
tables: ty::TypeckTables::empty(),
|
||||||
free_to_bound_regions: DefIdMap()
|
free_to_bound_regions: DefIdMap(),
|
||||||
|
body: body
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only build the reverse mapping if `impl Trait` is used.
|
// Only build the reverse mapping if `impl Trait` is used.
|
||||||
|
|
@ -195,21 +195,20 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_stmt(&mut self, s: &'gcx hir::Stmt) {
|
fn visit_stmt(&mut self, s: &'gcx hir::Stmt) {
|
||||||
self.visit_node_id(ResolvingExpr(s.span), s.node.id());
|
self.visit_node_id(s.span, s.node.id());
|
||||||
intravisit::walk_stmt(self, s);
|
intravisit::walk_stmt(self, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, e: &'gcx hir::Expr) {
|
fn visit_expr(&mut self, e: &'gcx hir::Expr) {
|
||||||
self.fix_scalar_builtin_expr(e);
|
self.fix_scalar_builtin_expr(e);
|
||||||
|
|
||||||
self.visit_node_id(ResolvingExpr(e.span), e.id);
|
self.visit_node_id(e.span, e.id);
|
||||||
self.visit_method_map_entry(ResolvingExpr(e.span),
|
self.visit_method_map_entry(e.span, MethodCall::expr(e.id));
|
||||||
MethodCall::expr(e.id));
|
|
||||||
|
|
||||||
if let hir::ExprClosure(_, _, body, _) = e.node {
|
if let hir::ExprClosure(_, _, body, _) = e.node {
|
||||||
let body = self.fcx.tcx.hir.body(body);
|
let body = self.fcx.tcx.hir.body(body);
|
||||||
for arg in &body.arguments {
|
for arg in &body.arguments {
|
||||||
self.visit_node_id(ResolvingExpr(e.span), arg.id);
|
self.visit_node_id(e.span, arg.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.visit_body(body);
|
self.visit_body(body);
|
||||||
|
|
@ -219,20 +218,20 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_block(&mut self, b: &'gcx hir::Block) {
|
fn visit_block(&mut self, b: &'gcx hir::Block) {
|
||||||
self.visit_node_id(ResolvingExpr(b.span), b.id);
|
self.visit_node_id(b.span, b.id);
|
||||||
intravisit::walk_block(self, b);
|
intravisit::walk_block(self, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_pat(&mut self, p: &'gcx hir::Pat) {
|
fn visit_pat(&mut self, p: &'gcx hir::Pat) {
|
||||||
self.visit_node_id(ResolvingPattern(p.span), p.id);
|
self.visit_node_id(p.span, p.id);
|
||||||
intravisit::walk_pat(self, p);
|
intravisit::walk_pat(self, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_local(&mut self, l: &'gcx hir::Local) {
|
fn visit_local(&mut self, l: &'gcx hir::Local) {
|
||||||
let var_ty = self.fcx.local_ty(l.span, l.id);
|
|
||||||
let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span));
|
|
||||||
self.write_ty_to_tables(l.id, var_ty);
|
|
||||||
intravisit::walk_local(self, l);
|
intravisit::walk_local(self, l);
|
||||||
|
let var_ty = self.fcx.local_ty(l.span, l.id);
|
||||||
|
let var_ty = self.resolve(&var_ty, &l.span);
|
||||||
|
self.write_ty_to_tables(l.id, var_ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,7 +242,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
|
ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
|
||||||
ty::UpvarCapture::ByRef(ref upvar_borrow) => {
|
ty::UpvarCapture::ByRef(ref upvar_borrow) => {
|
||||||
let r = upvar_borrow.region;
|
let r = upvar_borrow.region;
|
||||||
let r = self.resolve(&r, ResolvingUpvar(*upvar_id));
|
let r = self.resolve(&r, &upvar_id.var_id);
|
||||||
ty::UpvarCapture::ByRef(
|
ty::UpvarCapture::ByRef(
|
||||||
ty::UpvarBorrow { kind: upvar_borrow.kind, region: r })
|
ty::UpvarBorrow { kind: upvar_borrow.kind, region: r })
|
||||||
}
|
}
|
||||||
|
|
@ -257,7 +256,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
fn visit_closures(&mut self) {
|
fn visit_closures(&mut self) {
|
||||||
for (&id, closure_ty) in self.fcx.tables.borrow().closure_tys.iter() {
|
for (&id, closure_ty) in self.fcx.tables.borrow().closure_tys.iter() {
|
||||||
let closure_ty = self.resolve(closure_ty, ResolvingClosure(id));
|
let closure_ty = self.resolve(closure_ty, &id);
|
||||||
self.tables.closure_tys.insert(id, closure_ty);
|
self.tables.closure_tys.insert(id, closure_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -282,8 +281,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
fn visit_anon_types(&mut self) {
|
fn visit_anon_types(&mut self) {
|
||||||
let gcx = self.tcx().global_tcx();
|
let gcx = self.tcx().global_tcx();
|
||||||
for (&node_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() {
|
for (&node_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() {
|
||||||
let reason = ResolvingAnonTy(node_id);
|
let inside_ty = self.resolve(&concrete_ty, &node_id);
|
||||||
let inside_ty = self.resolve(&concrete_ty, reason);
|
|
||||||
|
|
||||||
// Convert the type from the function into a type valid outside
|
// Convert the type from the function into a type valid outside
|
||||||
// the function, by replacing free regions with early-bound ones.
|
// the function, by replacing free regions with early-bound ones.
|
||||||
|
|
@ -305,7 +303,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
ty::ReLateBound(..) |
|
ty::ReLateBound(..) |
|
||||||
ty::ReScope(_) |
|
ty::ReScope(_) |
|
||||||
ty::ReSkolemized(..) => {
|
ty::ReSkolemized(..) => {
|
||||||
let span = reason.span(self.tcx());
|
let span = node_id.to_span(&self.fcx.tcx);
|
||||||
span_err!(self.tcx().sess, span, E0564,
|
span_err!(self.tcx().sess, span, E0564,
|
||||||
"only named lifetimes are allowed in `impl Trait`, \
|
"only named lifetimes are allowed in `impl Trait`, \
|
||||||
but `{}` was found in the type `{}`", r, inside_ty);
|
but `{}` was found in the type `{}`", r, inside_ty);
|
||||||
|
|
@ -314,7 +312,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
ty::ReVar(_) |
|
ty::ReVar(_) |
|
||||||
ty::ReErased => {
|
ty::ReErased => {
|
||||||
let span = reason.span(self.tcx());
|
let span = node_id.to_span(&self.fcx.tcx);
|
||||||
span_bug!(span, "invalid region in impl Trait: {:?}", r);
|
span_bug!(span, "invalid region in impl Trait: {:?}", r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -324,37 +322,37 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_node_id(&mut self, reason: ResolveReason, id: ast::NodeId) {
|
fn visit_node_id(&mut self, span: Span, node_id: ast::NodeId) {
|
||||||
// Export associated path extensions.
|
// Export associated path extensions.
|
||||||
if let Some(def) = self.fcx.tables.borrow_mut().type_relative_path_defs.remove(&id) {
|
if let Some(def) = self.fcx.tables.borrow_mut().type_relative_path_defs.remove(&node_id) {
|
||||||
self.tables.type_relative_path_defs.insert(id, def);
|
self.tables.type_relative_path_defs.insert(node_id, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve any borrowings for the node with id `id`
|
// Resolve any borrowings for the node with id `node_id`
|
||||||
self.visit_adjustments(reason, id);
|
self.visit_adjustments(span, node_id);
|
||||||
|
|
||||||
// Resolve the type of the node with id `id`
|
// Resolve the type of the node with id `node_id`
|
||||||
let n_ty = self.fcx.node_ty(id);
|
let n_ty = self.fcx.node_ty(node_id);
|
||||||
let n_ty = self.resolve(&n_ty, reason);
|
let n_ty = self.resolve(&n_ty, &span);
|
||||||
self.write_ty_to_tables(id, n_ty);
|
self.write_ty_to_tables(node_id, n_ty);
|
||||||
debug!("Node {} has type {:?}", id, n_ty);
|
debug!("Node {} has type {:?}", node_id, n_ty);
|
||||||
|
|
||||||
// Resolve any substitutions
|
// Resolve any substitutions
|
||||||
self.fcx.opt_node_ty_substs(id, |item_substs| {
|
self.fcx.opt_node_ty_substs(node_id, |item_substs| {
|
||||||
let item_substs = self.resolve(item_substs, reason);
|
let item_substs = self.resolve(item_substs, &span);
|
||||||
if !item_substs.is_noop() {
|
if !item_substs.is_noop() {
|
||||||
debug!("write_substs_to_tcx({}, {:?})", id, item_substs);
|
debug!("write_substs_to_tcx({}, {:?})", node_id, item_substs);
|
||||||
assert!(!item_substs.substs.needs_infer());
|
assert!(!item_substs.substs.needs_infer());
|
||||||
self.tables.item_substs.insert(id, item_substs);
|
self.tables.item_substs.insert(node_id, item_substs);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_adjustments(&mut self, reason: ResolveReason, id: ast::NodeId) {
|
fn visit_adjustments(&mut self, span: Span, node_id: ast::NodeId) {
|
||||||
let adjustments = self.fcx.tables.borrow_mut().adjustments.remove(&id);
|
let adjustments = self.fcx.tables.borrow_mut().adjustments.remove(&node_id);
|
||||||
match adjustments {
|
match adjustments {
|
||||||
None => {
|
None => {
|
||||||
debug!("No adjustments for node {}", id);
|
debug!("No adjustments for node {}", node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(adjustment) => {
|
Some(adjustment) => {
|
||||||
|
|
@ -381,29 +379,29 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
adjustment::Adjust::DerefRef { autoderefs, autoref, unsize } => {
|
adjustment::Adjust::DerefRef { autoderefs, autoref, unsize } => {
|
||||||
for autoderef in 0..autoderefs {
|
for autoderef in 0..autoderefs {
|
||||||
let method_call = MethodCall::autoderef(id, autoderef as u32);
|
let method_call = MethodCall::autoderef(node_id, autoderef as u32);
|
||||||
self.visit_method_map_entry(reason, method_call);
|
self.visit_method_map_entry(span, method_call);
|
||||||
}
|
}
|
||||||
|
|
||||||
adjustment::Adjust::DerefRef {
|
adjustment::Adjust::DerefRef {
|
||||||
autoderefs: autoderefs,
|
autoderefs: autoderefs,
|
||||||
autoref: self.resolve(&autoref, reason),
|
autoref: self.resolve(&autoref, &span),
|
||||||
unsize: unsize,
|
unsize: unsize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let resolved_adjustment = adjustment::Adjustment {
|
let resolved_adjustment = adjustment::Adjustment {
|
||||||
kind: resolved_adjustment,
|
kind: resolved_adjustment,
|
||||||
target: self.resolve(&adjustment.target, reason)
|
target: self.resolve(&adjustment.target, &span)
|
||||||
};
|
};
|
||||||
debug!("Adjustments for node {}: {:?}", id, resolved_adjustment);
|
debug!("Adjustments for node {}: {:?}", node_id, resolved_adjustment);
|
||||||
self.tables.adjustments.insert(id, resolved_adjustment);
|
self.tables.adjustments.insert(node_id, resolved_adjustment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_method_map_entry(&mut self,
|
fn visit_method_map_entry(&mut self,
|
||||||
reason: ResolveReason,
|
method_span: Span,
|
||||||
method_call: MethodCall) {
|
method_call: MethodCall) {
|
||||||
// Resolve any method map entry
|
// Resolve any method map entry
|
||||||
let new_method = match self.fcx.tables.borrow_mut().method_map.remove(&method_call) {
|
let new_method = match self.fcx.tables.borrow_mut().method_map.remove(&method_call) {
|
||||||
|
|
@ -413,8 +411,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
method);
|
method);
|
||||||
let new_method = MethodCallee {
|
let new_method = MethodCallee {
|
||||||
def_id: method.def_id,
|
def_id: method.def_id,
|
||||||
ty: self.resolve(&method.ty, reason),
|
ty: self.resolve(&method.ty, &method_span),
|
||||||
substs: self.resolve(&method.substs, reason),
|
substs: self.resolve(&method.substs, &method_span),
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(new_method)
|
Some(new_method)
|
||||||
|
|
@ -430,72 +428,49 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
fn visit_liberated_fn_sigs(&mut self) {
|
fn visit_liberated_fn_sigs(&mut self) {
|
||||||
for (&node_id, fn_sig) in self.fcx.tables.borrow().liberated_fn_sigs.iter() {
|
for (&node_id, fn_sig) in self.fcx.tables.borrow().liberated_fn_sigs.iter() {
|
||||||
let fn_sig = self.resolve(fn_sig, ResolvingFnSig(node_id));
|
let fn_sig = self.resolve(fn_sig, &node_id);
|
||||||
self.tables.liberated_fn_sigs.insert(node_id, fn_sig.clone());
|
self.tables.liberated_fn_sigs.insert(node_id, fn_sig.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_fru_field_types(&mut self) {
|
fn visit_fru_field_types(&mut self) {
|
||||||
for (&node_id, ftys) in self.fcx.tables.borrow().fru_field_types.iter() {
|
for (&node_id, ftys) in self.fcx.tables.borrow().fru_field_types.iter() {
|
||||||
let ftys = self.resolve(ftys, ResolvingFieldTypes(node_id));
|
let ftys = self.resolve(ftys, &node_id);
|
||||||
self.tables.fru_field_types.insert(node_id, ftys);
|
self.tables.fru_field_types.insert(node_id, ftys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_type_nodes(&self) {
|
fn visit_type_nodes(&self) {
|
||||||
for (&id, ty) in self.fcx.ast_ty_to_ty_cache.borrow().iter() {
|
for (&id, ty) in self.fcx.ast_ty_to_ty_cache.borrow().iter() {
|
||||||
let ty = self.resolve(ty, ResolvingTyNode(id));
|
let ty = self.resolve(ty, &id);
|
||||||
self.fcx.tcx.ast_ty_to_ty_cache.borrow_mut().insert(id, ty);
|
self.fcx.tcx.ast_ty_to_ty_cache.borrow_mut().insert(id, ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve<T>(&self, x: &T, reason: ResolveReason) -> T::Lifted
|
fn resolve<T>(&self, x: &T, span: &Locatable) -> T::Lifted
|
||||||
where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
|
where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
|
||||||
{
|
{
|
||||||
let x = x.fold_with(&mut Resolver::new(self.fcx, reason));
|
let x = x.fold_with(&mut Resolver::new(self.fcx, span, self.body));
|
||||||
if let Some(lifted) = self.tcx().lift_to_global(&x) {
|
if let Some(lifted) = self.tcx().lift_to_global(&x) {
|
||||||
lifted
|
lifted
|
||||||
} else {
|
} else {
|
||||||
span_bug!(reason.span(self.tcx()),
|
span_bug!(span.to_span(&self.fcx.tcx),
|
||||||
"writeback: `{:?}` missing from the global type context", x);
|
"writeback: `{:?}` missing from the global type context",
|
||||||
|
x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
trait Locatable {
|
||||||
// Resolution reason.
|
fn to_span(&self, tcx: &TyCtxt) -> Span;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
enum ResolveReason {
|
|
||||||
ResolvingExpr(Span),
|
|
||||||
ResolvingLocal(Span),
|
|
||||||
ResolvingPattern(Span),
|
|
||||||
ResolvingUpvar(ty::UpvarId),
|
|
||||||
ResolvingClosure(ast::NodeId),
|
|
||||||
ResolvingFnSig(ast::NodeId),
|
|
||||||
ResolvingFieldTypes(ast::NodeId),
|
|
||||||
ResolvingAnonTy(ast::NodeId),
|
|
||||||
ResolvingTyNode(ast::NodeId),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> ResolveReason {
|
impl Locatable for Span {
|
||||||
fn span(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Span {
|
fn to_span(&self, _: &TyCtxt) -> Span { *self }
|
||||||
match *self {
|
}
|
||||||
ResolvingExpr(s) => s,
|
|
||||||
ResolvingLocal(s) => s,
|
impl Locatable for ast::NodeId {
|
||||||
ResolvingPattern(s) => s,
|
fn to_span(&self, tcx: &TyCtxt) -> Span { tcx.hir.span(*self) }
|
||||||
ResolvingUpvar(upvar_id) => {
|
|
||||||
tcx.expr_span(upvar_id.closure_expr_id)
|
|
||||||
}
|
|
||||||
ResolvingClosure(id) |
|
|
||||||
ResolvingFnSig(id) |
|
|
||||||
ResolvingFieldTypes(id) |
|
|
||||||
ResolvingTyNode(id) |
|
|
||||||
ResolvingAnonTy(id) => {
|
|
||||||
tcx.hir.span(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -505,82 +480,25 @@ impl<'a, 'gcx, 'tcx> ResolveReason {
|
||||||
struct Resolver<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
|
struct Resolver<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
|
||||||
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
|
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
|
||||||
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
|
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
|
||||||
reason: ResolveReason,
|
span: &'cx Locatable,
|
||||||
|
body: &'gcx hir::Body,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> {
|
impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> {
|
||||||
fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>,
|
fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, span: &'cx Locatable, body: &'gcx hir::Body)
|
||||||
reason: ResolveReason)
|
-> Resolver<'cx, 'gcx, 'tcx>
|
||||||
-> Resolver<'cx, 'gcx, 'tcx>
|
|
||||||
{
|
{
|
||||||
Resolver::from_infcx(fcx, reason)
|
Resolver {
|
||||||
|
tcx: fcx.tcx,
|
||||||
|
infcx: fcx,
|
||||||
|
span: span,
|
||||||
|
body: body,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_infcx(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
|
fn report_error(&self, t: Ty<'tcx>) {
|
||||||
reason: ResolveReason)
|
|
||||||
-> Resolver<'cx, 'gcx, 'tcx>
|
|
||||||
{
|
|
||||||
Resolver { infcx: infcx,
|
|
||||||
tcx: infcx.tcx,
|
|
||||||
reason: reason }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn report_error(&self, e: FixupError) {
|
|
||||||
if !self.tcx.sess.has_errors() {
|
if !self.tcx.sess.has_errors() {
|
||||||
match self.reason {
|
self.infcx.need_type_info(self.body.id(), self.span.to_span(&self.tcx), t);
|
||||||
ResolvingExpr(span) => {
|
|
||||||
struct_span_err!(
|
|
||||||
self.tcx.sess, span, E0101,
|
|
||||||
"cannot determine a type for this expression: {}", e)
|
|
||||||
.span_label(span, &format!("cannot resolve type of expression"))
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolvingLocal(span) => {
|
|
||||||
struct_span_err!(
|
|
||||||
self.tcx.sess, span, E0102,
|
|
||||||
"cannot determine a type for this local variable: {}", e)
|
|
||||||
.span_label(span, &format!("cannot resolve type of variable"))
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolvingPattern(span) => {
|
|
||||||
span_err!(self.tcx.sess, span, E0103,
|
|
||||||
"cannot determine a type for this pattern binding: {}", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolvingUpvar(upvar_id) => {
|
|
||||||
let span = self.reason.span(self.tcx);
|
|
||||||
span_err!(self.tcx.sess, span, E0104,
|
|
||||||
"cannot resolve lifetime for captured variable `{}`: {}",
|
|
||||||
self.tcx.local_var_name_str(upvar_id.var_id), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolvingClosure(_) => {
|
|
||||||
let span = self.reason.span(self.tcx);
|
|
||||||
span_err!(self.tcx.sess, span, E0196,
|
|
||||||
"cannot determine a type for this closure")
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolvingFnSig(_) |
|
|
||||||
ResolvingFieldTypes(_) |
|
|
||||||
ResolvingTyNode(_) => {
|
|
||||||
// any failures here should also fail when
|
|
||||||
// resolving the patterns, closure types, or
|
|
||||||
// something else.
|
|
||||||
let span = self.reason.span(self.tcx);
|
|
||||||
self.tcx.sess.delay_span_bug(
|
|
||||||
span,
|
|
||||||
&format!("cannot resolve some aspect of data for {:?}: {}",
|
|
||||||
self.reason, e));
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolvingAnonTy(_) => {
|
|
||||||
let span = self.reason.span(self.tcx);
|
|
||||||
span_err!(self.tcx.sess, span, E0563,
|
|
||||||
"cannot determine a type for this `impl Trait`: {}", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -593,20 +511,21 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Resolver<'cx, 'gcx, 'tcx> {
|
||||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
match self.infcx.fully_resolve(&t) {
|
match self.infcx.fully_resolve(&t) {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => {
|
Err(_) => {
|
||||||
debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable",
|
debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable",
|
||||||
t);
|
t);
|
||||||
self.report_error(e);
|
self.report_error(t);
|
||||||
self.tcx().types.err
|
self.tcx().types.err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME This should be carefully checked
|
||||||
|
// We could use `self.report_error` but it doesn't accept a ty::Region, right now.
|
||||||
fn fold_region(&mut self, r: &'tcx ty::Region) -> &'tcx ty::Region {
|
fn fold_region(&mut self, r: &'tcx ty::Region) -> &'tcx ty::Region {
|
||||||
match self.infcx.fully_resolve(&r) {
|
match self.infcx.fully_resolve(&r) {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
Err(e) => {
|
Err(_) => {
|
||||||
self.report_error(e);
|
|
||||||
self.tcx.mk_region(ty::ReStatic)
|
self.tcx.mk_region(ty::ReStatic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1351,50 +1351,6 @@ extern "rust-intrinsic" {
|
||||||
```
|
```
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
E0101: r##"
|
|
||||||
You hit this error because the compiler lacks the information to
|
|
||||||
determine a type for this expression. Erroneous code example:
|
|
||||||
|
|
||||||
```compile_fail,E0101
|
|
||||||
let x = |_| {}; // error: cannot determine a type for this expression
|
|
||||||
```
|
|
||||||
|
|
||||||
You have two possibilities to solve this situation:
|
|
||||||
|
|
||||||
* Give an explicit definition of the expression
|
|
||||||
* Infer the expression
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```
|
|
||||||
let x = |_ : u32| {}; // ok!
|
|
||||||
// or:
|
|
||||||
let x = |_| {};
|
|
||||||
x(0u32);
|
|
||||||
```
|
|
||||||
"##,
|
|
||||||
|
|
||||||
E0102: r##"
|
|
||||||
You hit this error because the compiler lacks the information to
|
|
||||||
determine the type of this variable. Erroneous code example:
|
|
||||||
|
|
||||||
```compile_fail,E0282
|
|
||||||
// could be an array of anything
|
|
||||||
let x = []; // error: cannot determine a type for this local variable
|
|
||||||
```
|
|
||||||
|
|
||||||
To solve this situation, constrain the type of the variable.
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```
|
|
||||||
#![allow(unused_variables)]
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let x: [u8; 0] = [];
|
|
||||||
}
|
|
||||||
```
|
|
||||||
"##,
|
|
||||||
|
|
||||||
E0107: r##"
|
E0107: r##"
|
||||||
This error means that an incorrect number of lifetime parameters were provided
|
This error means that an incorrect number of lifetime parameters were provided
|
||||||
for a type (like a struct or enum) or trait:
|
for a type (like a struct or enum) or trait:
|
||||||
|
|
@ -4146,8 +4102,6 @@ register_diagnostics! {
|
||||||
// E0068,
|
// E0068,
|
||||||
// E0085,
|
// E0085,
|
||||||
// E0086,
|
// E0086,
|
||||||
E0103, // @GuillaumeGomez: I was unable to get this error, try your best!
|
|
||||||
E0104,
|
|
||||||
// E0123,
|
// E0123,
|
||||||
// E0127,
|
// E0127,
|
||||||
// E0129,
|
// E0129,
|
||||||
|
|
@ -4164,7 +4118,7 @@ register_diagnostics! {
|
||||||
// E0188, // can not cast an immutable reference to a mutable pointer
|
// E0188, // can not cast an immutable reference to a mutable pointer
|
||||||
// E0189, // deprecated: can only cast a boxed pointer to a boxed object
|
// E0189, // deprecated: can only cast a boxed pointer to a boxed object
|
||||||
// E0190, // deprecated: can only cast a &-pointer to an &-object
|
// E0190, // deprecated: can only cast a &-pointer to an &-object
|
||||||
E0196, // cannot determine a type for this closure
|
E0196, // cannot determine a type for this closure // @cengizIO: this is no longer thrown. should I DELETE THIS?
|
||||||
E0203, // type parameter has more than one relaxed default bound,
|
E0203, // type parameter has more than one relaxed default bound,
|
||||||
// and only one is supported
|
// and only one is supported
|
||||||
E0208,
|
E0208,
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,5 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let (x,) = (vec![],);
|
let x = [];
|
||||||
}
|
}
|
||||||
10
src/test/ui/type-check/cannot_infer_local_or_array.stderr
Normal file
10
src/test/ui/type-check/cannot_infer_local_or_array.stderr
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/cannot_infer_local_or_array.rs:12:13
|
||||||
|
|
|
||||||
|
12 | let x = [];
|
||||||
|
| - ^^ cannot infer type for `_`
|
||||||
|
| |
|
||||||
|
| consider giving `x` a type
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0282]: type annotations needed
|
error[E0282]: type annotations needed
|
||||||
--> $DIR/issue-38812.rs:12:13
|
--> $DIR/cannot_infer_local_or_vec.rs:12:13
|
||||||
|
|
|
|
||||||
12 | let x = vec![];
|
12 | let x = vec![];
|
||||||
| - ^^^^^^ cannot infer type for `T`
|
| - ^^^^^^ cannot infer type for `T`
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||||
// file at the top-level directory of this distribution and at
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
|
@ -9,7 +9,5 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = |_| {};
|
let (x, ) = (vec![], );
|
||||||
//~^ ERROR E0101
|
|
||||||
//~| NOTE cannot resolve type of expression
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0282]: type annotations needed
|
error[E0282]: type annotations needed
|
||||||
--> $DIR/issue-38812-2.rs:12:17
|
--> $DIR/cannot_infer_local_or_vec_in_tuples.rs:12:18
|
||||||
|
|
|
|
||||||
12 | let (x,) = (vec![],);
|
12 | let (x, ) = (vec![], );
|
||||||
| ---- ^^^^^^ cannot infer type for `T`
|
| ----- ^^^^^^ cannot infer type for `T`
|
||||||
| |
|
| |
|
||||||
| consider giving a type to pattern
|
| consider giving a type to pattern
|
||||||
|
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||||
// file at the top-level directory of this distribution and at
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
|
@ -10,10 +10,6 @@
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
||||||
// Before these errors would ICE as "cat_expr Errd" because the errors
|
|
||||||
// were unknown when the bug was triggered.
|
|
||||||
|
|
||||||
fn unconstrained_type() {
|
fn unconstrained_type() {
|
||||||
[];
|
[];
|
||||||
//~^ ERROR cannot determine a type for this expression: unconstrained type
|
|
||||||
}
|
}
|
||||||
8
src/test/ui/type-check/issue-22897.stderr
Normal file
8
src/test/ui/type-check/issue-22897.stderr
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/issue-22897.rs:14:5
|
||||||
|
|
|
||||||
|
14 | [];
|
||||||
|
| ^^ cannot infer type for `[_; 0]`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||||
// file at the top-level directory of this distribution and at
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
|
@ -9,8 +9,5 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = [];
|
let x = |_| { };
|
||||||
//~^ ERROR type annotations needed
|
|
||||||
//~| NOTE consider giving `x` a type
|
|
||||||
//~| NOTE cannot infer type for `_`
|
|
||||||
}
|
}
|
||||||
8
src/test/ui/type-check/unknown_type_for_closure.stderr
Normal file
8
src/test/ui/type-check/unknown_type_for_closure.stderr
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/unknown_type_for_closure.rs:12:14
|
||||||
|
|
|
||||||
|
12 | let x = |_| { };
|
||||||
|
| ^ consider giving this closure parameter a type
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue