Skip to content

Commit

Permalink
Auto merge of rust-lang#34982 - arielb1:bad-tuples-and-objects, r=nik…
Browse files Browse the repository at this point in the history
…omatsakis

Turn the RFC1592 warnings into hard errors

The warnings have already reached stable, and I want to improve the trait error reporting code.

Turning warnings into errors, this is obviously a [breaking-change].

r? @nikomatsakis

cc @rust-lang/compiler
  • Loading branch information
bors authored Sep 1, 2016
2 parents b2799a5 + 7b92d05 commit 147371f
Show file tree
Hide file tree
Showing 28 changed files with 50 additions and 314 deletions.
14 changes: 0 additions & 14 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,18 +186,6 @@ declare_lint! {
"detects super or self keywords at the beginning of global path"
}

declare_lint! {
pub UNSIZED_IN_TUPLE,
Warn,
"unsized types in the interior of a tuple were erroneously allowed"
}

declare_lint! {
pub OBJECT_UNSAFE_FRAGMENT,
Warn,
"object-unsafe non-principal fragments in object types were erroneously allowed"
}

declare_lint! {
pub LIFETIME_UNDERSCORE,
Warn,
Expand Down Expand Up @@ -239,8 +227,6 @@ impl LintPass for HardwiredLints {
OVERLAPPING_INHERENT_IMPLS,
RENAMED_AND_REMOVED_LINTS,
SUPER_OR_SELF_IN_GLOBAL_PATH,
UNSIZED_IN_TUPLE,
OBJECT_UNSAFE_FRAGMENT,
HR_LIFETIME_IN_ASSOC_TYPE,
LIFETIME_UNDERSCORE
)
Expand Down
1 change: 0 additions & 1 deletion src/librustc/middle/free_region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ impl FreeRegionMap {
match *predicate {
ty::Predicate::Projection(..) |
ty::Predicate::Trait(..) |
ty::Predicate::Rfc1592(..) |
ty::Predicate::Equate(..) |
ty::Predicate::WellFormed(..) |
ty::Predicate::ObjectSafe(..) |
Expand Down
122 changes: 25 additions & 97 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,50 +36,37 @@ use util::nodemap::{FnvHashMap, FnvHashSet};

use std::cmp;
use std::fmt;
use syntax::ast;
use syntax_pos::Span;
use errors::DiagnosticBuilder;

#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TraitErrorKey<'tcx> {
span: Span,
warning_node_id: Option<ast::NodeId>,
predicate: ty::Predicate<'tcx>
}

impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
fn from_error(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
e: &FulfillmentError<'tcx>,
warning_node_id: Option<ast::NodeId>) -> Self {
e: &FulfillmentError<'tcx>) -> Self {
let predicate =
infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
TraitErrorKey {
span: e.obligation.cause.span,
predicate: infcx.tcx.erase_regions(&predicate),
warning_node_id: warning_node_id
predicate: infcx.tcx.erase_regions(&predicate)
}
}
}

impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
pub fn report_fulfillment_errors(&self, errors: &Vec<FulfillmentError<'tcx>>) {
for error in errors {
self.report_fulfillment_error(error, None);
}
}

pub fn report_fulfillment_errors_as_warnings(&self,
errors: &Vec<FulfillmentError<'tcx>>,
node_id: ast::NodeId) {
for error in errors {
self.report_fulfillment_error(error, Some(node_id));
self.report_fulfillment_error(error);
}
}

fn report_fulfillment_error(&self,
error: &FulfillmentError<'tcx>,
warning_node_id: Option<ast::NodeId>) {
let error_key = TraitErrorKey::from_error(self, error, warning_node_id);
error: &FulfillmentError<'tcx>) {
let error_key = TraitErrorKey::from_error(self, error);
debug!("report_fulfillment_errors({:?}) - key={:?}",
error, error_key);
if !self.reported_trait_errors.borrow_mut().insert(error_key) {
Expand All @@ -88,10 +75,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
match error.code {
FulfillmentErrorCode::CodeSelectionError(ref e) => {
self.report_selection_error(&error.obligation, e, warning_node_id);
self.report_selection_error(&error.obligation, e);
}
FulfillmentErrorCode::CodeProjectionError(ref e) => {
self.report_projection_error(&error.obligation, e, warning_node_id);
self.report_projection_error(&error.obligation, e);
}
FulfillmentErrorCode::CodeAmbiguity => {
self.maybe_report_ambiguity(&error.obligation);
Expand All @@ -101,25 +88,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {

fn report_projection_error(&self,
obligation: &PredicateObligation<'tcx>,
error: &MismatchedProjectionTypes<'tcx>,
warning_node_id: Option<ast::NodeId>)
error: &MismatchedProjectionTypes<'tcx>)
{
let predicate =
self.resolve_type_vars_if_possible(&obligation.predicate);

if predicate.references_error() {
return
}
if let Some(warning_node_id) = warning_node_id {
self.tcx.sess.add_lint(
::lint::builtin::UNSIZED_IN_TUPLE,
warning_node_id,
obligation.cause.span,
format!("type mismatch resolving `{}`: {}",
predicate,
error.err));
return
}

self.probe(|_| {
let origin = TypeOrigin::Misc(obligation.cause.span);
let err_buf;
Expand Down Expand Up @@ -442,8 +419,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {

pub fn report_selection_error(&self,
obligation: &PredicateObligation<'tcx>,
error: &SelectionError<'tcx>,
warning_node_id: Option<ast::NodeId>)
error: &SelectionError<'tcx>)
{
let span = obligation.cause.span;
let mut err = match *error {
Expand All @@ -466,16 +442,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
} else {
let trait_ref = trait_predicate.to_poly_trait_ref();

if let Some(warning_node_id) = warning_node_id {
self.tcx.sess.add_lint(
::lint::builtin::UNSIZED_IN_TUPLE,
warning_node_id,
obligation.cause.span,
format!("the trait bound `{}` is not satisfied",
trait_ref.to_predicate()));
return;
}

let mut err = struct_span_err!(self.tcx.sess, span, E0277,
"the trait bound `{}` is not satisfied",
trait_ref.to_predicate());
Expand Down Expand Up @@ -541,15 +507,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {

ty::Predicate::ObjectSafe(trait_def_id) => {
let violations = self.tcx.object_safety_violations(trait_def_id);
let err = self.tcx.report_object_safety_error(span,
trait_def_id,
warning_node_id,
violations);
if let Some(err) = err {
err
} else {
return;
}
self.tcx.report_object_safety_error(span,
trait_def_id,
violations)
}

ty::Predicate::ClosureKind(closure_def_id, kind) => {
Expand Down Expand Up @@ -577,13 +537,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// (which may fail).
span_bug!(span, "WF predicate not satisfied for {:?}", ty);
}

ty::Predicate::Rfc1592(ref data) => {
span_bug!(
obligation.cause.span,
"RFC1592 predicate not satisfied for {:?}",
data);
}
}
}
}
Expand All @@ -605,14 +558,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {

TraitNotObjectSafe(did) => {
let violations = self.tcx.object_safety_violations(did);
let err = self.tcx.report_object_safety_error(span, did,
warning_node_id,
violations);
if let Some(err) = err {
err
} else {
return;
}
self.tcx.report_object_safety_error(span, did,
violations)
}
};
self.note_obligation_cause(&mut err, obligation);
Expand Down Expand Up @@ -640,24 +587,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn report_object_safety_error(self,
span: Span,
trait_def_id: DefId,
warning_node_id: Option<ast::NodeId>,
violations: Vec<ObjectSafetyViolation>)
-> Option<DiagnosticBuilder<'tcx>>
-> DiagnosticBuilder<'tcx>
{
let mut err = match warning_node_id {
Some(_) => None,
None => {
let trait_str = self.item_path_str(trait_def_id);
let mut db = struct_span_err!(
self.sess, span, E0038,
"the trait `{}` cannot be made into an object",
trait_str);
db.span_label(span,
&format!("the trait `{}` cannot be made \
into an object", trait_str));
Some(db)
}
};
let trait_str = self.item_path_str(trait_def_id);
let mut err = struct_span_err!(
self.sess, span, E0038,
"the trait `{}` cannot be made into an object",
trait_str);
err.span_label(span, &format!(
"the trait `{}` cannot be made into an object", trait_str
));

let mut reported_violations = FnvHashSet();
for violation in violations {
Expand Down Expand Up @@ -697,19 +637,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
&buf
}
};
match (warning_node_id, &mut err) {
(Some(node_id), &mut None) => {
self.sess.add_lint(
::lint::builtin::OBJECT_UNSAFE_FRAGMENT,
node_id,
span,
note.to_string());
}
(None, &mut Some(ref mut err)) => {
err.note(note);
}
_ => unreachable!()
}
err.note(note);
}
err
}
Expand Down
38 changes: 0 additions & 38 deletions src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ pub struct FulfillmentContext<'tcx> {
// fulfillment context.
predicates: ObligationForest<PendingPredicateObligation<'tcx>>,

// A list of new obligations due to RFC1592.
rfc1592_obligations: Vec<PredicateObligation<'tcx>>,

// A set of constraints that regionck must validate. Each
// constraint has the form `T:'a`, meaning "some type `T` must
// outlive the lifetime 'a". These constraints derive from
Expand Down Expand Up @@ -192,7 +189,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
pub fn new() -> FulfillmentContext<'tcx> {
FulfillmentContext {
predicates: ObligationForest::new(),
rfc1592_obligations: Vec::new(),
region_obligations: NodeMap(),
deferred_obligations: vec![],
}
Expand Down Expand Up @@ -275,13 +271,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
});
}

pub fn register_rfc1592_obligation(&mut self,
_infcx: &InferCtxt<'a, 'gcx, 'tcx>,
obligation: PredicateObligation<'tcx>)
{
self.rfc1592_obligations.push(obligation);
}

pub fn region_obligations(&self,
body_id: ast::NodeId)
-> &[RegionObligation<'tcx>]
Expand All @@ -292,21 +281,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
}
}

pub fn select_rfc1592_obligations(&mut self,
infcx: &InferCtxt<'a, 'gcx, 'tcx>)
-> Result<(),Vec<FulfillmentError<'tcx>>>
{
while !self.rfc1592_obligations.is_empty() {
for obligation in mem::replace(&mut self.rfc1592_obligations, Vec::new()) {
self.register_predicate_obligation(infcx, obligation);
}

self.select_all_or_error(infcx)?;
}

Ok(())
}

pub fn select_all_or_error(&mut self,
infcx: &InferCtxt<'a, 'gcx, 'tcx>)
-> Result<(),Vec<FulfillmentError<'tcx>>>
Expand Down Expand Up @@ -362,7 +336,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
let outcome = self.predicates.process_obligations(&mut FulfillProcessor {
selcx: selcx,
region_obligations: &mut self.region_obligations,
rfc1592_obligations: &mut self.rfc1592_obligations,
deferred_obligations: &mut self.deferred_obligations
});
debug!("select: outcome={:?}", outcome);
Expand Down Expand Up @@ -398,7 +371,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
struct FulfillProcessor<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> {
selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
region_obligations: &'a mut NodeMap<Vec<RegionObligation<'tcx>>>,
rfc1592_obligations: &'a mut Vec<PredicateObligation<'tcx>>,
deferred_obligations: &'a mut Vec<DeferredObligation<'tcx>>
}

Expand All @@ -413,7 +385,6 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
process_predicate(self.selcx,
obligation,
self.region_obligations,
self.rfc1592_obligations,
self.deferred_obligations)
.map(|os| os.map(|os| os.into_iter().map(|o| PendingPredicateObligation {
obligation: o,
Expand Down Expand Up @@ -455,7 +426,6 @@ fn process_predicate<'a, 'gcx, 'tcx>(
selcx: &mut SelectionContext<'a, 'gcx, 'tcx>,
pending_obligation: &mut PendingPredicateObligation<'tcx>,
region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>,
rfc1592_obligations: &mut Vec<PredicateObligation<'tcx>>,
deferred_obligations: &mut Vec<DeferredObligation<'tcx>>)
-> Result<Option<Vec<PredicateObligation<'tcx>>>,
FulfillmentErrorCode<'tcx>>
Expand Down Expand Up @@ -644,14 +614,6 @@ fn process_predicate<'a, 'gcx, 'tcx>(
s => Ok(s)
}
}

ty::Predicate::Rfc1592(ref inner) => {
rfc1592_obligations.push(PredicateObligation {
predicate: ty::Predicate::clone(inner),
..obligation.clone()
});
Ok(Some(vec![]))
}
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
ty::Predicate::TypeOutlives(..) |
ty::Predicate::RegionOutlives(..) |
ty::Predicate::ClosureKind(..) |
ty::Predicate::Rfc1592(..) |
ty::Predicate::Equate(..) => {
false
}
Expand Down Expand Up @@ -184,7 +183,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
ty::Predicate::Projection(..) |
ty::Predicate::Trait(..) |
ty::Predicate::Rfc1592(..) |
ty::Predicate::Equate(..) |
ty::Predicate::RegionOutlives(..) |
ty::Predicate::WellFormed(..) |
Expand Down
Loading

0 comments on commit 147371f

Please sign in to comment.