Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #51379

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
daa5b81
Issue #50974: Suboptimal error in case of duplicate `,` in struct con…
lambtowolf May 29, 2018
a66597d
Issue #50974: Change text of suggestion to be more direct
lambtowolf May 29, 2018
4558a62
Issue #50974: Adding tests
lambtowolf May 29, 2018
4b32ddd
Issue #50974: Adding issue number in the test
lambtowolf May 29, 2018
8e956e1
Fix when the help message is displayed
lambtowolf May 30, 2018
18580e2
Issue #50974: Fix compilation error and test
lambtowolf May 30, 2018
dcc4b16
When NLL has illegal move due to borrowed content, provide feedback a…
pnkfelix May 31, 2018
74002d1
Drive-by: Make assignment conflict tests in borrowck-vec-pattern-nest…
pnkfelix May 31, 2018
e99f5ec
Update the expected error output to reflect changes in this PR.
pnkfelix May 31, 2018
8f4a542
Accept `..` in incorrect position to avoid further errors
estebank May 29, 2018
cbc70a0
Improve diagnostics for incorrect `..` usage
estebank May 30, 2018
d66d35b
Account for comma in suggestion
estebank May 30, 2018
aa23aba
[fuchsia] Migrate from launchpad to fdio_spawn_etc
Jun 1, 2018
01559fb
add an explanatory comment for recovery behavior
nikomatsakis Jun 5, 2018
5c0d135
Refactor the const eval diagnostic API
oli-obk Jun 2, 2018
9cb47de
Referring to erroneous constants in promoteds must abort the build
oli-obk Jun 3, 2018
78d4886
Properly report transitive errors
oli-obk Jun 3, 2018
13a55e8
Satisfy the untiring tidy
oli-obk Jun 3, 2018
848080d
Remove unused IndexOutOfBounds variant
oli-obk Jun 5, 2018
5950496
Remove another unused error variant
oli-obk Jun 5, 2018
8a74be6
Add source information the const propagation of places
oli-obk Jun 5, 2018
14d08e5
Rebase fallout
oli-obk Jun 5, 2018
8e9a5e9
Rollup merge of #51184 - lambtowolf:master, r=nikomatsakis
Mark-Simulacrum Jun 5, 2018
8ec9f4c
Rollup merge of #51201 - estebank:dotdot, r=petrochenkov
Mark-Simulacrum Jun 5, 2018
26ad9e2
Rollup merge of #51247 - pnkfelix:issue-51190-report-type-moved-from-…
Mark-Simulacrum Jun 5, 2018
7d0d7ea
Rollup merge of #51316 - oli-obk:const_err, r=nikomatsakis
Mark-Simulacrum Jun 5, 2018
5f2de72
Rollup merge of #51359 - cramertj:fdio_spawn, r=sfackler
Mark-Simulacrum Jun 5, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ impl_stable_hash_for!(struct ::middle::const_val::ConstEvalErr<'tcx> {

impl_stable_hash_for!(struct ::middle::const_val::FrameInfo {
span,
lint_root,
location
});

Expand All @@ -523,21 +524,11 @@ for ::middle::const_val::ErrKind<'gcx> {
mem::discriminant(self).hash_stable(hcx, hasher);

match *self {
NonConstPath |
TypeckError |
CouldNotResolve |
CheckMatchError => {
// nothing to do
}
UnimplementedConstVal(s) => {
s.hash_stable(hcx, hasher);
}
IndexOutOfBounds { len, index } => {
len.hash_stable(hcx, hasher);
index.hash_stable(hcx, hasher);
}
LayoutError(ref layout_error) => {
layout_error.hash_stable(hcx, hasher);
}
Miri(ref err, ref trace) => {
err.hash_stable(hcx, hasher);
trace.hash_stable(hcx, hasher);
Expand Down Expand Up @@ -608,8 +599,8 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> {
RemainderByZero |
DivisionByZero |
GeneratorResumedAfterReturn |
GeneratorResumedAfterPanic |
ReferencedConstant => {}
GeneratorResumedAfterPanic => {}
ReferencedConstant(ref err) => err.hash_stable(hcx, hasher),
MachineError(ref err) => err.hash_stable(hcx, hasher),
FunctionPointerTyMismatch(a, b) => {
a.hash_stable(hcx, hasher);
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,9 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
f(self);
self.param_env = old_param_env;
}
pub fn current_lint_root(&self) -> ast::NodeId {
self.last_ast_node_with_lint_attrs
}
}

impl<'a, 'tcx> LayoutOf for &'a LateContext<'a, 'tcx> {
Expand Down
139 changes: 77 additions & 62 deletions src/librustc/middle/const_val.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
// except according to those terms.

use hir::def_id::DefId;
use ty::{self, TyCtxt, layout};
use ty;
use ty::subst::Substs;
use ty::maps::TyCtxtAt;
use mir::interpret::ConstValue;
use errors::DiagnosticBuilder;

use graphviz::IntoCow;
use syntax_pos::Span;
use syntax::ast;

use std::borrow::Cow;
use rustc_data_structures::sync::Lrc;
Expand All @@ -28,30 +30,26 @@ pub enum ConstVal<'tcx> {
Value(ConstValue<'tcx>),
}

#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ConstEvalErr<'tcx> {
pub span: Span,
pub kind: Lrc<ErrKind<'tcx>>,
}

#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum ErrKind<'tcx> {

NonConstPath,
UnimplementedConstVal(&'static str),
IndexOutOfBounds { len: u64, index: u64 },

LayoutError(layout::LayoutError<'tcx>),

CouldNotResolve,
TypeckError,
CheckMatchError,
Miri(::mir::interpret::EvalError<'tcx>, Vec<FrameInfo>),
}

#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct FrameInfo {
pub span: Span,
pub location: String,
pub lint_root: Option<ast::NodeId>,
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -83,81 +81,98 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
}

match *self.kind {
NonConstPath => simple!("non-constant path in constant expression"),
UnimplementedConstVal(what) =>
simple!("unimplemented constant expression: {}", what),
IndexOutOfBounds { len, index } => {
simple!("index out of bounds: the len is {} but the index is {}",
len, index)
}

LayoutError(ref err) => Simple(err.to_string().into_cow()),

CouldNotResolve => simple!("could not resolve"),
TypeckError => simple!("type-checking failed"),
CheckMatchError => simple!("match-checking failed"),
Miri(ref err, ref trace) => Backtrace(err, trace),
}
}

pub fn struct_error(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
primary_span: Span,
primary_kind: &str)
-> DiagnosticBuilder<'gcx>
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str)
-> Option<DiagnosticBuilder<'tcx>>
{
let mut diag = struct_error(tcx, self.span, "constant evaluation error");
self.note(tcx, primary_span, primary_kind, &mut diag);
diag
self.struct_generic(tcx, message, None, true)
}

pub fn note(&self,
_tcx: TyCtxt<'a, 'gcx, 'tcx>,
primary_span: Span,
primary_kind: &str,
diag: &mut DiagnosticBuilder)
{
match self.description() {
ConstEvalErrDescription::Simple(message) => {
diag.span_label(self.span, message);
}
ConstEvalErrDescription::Backtrace(miri, frames) => {
diag.span_label(self.span, format!("{}", miri));
for frame in frames {
diag.span_label(frame.span, format!("inside call to `{}`", frame.location));
}
}
pub fn report_as_error(&self,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str
) {
let err = self.struct_generic(tcx, message, None, true);
if let Some(mut err) = err {
err.emit();
}
}

if !primary_span.contains(self.span) {
diag.span_note(primary_span,
&format!("for {} here", primary_kind));
pub fn report_as_lint(&self,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str,
lint_root: ast::NodeId,
) {
let lint = self.struct_generic(
tcx,
message,
Some(lint_root),
false,
);
if let Some(mut lint) = lint {
lint.emit();
}
}

pub fn report(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
primary_span: Span,
primary_kind: &str)
{
match *self.kind {
ErrKind::TypeckError | ErrKind::CheckMatchError => return,
ErrKind::Miri(ref miri, _) => {
fn struct_generic(
&self,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str,
lint_root: Option<ast::NodeId>,
as_err: bool,
) -> Option<DiagnosticBuilder<'tcx>> {
let (msg, frames): (_, &[_]) = match *self.kind {
ErrKind::TypeckError | ErrKind::CheckMatchError => return None,
ErrKind::Miri(ref miri, ref frames) => {
match miri.kind {
::mir::interpret::EvalErrorKind::TypeckError |
::mir::interpret::EvalErrorKind::Layout(_) => return,
_ => {},
::mir::interpret::EvalErrorKind::Layout(_) => return None,
::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
inner.struct_generic(tcx, "referenced constant", lint_root, as_err)?.emit();
(miri.to_string(), frames)
},
_ => (miri.to_string(), frames),
}
}
_ => {}
_ => (self.description().into_oneline().to_string(), &[]),
};
trace!("reporting const eval failure at {:?}", self.span);
let mut err = if as_err {
struct_error(tcx, message)
} else {
let node_id = frames
.iter()
.rev()
.filter_map(|frame| frame.lint_root)
.next()
.or(lint_root)
.expect("some part of a failing const eval must be local");
tcx.struct_span_lint_node(
::rustc::lint::builtin::CONST_ERR,
node_id,
tcx.span,
message,
)
};
err.span_label(self.span, msg);
for FrameInfo { span, location, .. } in frames {
err.span_label(*span, format!("inside call to `{}`", location));
}
self.struct_error(tcx, primary_span, primary_kind).emit();
Some(err)
}
}

pub fn struct_error<'a, 'gcx, 'tcx>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
span: Span,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
msg: &str,
) -> DiagnosticBuilder<'gcx> {
struct_span_err!(tcx.sess, span, E0080, "{}", msg)
) -> DiagnosticBuilder<'tcx> {
struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
}
48 changes: 39 additions & 9 deletions src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{fmt, env};

use mir;
use middle::const_val::ConstEvalErr;
use ty::{FnSig, Ty, layout};
use ty::layout::{Size, Align};

Expand All @@ -10,21 +11,50 @@ use super::{

use backtrace::Backtrace;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
pub struct EvalError<'tcx> {
pub kind: EvalErrorKind<'tcx, u64>,
pub backtrace: Option<Backtrace>,
}

impl<'tcx> From<EvalErrorKind<'tcx, u64>> for EvalError<'tcx> {
fn from(kind: EvalErrorKind<'tcx, u64>) -> Self {
let backtrace = match env::var("MIRI_BACKTRACE") {
Ok(ref val) if !val.is_empty() => Some(Backtrace::new_unresolved()),
_ => None
};
match env::var("MIRI_BACKTRACE") {
Ok(ref val) if !val.is_empty() => {
let backtrace = Backtrace::new();

use std::fmt::Write;
let mut trace_text = "\n\nAn error occurred in miri:\n".to_string();
write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
if frame.symbols().is_empty() {
write!(trace_text, "{}: no symbols\n", i).unwrap();
}
for symbol in frame.symbols() {
write!(trace_text, "{}: ", i).unwrap();
if let Some(name) = symbol.name() {
write!(trace_text, "{}\n", name).unwrap();
} else {
write!(trace_text, "<unknown>\n").unwrap();
}
write!(trace_text, "\tat ").unwrap();
if let Some(file_path) = symbol.filename() {
write!(trace_text, "{}", file_path.display()).unwrap();
} else {
write!(trace_text, "<unknown_file>").unwrap();
}
if let Some(line) = symbol.lineno() {
write!(trace_text, ":{}\n", line).unwrap();
} else {
write!(trace_text, "\n").unwrap();
}
}
}
error!("{}", trace_text);
},
_ => {},
}
EvalError {
kind,
backtrace,
}
}
}
Expand Down Expand Up @@ -122,7 +152,7 @@ pub enum EvalErrorKind<'tcx, O> {
TypeckError,
/// Cannot compute this constant because it depends on another one
/// which already produced an error
ReferencedConstant,
ReferencedConstant(ConstEvalErr<'tcx>),
GeneratorResumedAfterReturn,
GeneratorResumedAfterPanic,
}
Expand Down Expand Up @@ -238,7 +268,7 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> {
"there were unresolved type arguments during trait selection",
TypeckError =>
"encountered constants with type errors, stopping evaluation",
ReferencedConstant =>
ReferencedConstant(_) =>
"referenced constant has errors",
Overflow(mir::BinOp::Add) => "attempt to add with overflow",
Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow",
Expand Down
9 changes: 6 additions & 3 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -827,10 +827,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}

