use hir::def_id::DefId;
use middle::region;
use traits::{ObligationCause, ObligationCauseCode};
-use ty::{self, Region, Ty, TyCtxt, TypeFoldable};
+use ty::{self, Region, Ty, TyCtxt, TypeFoldable, TypeVariants};
use ty::error::TypeError;
use syntax::ast::DUMMY_NODE_ID;
use syntax_pos::{Pos, Span};
errors: &Vec<RegionResolutionError<'tcx>>) {
debug!("report_region_errors(): {} errors to start", errors.len());
+ if self.tcx.sess.opts.debugging_opts.nll {
+ for error in errors {
+ match *error {
+ RegionResolutionError::ConcreteFailure(ref origin, ..) |
+ RegionResolutionError::GenericBoundFailure(ref origin, ..) => {
+ self.tcx.sess.span_warn(
+ origin.span(),
+ "not reporting region error due to -Znll");
+ }
+
+ RegionResolutionError::SubSupConflict(ref rvo, ..) => {
+ self.tcx.sess.span_warn(
+ rvo.span(),
+ "not reporting region error due to -Znll");
+ }
+ }
+ }
+
+ return;
+ }
+
// try to pre-process the errors, which will group some of them
// together into a `ProcessedErrors` group:
let errors = self.process_errors(errors);
values: Option<ValuePairs<'tcx>>,
terr: &TypeError<'tcx>)
{
- let (expected_found, is_simple_error) = match values {
- None => (None, false),
+ let (expected_found, exp_found, is_simple_error) = match values {
+ None => (None, None, false),
Some(values) => {
- let is_simple_error = match values {
+ let (is_simple_error, exp_found) = match values {
ValuePairs::Types(exp_found) => {
- exp_found.expected.is_primitive() && exp_found.found.is_primitive()
+ let is_simple_err = exp_found.expected.is_primitive()
+ && exp_found.found.is_primitive();
+
+ (is_simple_err, Some(exp_found))
}
- _ => false,
+ _ => (false, None),
};
let vals = match self.values_str(&values) {
Some((expected, found)) => Some((expected, found)),
return
}
};
- (vals, is_simple_error)
+ (vals, exp_found, is_simple_error)
}
};
let span = cause.span;
+ diag.span_label(span, terr.to_string());
+ if let Some((sp, msg)) = secondary_span {
+ diag.span_label(sp, msg);
+ }
+
if let Some((expected, found)) = expected_found {
match (terr, is_simple_error, expected == found) {
(&TypeError::Sorts(ref values), false, true) => {
&format!(" ({})", values.expected.sort_string(self.tcx)),
&format!(" ({})", values.found.sort_string(self.tcx)));
}
- (_, false, _) => {
+ (_, false, _) => {
+ if let Some(exp_found) = exp_found {
+ let (def_id, ret_ty) = match exp_found.found.sty {
+ TypeVariants::TyFnDef(def, _) => {
+ (Some(def), Some(self.tcx.fn_sig(def).output()))
+ }
+ _ => (None, None)
+ };
+
+ let exp_is_struct = match exp_found.expected.sty {
+ TypeVariants::TyAdt(def, _) => def.is_struct(),
+ _ => false
+ };
+
+ if let (Some(def_id), Some(ret_ty)) = (def_id, ret_ty) {
+ if exp_is_struct && exp_found.expected == ret_ty.0 {
+ let message = format!(
+ "did you mean `{}(/* fields */)`?",
+ self.tcx.item_path_str(def_id)
+ );
+ diag.span_label(cause.span, message);
+ }
+ }
+ }
+
diag.note_expected_found(&"type", expected, found);
}
_ => (),
}
}
- diag.span_label(span, terr.to_string());
- if let Some((sp, msg)) = secondary_span {
- diag.span_label(sp, msg);
- }
-
self.note_error_origin(diag, &cause);
self.check_and_note_conflicting_crates(diag, terr, span);
self.tcx.note_and_explain_type_err(diag, terr, span);
fn visit_ty(&mut self,
ty: & $($mutability)* Ty<'tcx>,
- _: Lookup) {
+ _: TyContext) {
self.super_ty(ty);
}
}
fn visit_local_decl(&mut self,
+ local: Local,
local_decl: & $($mutability)* LocalDecl<'tcx>) {
- self.super_local_decl(local_decl);
+ self.super_local_decl(local, local_decl);
}
fn visit_local(&mut self,
self.visit_visibility_scope_data(scope);
}
- let lookup = Lookup::Src(SourceInfo {
+ let lookup = TyContext::SourceInfo(SourceInfo {
span: mir.span,
scope: ARGUMENT_VISIBILITY_SCOPE,
});
self.visit_ty(&$($mutability)* mir.return_ty, lookup);
- for local_decl in &$($mutability)* mir.local_decls {
- self.visit_local_decl(local_decl);
+ for local in mir.local_decls.indices() {
+ self.visit_local_decl(local, & $($mutability)* mir.local_decls[local]);
}
self.visit_span(&$($mutability)* mir.span);
for operand in lvalues {
self.visit_lvalue(& $($mutability)* operand.lval,
LvalueContext::Validate, location);
- self.visit_ty(& $($mutability)* operand.ty, Lookup::Loc(location));
+ self.visit_ty(& $($mutability)* operand.ty,
+ TyContext::Location(location));
}
}
StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
ref values,
ref targets } => {
self.visit_operand(discr, source_location);
- self.visit_ty(switch_ty, Lookup::Loc(source_location));
+ self.visit_ty(switch_ty, TyContext::Location(source_location));
for value in &values[..] {
self.visit_const_int(value, source_location);
}
self.visit_operand(value, source_location);
self.visit_branch(block, resume);
drop.map(|t| self.visit_branch(block, t));
+
}
+ TerminatorKind::FalseEdges { real_target, ref imaginary_targets } => {
+ self.visit_branch(block, real_target);
+ for target in imaginary_targets {
+ self.visit_branch(block, *target);
+ }
+ }
}
}
ref $($mutability)* operand,
ref $($mutability)* ty) => {
self.visit_operand(operand, location);
- self.visit_ty(ty, Lookup::Loc(location));
+ self.visit_ty(ty, TyContext::Location(location));
}
Rvalue::BinaryOp(_bin_op,
}
Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
- self.visit_ty(ty, Lookup::Loc(location));
+ self.visit_ty(ty, TyContext::Location(location));
}
Rvalue::Aggregate(ref $($mutability)* kind,
let kind = &$($mutability)* **kind;
match *kind {
AggregateKind::Array(ref $($mutability)* ty) => {
- self.visit_ty(ty, Lookup::Loc(location));
+ self.visit_ty(ty, TyContext::Location(location));
}
AggregateKind::Tuple => {
}
ref $($mutability)* ty,
} = *static_;
self.visit_def_id(def_id, location);
- self.visit_ty(ty, Lookup::Loc(location));
+ self.visit_ty(ty, TyContext::Location(location));
}
fn super_projection(&mut self,
ProjectionElem::Subslice { from: _, to: _ } => {
}
ProjectionElem::Field(_field, ref $($mutability)* ty) => {
- self.visit_ty(ty, Lookup::Loc(location));
+ self.visit_ty(ty, TyContext::Location(location));
}
ProjectionElem::Index(ref $($mutability)* local) => {
self.visit_local(local, LvalueContext::Consume, location);
}
fn super_local_decl(&mut self,
+ local: Local,
local_decl: & $($mutability)* LocalDecl<'tcx>) {
let LocalDecl {
mutability: _,
is_user_variable: _,
} = *local_decl;
- self.visit_ty(ty, Lookup::Src(*source_info));
+ self.visit_ty(ty, TyContext::LocalDecl {
+ local,
+ source_info: *source_info,
+ });
self.visit_source_info(source_info);
self.visit_visibility_scope(lexical_scope);
}
} = *constant;
self.visit_span(span);
- self.visit_ty(ty, Lookup::Loc(location));
+ self.visit_ty(ty, TyContext::Location(location));
self.visit_literal(literal, location);
}
make_mir_visitor!(Visitor,);
make_mir_visitor!(MutVisitor,mut);
+ /// Extra information passed to `visit_ty` and friends to give context
+ /// about where the type etc appears.
#[derive(Copy, Clone, Debug)]
- pub enum Lookup {
- Loc(Location),
- Src(SourceInfo),
+ pub enum TyContext {
+ LocalDecl {
+ /// The index of the local variable we are visiting.
+ local: Local,
+
+ /// The source location where this local variable was declared.
+ source_info: SourceInfo,
+ },
+
+ Location(Location),
+
+ SourceInfo(SourceInfo),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
self.sanitize_type(rvalue, rval_ty);
}
- fn visit_local_decl(&mut self, local_decl: &LocalDecl<'tcx>) {
- self.super_local_decl(local_decl);
+ fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
+ self.super_local_decl(local, local_decl);
self.sanitize_type(local_decl, local_decl.ty);
}
TerminatorKind::Return |
TerminatorKind::GeneratorDrop |
TerminatorKind::Unreachable |
- TerminatorKind::Drop { .. } => {
+ TerminatorKind::Drop { .. } |
+ TerminatorKind::FalseEdges { .. } => {
// no checks needed for these
}
self.assert_iscleanup(mir, block, cleanup, true);
}
}
+ TerminatorKind::FalseEdges { real_target, ref imaginary_targets } => {
+ self.assert_iscleanup(mir, block, real_target, is_cleanup);
+ for target in imaginary_targets {
+ self.assert_iscleanup(mir, block, *target, is_cleanup);
+ }
+ }
}
}
use rustc_const_math::{ConstUsize};
use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
- use rustc::mir::{Constant, Literal, Location, LocalDecl};
+ use rustc::mir::{Constant, Literal, Location, Local, LocalDecl};
use rustc::mir::{Lvalue, LvalueElem, LvalueProjection};
use rustc::mir::{Mir, Operand, ProjectionElem};
use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
TerminatorKind::Assert { .. } => "TerminatorKind::Assert",
TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop",
TerminatorKind::Yield { .. } => "TerminatorKind::Yield",
+ TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges",
}, kind);
self.super_terminator_kind(block, kind, location);
}
}
fn visit_local_decl(&mut self,
+ local: Local,
local_decl: &LocalDecl<'tcx>) {
self.record("LocalDecl", local_decl);
- self.super_local_decl(local_decl);
+ self.super_local_decl(local, local_decl);
}
fn visit_visibility_scope(&mut self,