change the newly-added errors to warnings

this commit should be reverted after a release cycle
This commit is contained in:
Ariel Ben-Yehuda 2016-05-01 09:59:28 +03:00
parent 5876b4b12a
commit 6057a7f188
29 changed files with 363 additions and 117 deletions

View File

@ -185,6 +185,18 @@ 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"
}
/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
#[derive(Copy, Clone)]
@ -220,7 +232,9 @@ impl LintPass for HardwiredLints {
TRANSMUTE_FROM_FN_ITEM_TYPES,
OVERLAPPING_INHERENT_IMPLS,
RENAMED_AND_REMOVED_LINTS,
SUPER_OR_SELF_IN_GLOBAL_PATH
SUPER_OR_SELF_IN_GLOBAL_PATH,
UNSIZED_IN_TUPLE,
OBJECT_UNSAFE_FRAGMENT
)
}
}

View File

@ -56,6 +56,7 @@ impl FreeRegionMap {
match *predicate {
ty::Predicate::Projection(..) |
ty::Predicate::Trait(..) |
ty::Predicate::Rfc1592(..) |
ty::Predicate::Equate(..) |
ty::Predicate::WellFormed(..) |
ty::Predicate::ObjectSafe(..) |

View File

@ -36,23 +36,27 @@ use util::nodemap::{FnvHashMap, FnvHashSet};
use std::cmp;
use std::fmt;
use syntax::attr::{AttributeMethods, AttrMetaMethods};
use syntax::ast;
use syntax::codemap::Span;
use syntax::errors::DiagnosticBuilder;
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TraitErrorKey<'tcx> {
span: Span,
warning_node_id: Option<ast::NodeId>,
predicate: ty::Predicate<'tcx>
}
impl<'tcx> TraitErrorKey<'tcx> {
fn from_error<'a>(infcx: &InferCtxt<'a, 'tcx>,
e: &FulfillmentError<'tcx>) -> Self {
e: &FulfillmentError<'tcx>,
warning_node_id: Option<ast::NodeId>) -> Self {
let predicate =
infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
TraitErrorKey {
span: e.obligation.cause.span,
predicate: infcx.tcx.erase_regions(&predicate)
predicate: infcx.tcx.erase_regions(&predicate),
warning_node_id: warning_node_id
}
}
}
@ -60,13 +64,23 @@ impl<'tcx> TraitErrorKey<'tcx> {
pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
errors: &Vec<FulfillmentError<'tcx>>) {
for error in errors {
report_fulfillment_error(infcx, error);
report_fulfillment_error(infcx, error, None);
}
}
pub fn report_fulfillment_errors_as_warnings<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
errors: &Vec<FulfillmentError<'tcx>>,
node_id: ast::NodeId)
{
for error in errors {
report_fulfillment_error(infcx, error, Some(node_id));
}
}
fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
error: &FulfillmentError<'tcx>) {
let error_key = TraitErrorKey::from_error(infcx, error);
error: &FulfillmentError<'tcx>,
warning_node_id: Option<ast::NodeId>) {
let error_key = TraitErrorKey::from_error(infcx, error, warning_node_id);
debug!("report_fulfillment_errors({:?}) - key={:?}",
error, error_key);
if !infcx.reported_trait_errors.borrow_mut().insert(error_key) {
@ -75,10 +89,10 @@ fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
}
match error.code {
FulfillmentErrorCode::CodeSelectionError(ref e) => {
report_selection_error(infcx, &error.obligation, e);
report_selection_error(infcx, &error.obligation, e, warning_node_id);
}
FulfillmentErrorCode::CodeProjectionError(ref e) => {
report_projection_error(infcx, &error.obligation, e);
report_projection_error(infcx, &error.obligation, e, warning_node_id);
}
FulfillmentErrorCode::CodeAmbiguity => {
maybe_report_ambiguity(infcx, &error.obligation);
@ -88,18 +102,29 @@ fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
obligation: &PredicateObligation<'tcx>,
error: &MismatchedProjectionTypes<'tcx>)
error: &MismatchedProjectionTypes<'tcx>,
warning_node_id: Option<ast::NodeId>)
{
let predicate =
infcx.resolve_type_vars_if_possible(&obligation.predicate);
if !predicate.references_error() {
let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0271,
"type mismatch resolving `{}`: {}",
predicate,
error.err);
note_obligation_cause(infcx, &mut err, obligation);
err.emit();
if let Some(warning_node_id) = warning_node_id {
infcx.tcx.sess.add_lint(
::lint::builtin::UNSIZED_IN_TUPLE,
warning_node_id,
obligation.cause.span,
format!("type mismatch resolving `{}`: {}",
predicate,
error.err));
} else {
let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0271,
"type mismatch resolving `{}`: {}",
predicate,
error.err);
note_obligation_cause(infcx, &mut err, obligation);
err.emit();
}
}
}
@ -383,7 +408,8 @@ pub fn recursive_type_with_infinite_size_error<'tcx>(tcx: &TyCtxt<'tcx>,
pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
obligation: &PredicateObligation<'tcx>,
error: &SelectionError<'tcx>)
error: &SelectionError<'tcx>,
warning_node_id: Option<ast::NodeId>)
{
match *error {
SelectionError::Unimplemented => {
@ -401,6 +427,17 @@ 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();
if let Some(warning_node_id) = warning_node_id {
infcx.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!(
infcx.tcx.sess, obligation.cause.span, E0277,
"the trait bound `{}` is not satisfied",
@ -480,12 +517,15 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
ty::Predicate::ObjectSafe(trait_def_id) => {
let violations = object_safety_violations(
infcx.tcx, trait_def_id);
let mut err = report_object_safety_error(infcx.tcx,
obligation.cause.span,
trait_def_id,
violations);
note_obligation_cause(infcx, &mut err, obligation);
err.emit();
let err = report_object_safety_error(infcx.tcx,
obligation.cause.span,
trait_def_id,
warning_node_id,
violations);
if let Some(mut err) = err {
note_obligation_cause(infcx, &mut err, obligation);
err.emit();
}
}
ty::Predicate::ClosureKind(closure_def_id, kind) => {
@ -514,6 +554,13 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
"WF predicate not satisfied for {:?}",
ty);
}
ty::Predicate::Rfc1592(ref data) => {
span_bug!(
obligation.cause.span,
"RFC1592 predicate not satisfied for {:?}",
data);
}
}
}
}
@ -537,10 +584,13 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
TraitNotObjectSafe(did) => {
let violations = object_safety_violations(infcx.tcx, did);
let mut err = report_object_safety_error(infcx.tcx, obligation.cause.span, did,
violations);
note_obligation_cause(infcx, &mut err, obligation);
err.emit();
let err = report_object_safety_error(infcx.tcx, obligation.cause.span, did,
warning_node_id,
violations);
if let Some(mut err) = err {
note_obligation_cause(infcx, &mut err, obligation);
err.emit();
}
}
}
}
@ -548,47 +598,70 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
pub fn report_object_safety_error<'tcx>(tcx: &TyCtxt<'tcx>,
span: Span,
trait_def_id: DefId,
warning_node_id: Option<ast::NodeId>,
violations: Vec<ObjectSafetyViolation>)
-> DiagnosticBuilder<'tcx>
-> Option<DiagnosticBuilder<'tcx>>
{
let mut err = struct_span_err!(
tcx.sess, span, E0038,
"the trait `{}` cannot be made into an object",
tcx.item_path_str(trait_def_id));
let mut err = match warning_node_id {
Some(_) => None,
None => {
Some(struct_span_err!(
tcx.sess, span, E0038,
"the trait `{}` cannot be made into an object",
tcx.item_path_str(trait_def_id)))
}
};
let mut reported_violations = FnvHashSet();
for violation in violations {
if !reported_violations.insert(violation.clone()) {
continue;
}
match violation {
let buf;
let note = match violation {
ObjectSafetyViolation::SizedSelf => {
err.note("the trait cannot require that `Self : Sized`");
"the trait cannot require that `Self : Sized`"
}
ObjectSafetyViolation::SupertraitSelf => {
err.note("the trait cannot use `Self` as a type parameter \
in the supertrait listing");
"the trait cannot use `Self` as a type parameter \
in the supertrait listing"
}
ObjectSafetyViolation::Method(method,
MethodViolationCode::StaticMethod) => {
err.note(&format!("method `{}` has no receiver",
method.name));
buf = format!("method `{}` has no receiver",
method.name);
&buf
}
ObjectSafetyViolation::Method(method,
MethodViolationCode::ReferencesSelf) => {
err.note(&format!("method `{}` references the `Self` type \
buf = format!("method `{}` references the `Self` type \
in its arguments or return type",
method.name));
method.name);
&buf
}
ObjectSafetyViolation::Method(method,
MethodViolationCode::Generic) => {
err.note(&format!("method `{}` has generic type parameters",
method.name));
buf = format!("method `{}` has generic type parameters",
method.name);
&buf
}
};
match (warning_node_id, &mut err) {
(Some(node_id), &mut None) => {
tcx.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
@ -765,13 +838,7 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
err.note("slice and array elements must have `Sized` type");
}
ObligationCauseCode::TupleElem => {
err.fileline_note(
cause_span,
"tuple elements must have `Sized` type");
err.fileline_warn(
cause_span,
"this is a new restriction added in rustc 1.10");
err.note("tuple elements must have `Sized` type");
}
ObligationCauseCode::ProjectionWf(data) => {
err.note(&format!("required so that the projection `{}` is well-formed",

View File

@ -13,6 +13,7 @@ use infer::{InferCtxt, InferOk};
use ty::{self, Ty, TyCtxt, TypeFoldable, ToPolyTraitRef};
use rustc_data_structures::obligation_forest::{Backtrace, ObligationForest, Error};
use std::iter;
use std::mem;
use syntax::ast;
use util::common::ErrorReported;
use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap};
@ -70,6 +71,9 @@ pub struct FulfillmentContext<'tcx> {
predicates: ObligationForest<PendingPredicateObligation<'tcx>,
LocalFulfilledPredicates<'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
@ -116,6 +120,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
FulfillmentContext {
duplicate_set: LocalFulfilledPredicates::new(),
predicates: ObligationForest::new(),
rfc1592_obligations: Vec::new(),
region_obligations: NodeMap(),
}
}
@ -197,6 +202,13 @@ impl<'tcx> FulfillmentContext<'tcx> {
self.predicates.push_tree(obligation, LocalFulfilledPredicates::new());
}
pub fn register_rfc1592_obligation<'a>(&mut self,
_infcx: &InferCtxt<'a,'tcx>,
obligation: PredicateObligation<'tcx>)
{
self.rfc1592_obligations.push(obligation);
}
pub fn region_obligations(&self,
body_id: ast::NodeId)
-> &[RegionObligation<'tcx>]
@ -207,11 +219,26 @@ impl<'tcx> FulfillmentContext<'tcx> {
}
}
pub fn select_rfc1592_obligations<'a>(&mut self,
infcx: &InferCtxt<'a,'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<'a>(&mut self,
infcx: &InferCtxt<'a,'tcx>)
-> Result<(),Vec<FulfillmentError<'tcx>>>
{
self.select_where_possible(infcx)?;
let errors: Vec<_> =
self.predicates.to_errors(CodeAmbiguity)
.into_iter()
@ -279,12 +306,14 @@ impl<'tcx> FulfillmentContext<'tcx> {
// Process pending obligations.
let outcome = {
let region_obligations = &mut self.region_obligations;
let rfc1592_obligations = &mut self.rfc1592_obligations;
self.predicates.process_obligations(
|obligation, tree, backtrace| process_predicate(selcx,
tree,
obligation,
backtrace,
region_obligations))
tree,
obligation,
backtrace,
region_obligations,
rfc1592_obligations))
};
debug!("select: outcome={:?}", outcome);
@ -321,11 +350,13 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
tree_cache: &mut LocalFulfilledPredicates<'tcx>,
pending_obligation: &mut PendingPredicateObligation<'tcx>,
backtrace: Backtrace<PendingPredicateObligation<'tcx>>,
region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>)
region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>,
rfc1592_obligations: &mut Vec<PredicateObligation<'tcx>>)
-> Result<Option<Vec<PendingPredicateObligation<'tcx>>>,
FulfillmentErrorCode<'tcx>>
{
match process_predicate1(selcx, pending_obligation, region_obligations) {
match process_predicate1(selcx, pending_obligation, region_obligations,
rfc1592_obligations) {
Ok(Some(v)) => process_child_obligations(selcx,
tree_cache,
&pending_obligation.obligation,
@ -507,7 +538,8 @@ fn trait_ref_type_vars<'a, 'tcx>(selcx: &mut SelectionContext<'a, 'tcx>,
/// - `Err` if the predicate does not hold
fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
pending_obligation: &mut PendingPredicateObligation<'tcx>,
region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>)
region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>,
rfc1592_obligations: &mut Vec<PredicateObligation<'tcx>>)
-> Result<Option<Vec<PredicateObligation<'tcx>>>,
FulfillmentErrorCode<'tcx>>
{
@ -677,6 +709,14 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
s => Ok(s)
}
}
ty::Predicate::Rfc1592(ref inner) => {
rfc1592_obligations.push(PredicateObligation {
predicate: ty::Predicate::clone(inner),
..obligation.clone()
});
Ok(Some(vec![]))
}
}
}

View File

@ -28,6 +28,7 @@ use syntax::codemap::{Span, DUMMY_SP};
pub use self::error_reporting::TraitErrorKey;
pub use self::error_reporting::recursive_type_with_infinite_size_error;
pub use self::error_reporting::report_fulfillment_errors;
pub use self::error_reporting::report_fulfillment_errors_as_warnings;
pub use self::error_reporting::report_overflow_error;
pub use self::error_reporting::report_overflow_error_cycle;
pub use self::error_reporting::report_selection_error;

View File

@ -166,6 +166,7 @@ pub fn supertraits_reference_self<'tcx>(tcx: &TyCtxt<'tcx>,
ty::Predicate::TypeOutlives(..) |
ty::Predicate::RegionOutlives(..) |
ty::Predicate::ClosureKind(..) |
ty::Predicate::Rfc1592(..) |
ty::Predicate::Equate(..) => {
false
}
@ -204,6 +205,7 @@ fn generics_require_sized_self<'tcx>(tcx: &TyCtxt<'tcx>,
}
ty::Predicate::Projection(..) |
ty::Predicate::Trait(..) |
ty::Predicate::Rfc1592(..) |
ty::Predicate::Equate(..) |
ty::Predicate::RegionOutlives(..) |
ty::Predicate::WellFormed(..) |

View File

@ -419,6 +419,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
match obligation.predicate {
ty::Predicate::Rfc1592(..) => EvaluatedToOk,
ty::Predicate::Trait(ref t) => {
assert!(!t.has_escaping_regions());
let obligation = obligation.with(t.clone());
@ -1661,10 +1663,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::TyStr | ty::TySlice(_) | ty::TyTrait(..) => Never,
ty::TyTuple(ref tys) => {
Where(ty::Binder(match tys.last() {
Some(ty) => vec![ty],
_ => vec![]
}))
// FIXME(#33242) we only need to constrain the last field
Where(ty::Binder(tys.clone()))
}
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
@ -2408,11 +2408,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// T -> Trait.
(_, &ty::TyTrait(ref data)) => {
let mut object_dids =
data.bounds.builtin_bounds.iter().flat_map(|bound| {
tcx.lang_items.from_builtin_kind(bound).ok()
})
.chain(Some(data.principal_def_id()));
let mut object_dids = Some(data.principal_def_id()).into_iter();
// FIXME(#33243)
// data.bounds.builtin_bounds.iter().flat_map(|bound| {
// tcx.lang_items.from_builtin_kind(bound).ok()
// })
// .chain(Some(data.principal_def_id()));
if let Some(did) = object_dids.find(|did| {
!object_safety::is_object_safe(tcx, *did)
}) {

View File

@ -18,6 +18,39 @@ use util::nodemap::FnvHashSet;
use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};
fn anonymize_predicate<'tcx>(tcx: &TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>)
-> ty::Predicate<'tcx> {
match *pred {
ty::Predicate::Trait(ref data) =>
ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data)),
ty::Predicate::Rfc1592(ref data) =>
ty::Predicate::Rfc1592(Box::new(anonymize_predicate(tcx, data))),
ty::Predicate::Equate(ref data) =>
ty::Predicate::Equate(tcx.anonymize_late_bound_regions(data)),
ty::Predicate::RegionOutlives(ref data) =>
ty::Predicate::RegionOutlives(tcx.anonymize_late_bound_regions(data)),
ty::Predicate::TypeOutlives(ref data) =>
ty::Predicate::TypeOutlives(tcx.anonymize_late_bound_regions(data)),
ty::Predicate::Projection(ref data) =>
ty::Predicate::Projection(tcx.anonymize_late_bound_regions(data)),
ty::Predicate::WellFormed(data) =>
ty::Predicate::WellFormed(data),
ty::Predicate::ObjectSafe(data) =>
ty::Predicate::ObjectSafe(data),
ty::Predicate::ClosureKind(closure_def_id, kind) =>
ty::Predicate::ClosureKind(closure_def_id, kind)
}
}
struct PredicateSet<'a,'tcx:'a> {
tcx: &'a TyCtxt<'tcx>,
set: FnvHashSet<ty::Predicate<'tcx>>,
@ -39,32 +72,7 @@ impl<'a,'tcx> PredicateSet<'a,'tcx> {
//
// to be considered equivalent. So normalize all late-bound
// regions before we throw things into the underlying set.
let normalized_pred = match *pred {
ty::Predicate::Trait(ref data) =>
ty::Predicate::Trait(self.tcx.anonymize_late_bound_regions(data)),
ty::Predicate::Equate(ref data) =>
ty::Predicate::Equate(self.tcx.anonymize_late_bound_regions(data)),
ty::Predicate::RegionOutlives(ref data) =>
ty::Predicate::RegionOutlives(self.tcx.anonymize_late_bound_regions(data)),
ty::Predicate::TypeOutlives(ref data) =>
ty::Predicate::TypeOutlives(self.tcx.anonymize_late_bound_regions(data)),
ty::Predicate::Projection(ref data) =>
ty::Predicate::Projection(self.tcx.anonymize_late_bound_regions(data)),
ty::Predicate::WellFormed(data) =>
ty::Predicate::WellFormed(data),
ty::Predicate::ObjectSafe(data) =>
ty::Predicate::ObjectSafe(data),
ty::Predicate::ClosureKind(closure_def_id, kind) =>
ty::Predicate::ClosureKind(closure_def_id, kind)
};
self.set.insert(normalized_pred)
self.set.insert(anonymize_predicate(self.tcx, pred))
}
}
@ -143,6 +151,9 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
self.stack.extend(predicates);
}
ty::Predicate::Rfc1592(..) => {
// Nothing to elaborate.
}
ty::Predicate::WellFormed(..) => {
// Currently, we do not elaborate WF predicates,
// although we easily could.

View File

@ -804,6 +804,9 @@ pub enum Predicate<'tcx> {
/// would be the parameters in the `TypeSpace`.
Trait(PolyTraitPredicate<'tcx>),
/// A predicate created by RFC1592
Rfc1592(Box<Predicate<'tcx>>),
/// where `T1 == T2`.
Equate(PolyEquatePredicate<'tcx>),
@ -904,6 +907,8 @@ impl<'tcx> Predicate<'tcx> {
match *self {
Predicate::Trait(ty::Binder(ref data)) =>
Predicate::Trait(ty::Binder(data.subst(tcx, substs))),
Predicate::Rfc1592(ref pi) =>
Predicate::Rfc1592(Box::new(pi.subst_supertrait(tcx, trait_ref))),
Predicate::Equate(ty::Binder(ref data)) =>
Predicate::Equate(ty::Binder(data.subst(tcx, substs))),
Predicate::RegionOutlives(ty::Binder(ref data)) =>
@ -1083,6 +1088,9 @@ impl<'tcx> Predicate<'tcx> {
ty::Predicate::Trait(ref data) => {
data.0.trait_ref.substs.types.as_slice().to_vec()
}
ty::Predicate::Rfc1592(ref data) => {
return data.walk_tys()
}
ty::Predicate::Equate(ty::Binder(ref data)) => {
vec![data.0, data.1]
}
@ -1123,6 +1131,7 @@ impl<'tcx> Predicate<'tcx> {
Predicate::Trait(ref t) => {
Some(t.to_poly_trait_ref())
}
Predicate::Rfc1592(..) |
Predicate::Projection(..) |
Predicate::Equate(..) |
Predicate::RegionOutlives(..) |
@ -1835,7 +1844,8 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
}
TyTuple(ref tys) => {
tys.last().into_iter().flat_map(|ty| {
// FIXME(#33242) we only need to constrain the last field
tys.iter().flat_map(|ty| {
self.sized_constraint_for_ty(tcx, stack, ty)
}).collect()
}

View File

@ -634,6 +634,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
match *self {
ty::Predicate::Trait(ref a) =>
ty::Predicate::Trait(a.fold_with(folder)),
ty::Predicate::Rfc1592(ref a) =>
ty::Predicate::Rfc1592(a.fold_with(folder)),
ty::Predicate::Equate(ref binder) =>
ty::Predicate::Equate(binder.fold_with(folder)),
ty::Predicate::RegionOutlives(ref binder) =>
@ -654,6 +656,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match *self {
ty::Predicate::Trait(ref a) => a.visit_with(visitor),
ty::Predicate::Rfc1592(ref a) => a.visit_with(visitor),
ty::Predicate::Equate(ref binder) => binder.visit_with(visitor),
ty::Predicate::RegionOutlives(ref binder) => binder.visit_with(visitor),
ty::Predicate::TypeOutlives(ref binder) => binder.visit_with(visitor),

View File

@ -299,6 +299,7 @@ impl<'tcx> TyCtxt<'tcx> {
match predicate {
ty::Predicate::Projection(..) |
ty::Predicate::Trait(..) |
ty::Predicate::Rfc1592(..) |
ty::Predicate::Equate(..) |
ty::Predicate::WellFormed(..) |
ty::Predicate::ObjectSafe(..) |

View File

@ -94,6 +94,9 @@ pub fn predicate_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
}
ty::Predicate::ClosureKind(..) => {
}
ty::Predicate::Rfc1592(ref data) => {
bug!("RFC1592 predicate `{:?}` in predicate_obligations", data);
}
}
wf.normalize()
@ -155,6 +158,7 @@ pub fn implied_bounds<'a,'tcx>(
assert!(!obligation.has_escaping_regions());
match obligation.predicate {
ty::Predicate::Trait(..) |
ty::Predicate::Rfc1592(..) |
ty::Predicate::Equate(..) |
ty::Predicate::Projection(..) |
ty::Predicate::ClosureKind(..) |
@ -280,16 +284,23 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
}
}
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>,
rfc1592: bool) {
if !subty.has_escaping_regions() {
let cause = self.cause(cause);
match traits::trait_ref_for_builtin_bound(self.infcx.tcx,
ty::BoundSized,
subty) {
Ok(trait_ref) => {
let predicate = trait_ref.to_predicate();
let predicate = if rfc1592 {
ty::Predicate::Rfc1592(box predicate)
} else {
predicate
};
self.out.push(
traits::Obligation::new(cause,
trait_ref.to_predicate()));
predicate));
}
Err(ErrorReported) => { }
}
@ -318,13 +329,13 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
ty::TySlice(subty) |
ty::TyArray(subty, _) => {
self.require_sized(subty, traits::SliceOrArrayElem);
self.require_sized(subty, traits::SliceOrArrayElem, false);
}
ty::TyTuple(ref tys) => {
if let Some((_last, rest)) = tys.split_last() {
for elem in rest {
self.require_sized(elem, traits::TupleElem);
self.require_sized(elem, traits::TupleElem, true);
}
}
}
@ -387,18 +398,23 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
let cause = self.cause(traits::MiscObligation);
// FIXME(#33243): remove RFC1592
self.out.push(traits::Obligation::new(
cause.clone(),
ty::Predicate::ObjectSafe(data.principal_def_id())
));
let component_traits =
data.bounds.builtin_bounds.iter().flat_map(|bound| {
tcx.lang_items.from_builtin_kind(bound).ok()
})
.chain(Some(data.principal_def_id()));
});
// .chain(Some(data.principal_def_id()));
self.out.extend(
component_traits.map(|did| {
traits::Obligation::new(
cause.clone(),
ty::Predicate::ObjectSafe(did)
component_traits.map(|did| { traits::Obligation::new(
cause.clone(),
ty::Predicate::Rfc1592(
box ty::Predicate::ObjectSafe(did)
)
})
)})
);
}

View File

@ -459,6 +459,9 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ty::Predicate::Trait(ref a) => write!(f, "{:?}", a),
ty::Predicate::Rfc1592(ref a) => {
write!(f, "RFC1592({:?})", a)
}
ty::Predicate::Equate(ref pair) => write!(f, "{:?}", pair),
ty::Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair),
ty::Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair),
@ -1056,6 +1059,7 @@ impl<'tcx> fmt::Display for ty::Predicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ty::Predicate::Trait(ref data) => write!(f, "{}", data),
ty::Predicate::Rfc1592(ref data) => write!(f, "{}", data),
ty::Predicate::Equate(ref predicate) => write!(f, "{}", predicate),
ty::Predicate::RegionOutlives(ref predicate) => write!(f, "{}", predicate),
ty::Predicate::TypeOutlives(ref predicate) => write!(f, "{}", predicate),

View File

@ -190,6 +190,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
id: LintId::of(ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN),
reference: "RFC 1445 <https://github.com/rust-lang/rfcs/pull/1445>",
},
FutureIncompatibleInfo {
id: LintId::of(UNSIZED_IN_TUPLE),
reference: "RFC PR 1592 <https://github.com/rust-lang/rfcs/pull/1592>",
}
]);
// We have one lint pass defined specially

View File

@ -449,6 +449,9 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
p: &ty::Predicate<'tcx>)
{
match *p {
ty::Predicate::Rfc1592(..) => {
bug!("RFC1592 predicate in metadata `{:?}`", p);
}
ty::Predicate::Trait(ref trait_ref) => {
write!(w, "t");
enc_trait_ref(w, cx, trait_ref.0.trait_ref);

View File

@ -277,6 +277,9 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
traits::report_fulfillment_errors(&infcx, errors);
}
}
if let Err(ref errors) = fulfillment_cx.select_rfc1592_obligations(&infcx) {
traits::report_fulfillment_errors_as_warnings(&infcx, errors, e.id);
}
}
}

View File

@ -1143,8 +1143,8 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx>,
traits::astconv_object_safety_violations(tcx, principal.def_id());
if !object_safety_violations.is_empty() {
traits::report_object_safety_error(
tcx, span, principal.def_id(), object_safety_violations)
.emit();
tcx, span, principal.def_id(), None, object_safety_violations)
.unwrap().emit();
return tcx.types.err;
}

View File

@ -179,6 +179,7 @@ fn deduce_expectations_from_obligations<'a,'tcx>(
ty::Predicate::TypeOutlives(..) => None,
ty::Predicate::WellFormed(..) => None,
ty::Predicate::ObjectSafe(..) => None,
ty::Predicate::Rfc1592(..) => None,
// NB: This predicate is created by breaking down a
// `ClosureType: FnFoo()` predicate, where

View File

@ -477,7 +477,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// Object safety violations or miscellaneous.
Err(err) => {
report_selection_error(self.fcx.infcx(), &obligation, &err);
report_selection_error(self.fcx.infcx(), &obligation, &err, None);
// Treat this like an obligation and follow through
// with the unsizing - the lack of a coercion should
// be silent, as it causes a type mismatch later.

View File

@ -114,6 +114,11 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
return Err(());
}
if let Err(ref errors) = fulfillment_cx.select_rfc1592_obligations(&infcx) {
traits::report_fulfillment_errors_as_warnings(&infcx, errors,
drop_impl_node_id);
}
let free_regions = FreeRegionMap::new();
infcx.resolve_regions_and_report_errors(&free_regions, drop_impl_node_id);
Ok(())

View File

@ -492,6 +492,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
ty::Predicate::WellFormed(..) |
ty::Predicate::ObjectSafe(..) |
ty::Predicate::ClosureKind(..) |
ty::Predicate::Rfc1592(..) |
ty::Predicate::TypeOutlives(..) => {
None
}

View File

@ -1989,13 +1989,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// upvar inference should have ensured that all deferred call
// resolutions are handled by now.
assert!(self.inh.deferred_call_resolutions.borrow().is_empty());
let infcx = self.infcx();
self.select_all_obligations_and_apply_defaults();
let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
match fulfillment_cx.select_all_or_error(self.infcx()) {
match fulfillment_cx.select_all_or_error(infcx) {
Ok(()) => { }
Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
Err(errors) => { report_fulfillment_errors(infcx, &errors); }
}
if let Err(ref errors) = fulfillment_cx.select_rfc1592_obligations(infcx) {
traits::report_fulfillment_errors_as_warnings(infcx, errors, self.body_id);
}
}

View File

@ -450,6 +450,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
ty::Predicate::TypeOutlives(ref data) => {
data.skip_binder().0.is_param(def.space, def.index)
}
ty::Predicate::Rfc1592(..) |
ty::Predicate::Equate(..) |
ty::Predicate::RegionOutlives(..) |
ty::Predicate::WellFormed(..) |

View File

@ -15,5 +15,4 @@ pub fn main() {
//~^ ERROR `Trait + Sized: std::marker::Sized` is not satisfied
//~| ERROR `Trait + Sized: std::marker::Sized` is not satisfied
//~| ERROR `Trait + Sized: std::marker::Sized` is not satisfied
//~| ERROR `std::marker::Sized` cannot be made into an object
}

View File

@ -16,6 +16,5 @@ fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
fn main() {
size_of_copy::<Misc+Copy>();
//~^ ERROR `std::marker::Copy` cannot be made into an object
//~| ERROR `Misc + Copy: std::marker::Copy` is not satisfied
//~^ ERROR `Misc + Copy: std::marker::Copy` is not satisfied
}

View File

@ -0,0 +1,31 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt;
trait Foo {
fn foo(&self) -> (Self, Self);
//~^ WARNING hard error
}
impl<T: Copy> Foo for T {
fn foo(&self) -> (Self, Self) {
(*self, *self)
}
}
fn main() {
assert_eq!((11).foo(), (11, 11));
let junk: Box<fmt::Debug+Sized> = Box::new(42);
//~^ WARNING hard error
let f = format!("{:?}", junk);
assert_eq!(f, "42");
}

View File

@ -60,9 +60,6 @@ fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
fn f9<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {
f5(&(*x1, 34));
//~^ ERROR `X: std::marker::Sized` is not satisfied
//~| WARNING this is a new restriction added in rustc 1.10
//~^^^ ERROR `X: std::marker::Sized` is not satisfied
//~| WARNING this is a new restriction added in rustc 1.10
}
fn f10<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {

View File

@ -14,16 +14,13 @@ trait T {}
fn f1<X: ?Sized>(x: &X) {
let _: X; // <-- this is OK, no bindings created, no initializer.
let _: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfied
//~| WARNING this is a new restriction added in rustc 1.10
let _: (isize, (X, isize));
let y: X; //~ERROR `X: std::marker::Sized` is not satisfied
let y: (isize, (X, usize)); //~ERROR `X: std::marker::Sized` is not satisfied
//~| WARNING this is a new restriction added in rustc 1.10
}
fn f2<X: ?Sized + T>(x: &X) {
let y: X; //~ERROR `X: std::marker::Sized` is not satisfied
let y: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfied
//~| WARNING this is a new restriction added in rustc 1.10
}
fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {

View File

@ -0,0 +1,29 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt;
trait Foo {
fn foo(&self) -> (Self, Self);
}
impl<T: Copy> Foo for T {
fn foo(&self) -> (Self, Self) {
(*self, *self)
}
}
fn main() {
assert_eq!((11).foo(), (11, 11));
let junk: Box<fmt::Debug+Sized> = Box::new(42);
let f = format!("{:?}", junk);
assert_eq!(f, "42");
}