From 6057a7f18827f065668fcf22cfc0242de8f694b9 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 1 May 2016 09:59:28 +0300 Subject: [PATCH] change the newly-added errors to warnings this commit should be reverted after a release cycle --- src/librustc/lint/builtin.rs | 16 +- src/librustc/middle/free_region.rs | 1 + src/librustc/traits/error_reporting.rs | 161 ++++++++++++++------ src/librustc/traits/fulfill.rs | 54 ++++++- src/librustc/traits/mod.rs | 1 + src/librustc/traits/object_safety.rs | 2 + src/librustc/traits/select.rs | 19 +-- src/librustc/traits/util.rs | 63 ++++---- src/librustc/ty/mod.rs | 12 +- src/librustc/ty/structural_impls.rs | 3 + src/librustc/ty/util.rs | 1 + src/librustc/ty/wf.rs | 38 +++-- src/librustc/util/ppaux.rs | 4 + src/librustc_lint/lib.rs | 4 + src/librustc_metadata/tyencode.rs | 3 + src/librustc_passes/consts.rs | 3 + src/librustc_typeck/astconv.rs | 4 +- src/librustc_typeck/check/closure.rs | 1 + src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/dropck.rs | 5 + src/librustc_typeck/check/method/probe.rs | 1 + src/librustc_typeck/check/mod.rs | 9 +- src/librustc_typeck/collect.rs | 1 + src/test/compile-fail/bad-sized.rs | 1 - src/test/compile-fail/issue-32963.rs | 3 +- src/test/compile-fail/rfc1592-deprecated.rs | 31 ++++ src/test/compile-fail/unsized3.rs | 3 - src/test/compile-fail/unsized6.rs | 5 +- src/test/run-pass/rfc1592-deprecated.rs | 29 ++++ 29 files changed, 363 insertions(+), 117 deletions(-) create mode 100644 src/test/compile-fail/rfc1592-deprecated.rs create mode 100644 src/test/run-pass/rfc1592-deprecated.rs diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 2564838c67d65..6dd98425df317 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -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 ) } } diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs index 51eebd4373113..758fb7a81fd94 100644 --- a/src/librustc/middle/free_region.rs +++ b/src/librustc/middle/free_region.rs @@ -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(..) | diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 98812f4e00fcc..b89ce2ce3b2cf 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -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, 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) -> 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>) { 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>, + 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) { + 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) { 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) { 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, violations: Vec) - -> DiagnosticBuilder<'tcx> + -> Option> { - 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", diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 8946ec2153b03..a184e951b834c 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -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, LocalFulfilledPredicates<'tcx>>, + // A list of new obligations due to RFC1592. + rfc1592_obligations: Vec>, + // 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>> + { + 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>> { 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>, - region_obligations: &mut NodeMap>>) + region_obligations: &mut NodeMap>>, + rfc1592_obligations: &mut Vec>) -> Result>>, 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>>) + region_obligations: &mut NodeMap>>, + rfc1592_obligations: &mut Vec>) -> Result>>, 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![])) + } } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 5921cdeab7867..7da95b6646ae3 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -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; diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index c870d609814be..59db68b1c3c29 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -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(..) | diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 738ed85ae6d8a..2338eff3ec30a 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -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) }) { diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 90def00be0730..d82f9d7549d90 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -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>, @@ -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. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a61e8603dbbe4..3e3dae3b3e985 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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>), + /// 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() } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 4d64dd8307157..ac3dfa82bd6d2 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -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>(&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), diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 2e4f37f1cc1d4..b6bd8f5f55fba 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -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(..) | diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 316a81e8f6245..609252f948ab3 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -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) ) - }) + )}) ); } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 6682a0e2b4f4f..728306b25ddc7 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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), diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index e7c9097a56a58..4832f18f21322 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -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 ", }, + FutureIncompatibleInfo { + id: LintId::of(UNSIZED_IN_TUPLE), + reference: "RFC PR 1592 ", + } ]); // We have one lint pass defined specially diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 61d055d4d5173..57aa347847e15 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -449,6 +449,9 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor>, 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); diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index dede4d2a42a53..6fb9739fca4f4 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -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); + } } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ac7745985e6af..5e07011d5bafd 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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; } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 4ac7e3323efc8..b84ded1ea7acf 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -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 diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index f1c6868efd210..6c8d437f429f9 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -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. diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 368b826b1bb39..b9fda2104546b 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -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(()) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 2defbf0d33e0a..8a71debdf206b 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -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 } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 385f04b8564f5..6599199c239af 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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); } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index c10488a03ef68..4dd093e2e4bfd 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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(..) | diff --git a/src/test/compile-fail/bad-sized.rs b/src/test/compile-fail/bad-sized.rs index ba0a6f19f0716..f62404e60e69e 100644 --- a/src/test/compile-fail/bad-sized.rs +++ b/src/test/compile-fail/bad-sized.rs @@ -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 } diff --git a/src/test/compile-fail/issue-32963.rs b/src/test/compile-fail/issue-32963.rs index d0434384cd047..c4e8f76611752 100644 --- a/src/test/compile-fail/issue-32963.rs +++ b/src/test/compile-fail/issue-32963.rs @@ -16,6 +16,5 @@ fn size_of_copy() -> usize { mem::size_of::() } fn main() { size_of_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 } diff --git a/src/test/compile-fail/rfc1592-deprecated.rs b/src/test/compile-fail/rfc1592-deprecated.rs new file mode 100644 index 0000000000000..0c12c1c444401 --- /dev/null +++ b/src/test/compile-fail/rfc1592-deprecated.rs @@ -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 or the MIT license +// , 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 Foo for T { + fn foo(&self) -> (Self, Self) { + (*self, *self) + } +} + +fn main() { + assert_eq!((11).foo(), (11, 11)); + + let junk: Box = Box::new(42); + //~^ WARNING hard error + let f = format!("{:?}", junk); + assert_eq!(f, "42"); +} diff --git a/src/test/compile-fail/unsized3.rs b/src/test/compile-fail/unsized3.rs index d5f2cf65a69f2..f88165c02e988 100644 --- a/src/test/compile-fail/unsized3.rs +++ b/src/test/compile-fail/unsized3.rs @@ -60,9 +60,6 @@ fn f8(x1: &S, x2: &S) { fn f9(x1: Box>, x2: Box>) { 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(x1: Box>, x2: Box>) { diff --git a/src/test/compile-fail/unsized6.rs b/src/test/compile-fail/unsized6.rs index ba9a8a4f294f9..d40c12f67a08d 100644 --- a/src/test/compile-fail/unsized6.rs +++ b/src/test/compile-fail/unsized6.rs @@ -14,16 +14,13 @@ trait T {} fn f1(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: &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(x1: Box, x2: Box, x3: Box) { diff --git a/src/test/run-pass/rfc1592-deprecated.rs b/src/test/run-pass/rfc1592-deprecated.rs new file mode 100644 index 0000000000000..81bf02587896f --- /dev/null +++ b/src/test/run-pass/rfc1592-deprecated.rs @@ -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 or the MIT license +// , 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 Foo for T { + fn foo(&self) -> (Self, Self) { + (*self, *self) + } +} + +fn main() { + assert_eq!((11).foo(), (11, 11)); + + let junk: Box = Box::new(42); + let f = format!("{:?}", junk); + assert_eq!(f, "42"); +}