Skip to content

Commit

Permalink
Make RFC 1214 warnings into errors, and rip out the "warn or err"
Browse files Browse the repository at this point in the history
associated machinery. Future such attempts should go through lints
anyhow.

There is a fair amount of fallout in the compile-fail tests, as WF
checking now occurs earlier in the process.
  • Loading branch information
nikomatsakis committed Dec 18, 2015
1 parent de62f9d commit dbf994b
Show file tree
Hide file tree
Showing 88 changed files with 291 additions and 1,187 deletions.
31 changes: 6 additions & 25 deletions src/librustc/middle/infer/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,11 +578,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
// where the error was detected. But that span is not readily
// accessible.

let is_warning = match origin {
infer::RFC1214Subregion(_) => true,
_ => false,
};

let labeled_user_string = match bound_kind {
GenericKind::Param(ref p) =>
format!("the parameter type `{}`", p),
Expand All @@ -593,8 +588,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
match sub {
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
// Does the required lifetime have a nice name we can print?
span_err_or_warn!(
is_warning, self.tcx.sess, origin.span(), E0309,
span_err!(
self.tcx.sess, origin.span(), E0309,
"{} may not live long enough", labeled_user_string);
self.tcx.sess.fileline_help(
origin.span(),
Expand All @@ -606,8 +601,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {

ty::ReStatic => {
// Does the required lifetime have a nice name we can print?
span_err_or_warn!(
is_warning, self.tcx.sess, origin.span(), E0310,
span_err!(
self.tcx.sess, origin.span(), E0310,
"{} may not live long enough", labeled_user_string);
self.tcx.sess.fileline_help(
origin.span(),
Expand All @@ -618,8 +613,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {

_ => {
// If not, be less specific.
span_err_or_warn!(
is_warning, self.tcx.sess, origin.span(), E0311,
span_err!(
self.tcx.sess, origin.span(), E0311,
"{} may not live long enough",
labeled_user_string);
self.tcx.sess.fileline_help(
Expand All @@ -634,10 +629,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
}
}

if is_warning {
self.tcx.sess.note_rfc_1214(origin.span());
}

self.note_region_origin(&origin);
}

Expand All @@ -646,13 +637,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
sub: Region,
sup: Region) {
match origin {
infer::RFC1214Subregion(ref suborigin) => {
// Ideally, this would be a warning, but it doesn't
// seem to come up in practice, since the changes from
// RFC1214 mostly trigger errors in type definitions
// that don't wind up coming down this path.
self.report_concrete_failure((**suborigin).clone(), sub, sup);
}
infer::Subtype(trace) => {
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
self.report_and_explain_type_error(trace, &terr);
Expand Down Expand Up @@ -1599,9 +1583,6 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {

fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
match *origin {
infer::RFC1214Subregion(ref suborigin) => {
self.note_region_origin(suborigin);
}
infer::Subtype(ref trace) => {
let desc = match trace.origin {
TypeOrigin::Misc(_) => {
Expand Down
7 changes: 0 additions & 7 deletions src/librustc/middle/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ use middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_data_structures::unify::{self, UnificationTable};
use std::cell::{RefCell, Ref};
use std::fmt;
use std::rc::Rc;
use syntax::ast;
use syntax::codemap;
use syntax::codemap::{Span, DUMMY_SP};
Expand Down Expand Up @@ -198,11 +197,6 @@ pub struct TypeTrace<'tcx> {
/// See `error_reporting.rs` for more details
#[derive(Clone, Debug)]
pub enum SubregionOrigin<'tcx> {
// Marker to indicate a constraint that only arises due to new
// provisions from RFC 1214. This will result in a warning, not an
// error.
RFC1214Subregion(Rc<SubregionOrigin<'tcx>>),

// Arose from a subtyping relation
Subtype(TypeTrace<'tcx>),

Expand Down Expand Up @@ -1568,7 +1562,6 @@ impl TypeOrigin {
impl<'tcx> SubregionOrigin<'tcx> {
pub fn span(&self) -> Span {
match *self {
RFC1214Subregion(ref a) => a.span(),
Subtype(ref a) => a.span(),
InfStackClosure(a) => a,
InvokeClosure(a) => a,
Expand Down
74 changes: 30 additions & 44 deletions src/librustc/middle/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ use syntax::attr::{AttributeMethods, AttrMetaMethods};

#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TraitErrorKey<'tcx> {
is_warning: bool,
span: Span,
predicate: ty::Predicate<'tcx>
}
Expand All @@ -47,7 +46,6 @@ impl<'tcx> TraitErrorKey<'tcx> {
let predicate =
infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
TraitErrorKey {
is_warning: is_warning(&e.obligation),
span: e.obligation.cause.span,
predicate: infcx.tcx.erase_regions(&predicate)
}
Expand Down Expand Up @@ -83,10 +81,6 @@ fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
}
}

fn is_warning<T>(obligation: &Obligation<T>) -> bool {
obligation.cause.code.is_rfc1214()
}

pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
obligation: &PredicateObligation<'tcx>,
error: &MismatchedProjectionTypes<'tcx>)
Expand All @@ -100,8 +94,8 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
// then $X will be unified with TyError, but the error still needs to be
// reported.
if !infcx.tcx.sess.has_errors() || !predicate.references_error() {
span_err_or_warn!(
is_warning(obligation), infcx.tcx.sess, obligation.cause.span, E0271,
span_err!(
infcx.tcx.sess, obligation.cause.span, E0271,
"type mismatch resolving `{}`: {}",
predicate,
error.err);
Expand Down Expand Up @@ -208,12 +202,11 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
obligation: &PredicateObligation<'tcx>,
error: &SelectionError<'tcx>)
{
let is_warning = is_warning(obligation);
match *error {
SelectionError::Unimplemented => {
if let ObligationCauseCode::CompareImplMethodObligation = obligation.cause.code {
span_err_or_warn!(
is_warning, infcx.tcx.sess, obligation.cause.span, E0276,
span_err!(
infcx.tcx.sess, obligation.cause.span, E0276,
"the requirement `{}` appears on the impl \
method but not on the corresponding trait method",
obligation.predicate);
Expand All @@ -225,8 +218,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,

if !infcx.tcx.sess.has_errors() || !trait_predicate.references_error() {
let trait_ref = trait_predicate.to_poly_trait_ref();
span_err_or_warn!(
is_warning, infcx.tcx.sess, obligation.cause.span, E0277,
span_err!(
infcx.tcx.sess, obligation.cause.span, E0277,
"the trait `{}` is not implemented for the type `{}`",
trait_ref, trait_ref.self_ty());

Expand All @@ -245,8 +238,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
let predicate = infcx.resolve_type_vars_if_possible(predicate);
let err = infcx.equality_predicate(obligation.cause.span,
&predicate).err().unwrap();
span_err_or_warn!(
is_warning, infcx.tcx.sess, obligation.cause.span, E0278,
span_err!(
infcx.tcx.sess, obligation.cause.span, E0278,
"the requirement `{}` is not satisfied (`{}`)",
predicate,
err);
Expand All @@ -257,8 +250,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
let predicate = infcx.resolve_type_vars_if_possible(predicate);
let err = infcx.region_outlives_predicate(obligation.cause.span,
&predicate).err().unwrap();
span_err_or_warn!(
is_warning, infcx.tcx.sess, obligation.cause.span, E0279,
span_err!(
infcx.tcx.sess, obligation.cause.span, E0279,
"the requirement `{}` is not satisfied (`{}`)",
predicate,
err);
Expand All @@ -268,8 +261,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
let predicate =
infcx.resolve_type_vars_if_possible(&obligation.predicate);
span_err_or_warn!(
is_warning, infcx.tcx.sess, obligation.cause.span, E0280,
span_err!(
infcx.tcx.sess, obligation.cause.span, E0280,
"the requirement `{}` is not satisfied",
predicate);
note_obligation_cause(infcx, obligation);
Expand All @@ -281,8 +274,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
report_object_safety_error(infcx.tcx,
obligation.cause.span,
trait_def_id,
violations,
is_warning);
violations);
note_obligation_cause(infcx, obligation);
}

Expand All @@ -304,8 +296,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
if !actual_trait_ref.self_ty().references_error() {
span_err_or_warn!(
is_warning, infcx.tcx.sess, obligation.cause.span, E0281,
span_err!(
infcx.tcx.sess, obligation.cause.span, E0281,
"type mismatch: the type `{}` implements the trait `{}`, \
but the trait `{}` is required ({})",
expected_trait_ref.self_ty(),
Expand All @@ -318,8 +310,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,

TraitNotObjectSafe(did) => {
let violations = object_safety_violations(infcx.tcx, did);
report_object_safety_error(infcx.tcx, obligation.cause.span, did,
violations, is_warning);
report_object_safety_error(infcx.tcx, obligation.cause.span, did, violations);
note_obligation_cause(infcx, obligation);
}
}
Expand All @@ -328,11 +319,10 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
span: Span,
trait_def_id: DefId,
violations: Vec<ObjectSafetyViolation>,
is_warning: bool)
violations: Vec<ObjectSafetyViolation>)
{
span_err_or_warn!(
is_warning, tcx.sess, span, E0038,
span_err!(
tcx.sess, span, E0038,
"the trait `{}` cannot be made into an object",
tcx.item_path_str(trait_def_id));

Expand Down Expand Up @@ -402,7 +392,17 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
let self_ty = trait_ref.self_ty();
let all_types = &trait_ref.substs().types;
if all_types.references_error() {
} else if all_types.needs_infer() {
} else {
// Typically, this ambiguity should only happen if
// there are unresolved type inference variables
// (otherwise it would suggest a coherence
// failure). But given #21974 that is not necessarily
// the case -- we can have multiple where clauses that
// are only distinguished by a region, which results
// in an ambiguity even when all types are fully
// known, since we don't dispatch based on region
// relationships.

// This is kind of a hack: it frequently happens that some earlier
// error prevents types from being fully inferred, and then we get
// a bunch of uninteresting errors saying something like "<generic
Expand Down Expand Up @@ -430,16 +430,6 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
note_obligation_cause(infcx, obligation);
}
}
} else if !infcx.tcx.sess.has_errors() {
// Ambiguity. Coherence should have reported an error.
infcx.tcx.sess.span_bug(
obligation.cause.span,
&format!(
"coherence failed to report ambiguity: \
cannot locate the impl of the trait `{}` for \
the type `{}`",
trait_ref,
self_ty));
}
}

Expand Down Expand Up @@ -491,10 +481,6 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
let tcx = infcx.tcx;
match *cause_code {
ObligationCauseCode::MiscObligation => { }
ObligationCauseCode::RFC1214(ref subcode) => {
tcx.sess.note_rfc_1214(cause_span);
note_obligation_cause_code(infcx, predicate, cause_span, subcode);
}
ObligationCauseCode::SliceOrArrayElem => {
tcx.sess.fileline_note(
cause_span,
Expand Down
33 changes: 10 additions & 23 deletions src/librustc/middle/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@ use super::CodeSelectionError;
use super::is_object_safe;
use super::FulfillmentError;
use super::ObligationCause;
use super::ObligationCauseCode;
use super::PredicateObligation;
use super::project;
use super::RFC1214Warning;
use super::select::SelectionContext;
use super::Unimplemented;
use super::util::predicate_for_builtin_bound;

pub struct FulfilledPredicates<'tcx> {
set: FnvHashSet<(RFC1214Warning, ty::Predicate<'tcx>)>
set: FnvHashSet<ty::Predicate<'tcx>>
}

/// The fulfillment context is used to drive trait resolution. It
Expand Down Expand Up @@ -194,9 +192,7 @@ impl<'tcx> FulfillmentContext<'tcx> {

assert!(!obligation.has_escaping_regions());

let w = RFC1214Warning(obligation.cause.code.is_rfc1214());

if self.is_duplicate_or_add(infcx.tcx, w, &obligation.predicate) {
if self.is_duplicate_or_add(infcx.tcx, &obligation.predicate) {
debug!("register_predicate({:?}) -- already seen, skip", obligation);
return;
}
Expand Down Expand Up @@ -261,7 +257,6 @@ impl<'tcx> FulfillmentContext<'tcx> {

fn is_duplicate_or_add(&mut self,
tcx: &ty::ctxt<'tcx>,
w: RFC1214Warning,
predicate: &ty::Predicate<'tcx>)
-> bool {
// This is a kind of dirty hack to allow us to avoid "rederiving"
Expand All @@ -276,12 +271,10 @@ impl<'tcx> FulfillmentContext<'tcx> {
// evaluating the 'nested obligations'. This cache lets us
// skip those.

let will_warn_due_to_rfc1214 = w.0;
let errors_will_be_reported = self.errors_will_be_reported && !will_warn_due_to_rfc1214;
if errors_will_be_reported && predicate.is_global() {
tcx.fulfilled_predicates.borrow_mut().is_duplicate_or_add(w, predicate)
if self.errors_will_be_reported && predicate.is_global() {
tcx.fulfilled_predicates.borrow_mut().is_duplicate_or_add(predicate)
} else {
self.duplicate_set.is_duplicate_or_add(w, predicate)
self.duplicate_set.is_duplicate_or_add(predicate)
}
}

Expand Down Expand Up @@ -496,12 +489,8 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
}

ty::Predicate::WellFormed(ty) => {
let rfc1214 = match obligation.cause.code {
ObligationCauseCode::RFC1214(_) => true,
_ => false,
};
match ty::wf::obligations(selcx.infcx(), obligation.cause.body_id,
ty, obligation.cause.span, rfc1214) {
ty, obligation.cause.span) {
Some(obligations) => {
new_obligations.extend(obligations);
true
Expand Down Expand Up @@ -539,13 +528,11 @@ impl<'tcx> FulfilledPredicates<'tcx> {
}
}

pub fn is_duplicate(&self, w: RFC1214Warning, p: &ty::Predicate<'tcx>) -> bool {
let key = (w, p.clone());
self.set.contains(&key)
pub fn is_duplicate(&self, key: &ty::Predicate<'tcx>) -> bool {
self.set.contains(key)
}

fn is_duplicate_or_add(&mut self, w: RFC1214Warning, p: &ty::Predicate<'tcx>) -> bool {
let key = (w, p.clone());
!self.set.insert(key)
fn is_duplicate_or_add(&mut self, key: &ty::Predicate<'tcx>) -> bool {
!self.set.insert(key.clone())
}
}
Loading

0 comments on commit dbf994b

Please sign in to comment.