ConstEvalFailure(ref err) => {
if let ::middle::const_val::ErrKind::TypeckError = *err.kind {
return;
match err.struct_error(
self.tcx.at(span),
"could not evaluate constant expression",
) {
Some(err) => err,
None => return,
}
err.struct_error(self.tcx, span, "constant expression")
}

Overflow => {
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,8 +534,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
} else {
Err(CodeSelectionError(ConstEvalFailure(ConstEvalErr {
span: obligation.cause.span,
kind: ErrKind::UnimplementedConstVal("could not resolve")
.into(),
kind: ErrKind::CouldNotResolve.into(),
})))
}
},
Expand Down
8 changes: 5 additions & 3 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2075,15 +2075,17 @@ impl<'a, 'gcx, 'tcx> AdtDef {
} else {
info!("invalid enum discriminant: {:#?}", val);
::middle::const_val::struct_error(
tcx,
tcx.def_span(expr_did),
tcx.at(tcx.def_span(expr_did)),
"constant evaluation of enum discriminant resulted in non-integer",
).emit();
None
}
}
Err(err) => {
err.report(tcx, tcx.def_span(expr_did), "enum discriminant");
err.report_as_error(
tcx.at(tcx.def_span(expr_did)),
"could not evaluate enum discriminant",
);
if !expr_did.is_local() {
span_bug!(tcx.def_span(expr_did),
"variant discriminant evaluation succeeded \
Expand Down
Loading