1
Fork 0

errooaaar~

This commit is contained in:
Ellen 2021-03-02 15:47:06 +00:00
parent d2731d8e93
commit f97e075e92
11 changed files with 146 additions and 113 deletions

View file

@ -13,7 +13,7 @@ use rustc_hir::def::DefKind;
use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::abstract_const::{Node, NodeId};
use rustc_middle::mir::abstract_const::{Node, NodeId, NotConstEvaluatable};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::mir::{self, Rvalue, StatementKind, TerminatorKind};
use rustc_middle::ty::subst::{Subst, SubstsRef};
@ -32,7 +32,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
substs: SubstsRef<'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span,
) -> Result<(), ErrorHandled> {
) -> Result<(), NotConstEvaluatable> {
debug!("is_const_evaluatable({:?}, {:?})", def, substs);
if infcx.tcx.features().const_evaluatable_checked {
let tcx = infcx.tcx;
@ -103,34 +103,12 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
match failure_kind {
FailureKind::MentionsInfer => {
return Err(ErrorHandled::TooGeneric);
return Err(NotConstEvaluatable::MentionsInfer);
}
FailureKind::MentionsParam => {
// FIXME(const_evaluatable_checked): Better error message.
let mut err =
infcx.tcx.sess.struct_span_err(span, "unconstrained generic constant");
let const_span = tcx.def_span(def.did);
// FIXME(const_evaluatable_checked): Update this suggestion once
// explicit const evaluatable bounds are implemented.
if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(const_span)
{
err.span_help(
tcx.def_span(def.did),
&format!("try adding a `where` bound using this expression: `where [u8; {}]: Sized`", snippet),
);
} else {
err.span_help(
const_span,
"consider adding a `where` bound for this expression",
);
}
err.emit();
return Err(ErrorHandled::Reported(ErrorReported));
}
FailureKind::Concrete => {
// Dealt with below by the same code which handles this
// without the feature gate.
return Err(NotConstEvaluatable::MentionsParam);
}
_ => (),
}
}
None => {
@ -181,33 +159,15 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
debug!(?concrete, "is_const_evaluatable");
match concrete {
Err(ErrorHandled::TooGeneric) if !substs.has_infer_types_or_consts() => {
// FIXME(const_evaluatable_checked): We really should move
// emitting this error message to fulfill instead. For
// now this is easier.
//
// This is not a problem without `const_evaluatable_checked` as
// all `ConstEvaluatable` predicates have to be fulfilled for compilation
// to succeed.
//
// @lcnr: We already emit an error for things like
// `fn test<const N: usize>() -> [0 - N]` eagerly here,
// so until we fix this I don't really care.
let mut err = infcx
.tcx
.sess
.struct_span_err(span, "constant expression depends on a generic parameter");
// FIXME(const_generics): we should suggest to the user how they can resolve this
// issue. However, this is currently not actually possible
// (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
//
// Note that with `feature(const_evaluatable_checked)` this case should not
// be reachable.
err.note("this may fail depending on what value the parameter takes");
err.emit();
Err(ErrorHandled::Reported(ErrorReported))
Err(NotConstEvaluatable::MentionsParam)
}
c => c.map(drop),
Err(ErrorHandled::TooGeneric) => Err(NotConstEvaluatable::MentionsInfer),
Err(ErrorHandled::Linted) => {
infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
Err(NotConstEvaluatable::Error(ErrorReported))
}
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
Ok(_) => Ok(()),
}
}

View file

@ -2,10 +2,10 @@ pub mod on_unimplemented;
pub mod suggestions;
use super::{
ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow,
PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
EvaluationResult, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes,
Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective,
OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, PredicateObligation,
SelectionContext, SelectionError, TraitNotObjectSafe,
};
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
@ -17,7 +17,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::intravisit::Visitor;
use rustc_hir::Node;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::mir::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::fold::TypeFolder;
use rustc_middle::ty::{
@ -738,21 +738,56 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let violations = self.tcx.object_safety_violations(did);
report_object_safety_error(self.tcx, span, did, violations)
}
ConstEvalFailure(ErrorHandled::TooGeneric) => {
bug!("too generic should have been handled in `is_const_evaluatable`");
SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => {
bug!(
"MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`"
)
}
// Already reported in the query.
ConstEvalFailure(ErrorHandled::Reported(ErrorReported)) => {
// FIXME(eddyb) remove this once `ErrorReported` becomes a proof token.
self.tcx.sess.delay_span_bug(span, "`ErrorReported` without an error");
return;
SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => {
if !self.tcx.features().const_evaluatable_checked {
let mut err = self.tcx.sess.struct_span_err(
span,
"constant expression depends on a generic parameter",
);
// FIXME(const_generics): we should suggest to the user how they can resolve this
// issue. However, this is currently not actually possible
// (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
//
// Note that with `feature(const_evaluatable_checked)` this case should not
// be reachable.
err.note("this may fail depending on what value the parameter takes");
err.emit();
return;
}
match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::ConstEvaluatable(def, _) => {
let mut err =
self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
let const_span = self.tcx.def_span(def.did);
match self.tcx.sess.source_map().span_to_snippet(const_span) {
Ok(snippet) => err.help(&format!(
"try adding a `where` bound using this expression: `where [(); {}]:`",
snippet
)),
_ => err.help("consider adding a `where` bound using this expression"),
};
err
}
_ => {
span_bug!(
span,
"unexpected non-ConstEvaluatable predicate, this should not be reachable"
)
}
}
}
// Already reported in the query, but only as a lint.
// This shouldn't actually happen for constants used in types, modulo
// bugs. The `delay_span_bug` here ensures it won't be ignored.
ConstEvalFailure(ErrorHandled::Linted) => {
self.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
// Already reported in the query.
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(ErrorReported)) => {
// FIXME(eddyb) remove this once `ErrorReported` becomes a proof token.
self.tcx.sess.delay_span_bug(span, "`ErrorReported` without an error");
return;
}

View file

@ -3,7 +3,8 @@ use rustc_data_structures::obligation_forest::ProcessResult;
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
use rustc_errors::ErrorReported;
use rustc_infer::traits::{TraitEngine, TraitEngineExt as _, TraitObligation};
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
use rustc_middle::mir::abstract_const::NotConstEvaluatable;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::subst::SubstsRef;
@ -18,7 +19,7 @@ use super::wf;
use super::CodeAmbiguity;
use super::CodeProjectionError;
use super::CodeSelectionError;
use super::{ConstEvalFailure, Unimplemented};
use super::Unimplemented;
use super::{FulfillmentError, FulfillmentErrorCode};
use super::{ObligationCause, PredicateObligation};
@ -498,14 +499,23 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
obligation.cause.span,
) {
Ok(()) => ProcessResult::Changed(vec![]),
Err(ErrorHandled::TooGeneric) => {
Err(NotConstEvaluatable::MentionsInfer) => {
pending_obligation.stalled_on.clear();
pending_obligation.stalled_on.extend(
substs.iter().filter_map(TyOrConstInferVar::maybe_from_generic_arg),
);
ProcessResult::Unchanged
}
Err(e) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(e))),
Err(NotConstEvaluatable::MentionsParam) => ProcessResult::Error(
CodeSelectionError(SelectionError::NotConstEvaluatable(
NotConstEvaluatable::MentionsParam,
)),
),
Err(NotConstEvaluatable::Error(e)) => {
ProcessResult::Error(CodeSelectionError(
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(e)),
))
}
}
}
@ -576,11 +586,11 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
}
}
(Err(ErrorHandled::Reported(ErrorReported)), _)
| (_, Err(ErrorHandled::Reported(ErrorReported))) => {
ProcessResult::Error(CodeSelectionError(ConstEvalFailure(
ErrorHandled::Reported(ErrorReported),
)))
}
| (_, Err(ErrorHandled::Reported(ErrorReported))) => ProcessResult::Error(
CodeSelectionError(SelectionError::NotConstEvaluatable(
NotConstEvaluatable::Error(ErrorReported),
)),
),
(Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => {
span_bug!(
obligation.cause.span(self.selcx.tcx()),

View file

@ -34,6 +34,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::Constness;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
use rustc_middle::mir::abstract_const::NotConstEvaluatable;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::fast_reject;
use rustc_middle::ty::print::with_no_trimmed_paths;
@ -547,7 +548,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.cause.span,
) {
Ok(()) => Ok(EvaluatedToOk),
Err(ErrorHandled::TooGeneric) => Ok(EvaluatedToAmbig),
Err(NotConstEvaluatable::MentionsInfer) => Ok(EvaluatedToAmbig),
Err(NotConstEvaluatable::MentionsParam) => Ok(EvaluatedToErr),
Err(_) => Ok(EvaluatedToErr),
}
}