Auto merge of #30389 - nikomatsakis:rfc1214-error, r=arielb1

Make RFC 1214 warnings into errors, and rip out the "warn or err"
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.

r? @arielb1
This commit is contained in:
bors 2015-12-18 20:44:33 +00:00
commit 5dd29cc310
88 changed files with 293 additions and 1189 deletions

View File

@ -577,11 +577,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),
@ -592,8 +587,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(),
@ -605,8 +600,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(),
@ -617,8 +612,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(
@ -633,10 +628,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);
}
@ -645,13 +636,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);
@ -1598,9 +1582,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(_) => {

View File

@ -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};
@ -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>),
@ -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,

View File

@ -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>
}
@ -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)
}
@ -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>)
@ -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);
@ -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);
@ -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());
@ -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);
@ -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);
@ -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);
@ -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);
}
@ -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(),
@ -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);
}
}
@ -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));
@ -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
@ -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));
}
}
@ -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,

View File

@ -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
@ -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;
}
@ -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"
@ -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)
}
}
@ -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
@ -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())
}
}

View File

@ -106,9 +106,6 @@ pub enum ObligationCauseCode<'tcx> {
/// Not well classified or should be obvious from span.
MiscObligation,
/// Obligation that triggers warning until RFC 1214 is fully in place.
RFC1214(Rc<ObligationCauseCode<'tcx>>),
/// This is the trait reference from the given projection
SliceOrArrayElem,
@ -554,24 +551,6 @@ impl<'tcx> ObligationCause<'tcx> {
}
}
/// This marker is used in some caches to record whether the
/// predicate, if it is found to be false, will yield a warning (due
/// to RFC1214) or an error. We separate these two cases in the cache
/// so that if we see the same predicate twice, first resulting in a
/// warning, and next resulting in an error, we still report the
/// error, rather than considering it a duplicate.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct RFC1214Warning(bool);
impl<'tcx> ObligationCauseCode<'tcx> {
pub fn is_rfc1214(&self) -> bool {
match *self {
ObligationCauseCode::RFC1214(..) => true,
_ => false,
}
}
}
impl<'tcx, N> Vtable<'tcx, N> {
pub fn nested_obligations(self) -> Vec<N> {
match self {

View File

@ -26,7 +26,6 @@ use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation
use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
use super::{ObjectCastObligation, Obligation};
use super::TraitNotObjectSafe;
use super::RFC1214Warning;
use super::Selection;
use super::SelectionResult;
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
@ -463,8 +462,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// have been proven elsewhere. This cache only contains
// predicates that are global in scope and hence unaffected by
// the current environment.
let w = RFC1214Warning(false);
if self.tcx().fulfilled_predicates.borrow().is_duplicate(w, &obligation.predicate) {
if self.tcx().fulfilled_predicates.borrow().is_duplicate(&obligation.predicate) {
return EvaluatedToOk;
}
@ -485,8 +483,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::Predicate::WellFormed(ty) => {
match ty::wf::obligations(self.infcx, obligation.cause.body_id,
ty, obligation.cause.span,
obligation.cause.code.is_rfc1214()) {
ty, obligation.cause.span) {
Some(obligations) =>
self.evaluate_predicates_recursively(previous_stack, obligations.iter()),
None =>
@ -2906,22 +2903,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// chain. Ideally, we should have a way to configure this either
// by using -Z verbose or just a CLI argument.
if obligation.recursion_depth >= 0 {
let derived_code = match obligation.cause.code {
ObligationCauseCode::RFC1214(ref base_code) => {
let derived_cause = DerivedObligationCause {
parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
parent_code: base_code.clone(),
};
ObligationCauseCode::RFC1214(Rc::new(variant(derived_cause)))
}
_ => {
let derived_cause = DerivedObligationCause {
parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
parent_code: Rc::new(obligation.cause.code.clone())
};
variant(derived_cause)
}
let derived_cause = DerivedObligationCause {
parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
parent_code: Rc::new(obligation.cause.code.clone())
};
let derived_code = variant(derived_cause);
ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)
} else {
obligation.cause.clone()

View File

@ -53,12 +53,6 @@ pub enum Component<'tcx> {
// them. This gives us room to improve the regionck reasoning in
// the future without breaking backwards compat.
EscapingProjection(Vec<Component<'tcx>>),
// This is a temporary marker indicating "outlives components"
// that are due to the new rules introduced by RFC 1214. For the
// time being, violations of these requirements generally induce
// warnings, not errors.
RFC1214(Vec<Component<'tcx>>),
}
/// Returns all the things that must outlive `'a` for the condition
@ -124,20 +118,6 @@ fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
}
}
// Bare functions and traits are both binders. In the RFC,
// this means we would add the bound regions to the "bound
// regions list". In our representation, no such list is
// maintained explicitly, because bound regions themselves can
// be readily identified. However, because the outlives
// relation did not used to be applied to fn/trait-object
// arguments, we wrap the resulting components in an RFC1214
// wrapper so we can issue warnings.
ty::TyBareFn(..) | ty::TyTrait(..) => {
// OutlivesFunction, OutlivesObject, OutlivesFragment
let subcomponents = capture_components(infcx, ty);
out.push(Component::RFC1214(subcomponents));
}
// OutlivesTypeParameterEnv -- the actual checking that `X:'a`
// is implied by the environment is done in regionck.
ty::TyParam(p) => {
@ -202,7 +182,15 @@ fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
ty::TyRawPtr(..) | // ...
ty::TyRef(..) | // OutlivesReference
ty::TyTuple(..) | // ...
ty::TyBareFn(..) | // OutlivesFunction (*)
ty::TyTrait(..) | // OutlivesObject, OutlivesFragment (*)
ty::TyError => {
// (*) Bare functions and traits are both binders. In the
// RFC, this means we would add the bound regions to the
// "bound regions list". In our representation, no such
// list is maintained explicitly, because bound regions
// themselves can be readily identified.
push_region_constraints(out, ty.regions());
for subty in ty.walk_shallow() {
compute_components(infcx, subty, out);

View File

@ -15,8 +15,6 @@ use middle::subst::Substs;
use middle::traits;
use middle::ty::{self, RegionEscape, ToPredicate, Ty};
use std::iter::once;
use std::mem;
use std::rc::Rc;
use syntax::ast;
use syntax::codemap::Span;
use util::common::ErrorReported;
@ -30,15 +28,13 @@ use util::common::ErrorReported;
pub fn obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
body_id: ast::NodeId,
ty: Ty<'tcx>,
span: Span,
rfc1214: bool)
span: Span)
-> Option<Vec<traits::PredicateObligation<'tcx>>>
{
let mut wf = WfPredicates { infcx: infcx,
body_id: body_id,
span: span,
out: vec![],
rfc1214: rfc1214 };
out: vec![] };
if wf.compute(ty) {
debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out);
let result = wf.normalize();
@ -56,12 +52,10 @@ pub fn obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
pub fn trait_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
body_id: ast::NodeId,
trait_ref: &ty::TraitRef<'tcx>,
span: Span,
rfc1214: bool)
span: Span)
-> Vec<traits::PredicateObligation<'tcx>>
{
let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span,
out: vec![], rfc1214: rfc1214 };
let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span, out: vec![] };
wf.compute_trait_ref(trait_ref);
wf.normalize()
}
@ -69,12 +63,10 @@ pub fn trait_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
pub fn predicate_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
body_id: ast::NodeId,
predicate: &ty::Predicate<'tcx>,
span: Span,
rfc1214: bool)
span: Span)
-> Vec<traits::PredicateObligation<'tcx>>
{
let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span,
out: vec![], rfc1214: rfc1214 };
let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span, out: vec![] };
// (*) ok to skip binders, because wf code is prepared for it
match *predicate {
@ -150,7 +142,7 @@ pub fn implied_bounds<'a,'tcx>(
// than the ultimate set. (Note: normally there won't be
// unresolved inference variables here anyway, but there might be
// during typeck under some circumstances.)
let obligations = obligations(infcx, body_id, ty, span, false).unwrap_or(vec![]);
let obligations = obligations(infcx, body_id, ty, span).unwrap_or(vec![]);
// From the full set of obligations, just filter down to the
// region relationships.
@ -223,8 +215,6 @@ fn implied_bounds_from_components<'tcx>(sub_region: ty::Region,
vec!(),
Component::UnresolvedInferenceVariable(..) =>
vec!(),
Component::RFC1214(components) =>
implied_bounds_from_components(sub_region, components),
}
})
.collect()
@ -235,24 +225,11 @@ struct WfPredicates<'a,'tcx:'a> {
body_id: ast::NodeId,
span: Span,
out: Vec<traits::PredicateObligation<'tcx>>,
rfc1214: bool
}
impl<'a,'tcx> WfPredicates<'a,'tcx> {
fn rfc1214<R,F:FnOnce(&mut WfPredicates<'a,'tcx>) -> R>(&mut self, f: F) -> R {
let b = mem::replace(&mut self.rfc1214, true);
let r = f(self);
self.rfc1214 = b;
r
}
fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
if !self.rfc1214 {
traits::ObligationCause::new(self.span, self.body_id, code)
} else {
let code = traits::ObligationCauseCode::RFC1214(Rc::new(code));
traits::ObligationCause::new(self.span, self.body_id, code)
}
traits::ObligationCause::new(self.span, self.body_id, code)
}
fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
@ -268,14 +245,6 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
.collect()
}
fn compute_rfc1214(&mut self, ty: Ty<'tcx>) {
let b = mem::replace(&mut self.rfc1214, true);
for subty in ty.walk().skip(1) {
self.compute(subty);
}
self.rfc1214 = b;
}
/// Pushes the obligations required for `trait_ref` to be WF into
/// `self.out`.
fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
@ -329,21 +298,19 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
ty::TySlice(subty) |
ty::TyArray(subty, _) => {
self.rfc1214(|this| {
if !subty.has_escaping_regions() {
let cause = this.cause(traits::SliceOrArrayElem);
match traits::trait_ref_for_builtin_bound(this.infcx.tcx,
ty::BoundSized,
subty) {
Ok(trait_ref) => {
this.out.push(
traits::Obligation::new(cause,
trait_ref.to_predicate()));
}
Err(ErrorReported) => { }
if !subty.has_escaping_regions() {
let cause = self.cause(traits::SliceOrArrayElem);
match traits::trait_ref_for_builtin_bound(self.infcx.tcx,
ty::BoundSized,
subty) {
Ok(trait_ref) => {
self.out.push(
traits::Obligation::new(cause,
trait_ref.to_predicate()));
}
Err(ErrorReported) => { }
}
})
}
}
ty::TyBox(_) |
@ -380,15 +347,16 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
ty::TyClosure(..) => {
// the types in a closure are always the types of
// local variables (or possibly references to local
// variables), which are separately checked w/r/t
// WFedness.
// variables), we'll walk those.
//
// (Though, local variables are probably not
// needed, as they are separately checked w/r/t
// WFedness.)
}
ty::TyBareFn(..) => {
// process the bound types; because the old implicator
// did not do this, go into RFC1214 mode.
subtys.skip_current_subtree();
self.compute_rfc1214(ty);
// let the loop iterator into the argument/return
// types appearing in the fn signature
}
ty::TyTrait(ref data) => {
@ -407,11 +375,6 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
traits::Obligation::new(
cause,
ty::Predicate::ObjectSafe(data.principal_def_id())));
// process the bound types; because the old implicator
// did not do this, go into RFC1214 mode.
subtys.skip_current_subtree();
self.compute_rfc1214(ty);
}
// Inference variables are the complicated case, since we don't

View File

@ -102,13 +102,6 @@ impl Session {
None => self.diagnostic().span_err(sp, msg)
}
}
pub fn note_rfc_1214(&self, span: Span) {
self.span_note(
span,
&format!("this warning results from recent bug fixes and clarifications; \
it will become a HARD ERROR in the next release. \
See RFC 1214 for details."));
}
pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
match split_msg_into_multilines(msg) {
Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[..], code),

View File

@ -1136,7 +1136,7 @@ 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, false);
tcx, span, principal.def_id(), object_safety_violations);
return tcx.types.err;
}

View File

@ -138,7 +138,6 @@ pub mod coercion;
pub mod demand;
pub mod method;
mod upvar;
mod wf;
mod wfcheck;
mod cast;
mod closure;
@ -382,21 +381,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
}
}
pub fn check_wf_old(ccx: &CrateCtxt) {
// If types are not well-formed, it leads to all manner of errors
// downstream, so stop reporting errors at this point.
ccx.tcx.sess.abort_if_new_errors(|| {
// FIXME(#25759). The new code below is much more reliable but (for now)
// only generates warnings. So as to ensure that we continue
// getting errors where we used to get errors, we run the old wf
// code first and abort if it encounters any errors. If no abort
// comes, we run the new code and issue warnings.
let krate = ccx.tcx.map.krate();
let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
krate.visit_all_items(&mut visit);
});
}
pub fn check_wf_new(ccx: &CrateCtxt) {
ccx.tcx.sess.abort_if_new_errors(|| {
let krate = ccx.tcx.map.krate();

View File

@ -99,7 +99,6 @@ use middle::ty::adjustment;
use middle::ty::wf::ImpliedBound;
use std::mem;
use std::rc::Rc;
use syntax::ast;
use syntax::codemap::Span;
use rustc_front::intravisit::{self, Visitor};
@ -426,8 +425,6 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
code: &traits::ObligationCauseCode<'tcx>)
-> SubregionOrigin<'tcx> {
match *code {
traits::ObligationCauseCode::RFC1214(ref code) =>
infer::RFC1214Subregion(Rc::new(self.code_to_origin(span, sup_type, code))),
traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) =>
infer::ReferenceOutlivesReferent(ref_type, span),
_ =>
@ -1606,10 +1603,6 @@ fn components_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
origin.span(),
&format!("unresolved inference variable in outlives: {:?}", v));
}
ty::outlives::Component::RFC1214(subcomponents) => {
let suborigin = infer::RFC1214Subregion(Rc::new(origin));
components_must_outlive(rcx, suborigin, subcomponents, region);
}
}
}
}

View File

@ -1,673 +0,0 @@
// Copyright 2014 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 astconv::AstConv;
use check::{FnCtxt, Inherited, blank_fn_ctxt, regionck, wfcheck};
use constrained_type_params::{identify_constrained_type_params, Parameter};
use CrateCtxt;
use middle::region;
use middle::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
use middle::traits;
use middle::ty::{self, Ty};
use middle::ty::fold::{TypeFolder, TypeFoldable, super_fold_ty};
use std::cell::RefCell;
use std::collections::HashSet;
use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::parse::token::special_idents;
use rustc_front::intravisit::{self, Visitor, FnKind};
use rustc_front::hir;
pub struct CheckTypeWellFormedVisitor<'ccx, 'tcx:'ccx> {
ccx: &'ccx CrateCtxt<'ccx, 'tcx>,
cache: HashSet<Ty<'tcx>>
}
impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
pub fn new(ccx: &'ccx CrateCtxt<'ccx, 'tcx>) -> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
CheckTypeWellFormedVisitor { ccx: ccx, cache: HashSet::new() }
}
fn tcx(&self) -> &ty::ctxt<'tcx> {
self.ccx.tcx
}
/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
/// well-formed, meaning that they do not require any constraints not declared in the struct
/// definition itself. For example, this definition would be illegal:
///
/// struct Ref<'a, T> { x: &'a T }
///
/// because the type did not declare that `T:'a`.
///
/// We do this check as a pre-pass before checking fn bodies because if these constraints are
/// not included it frequently leads to confusing errors in fn bodies. So it's better to check
/// the types first.
fn check_item_well_formed(&mut self, item: &hir::Item) {
let ccx = self.ccx;
debug!("check_item_well_formed(it.id={}, it.name={})",
item.id,
ccx.tcx.item_path_str(ccx.tcx.map.local_def_id(item.id)));
match item.node {
/// Right now we check that every default trait implementation
/// has an implementation of itself. Basically, a case like:
///
/// `impl Trait for T {}`
///
/// has a requirement of `T: Trait` which was required for default
/// method implementations. Although this could be improved now that
/// there's a better infrastructure in place for this, it's being left
/// for a follow-up work.
///
/// Since there's such a requirement, we need to check *just* positive
/// implementations, otherwise things like:
///
/// impl !Send for T {}
///
/// won't be allowed unless there's an *explicit* implementation of `Send`
/// for `T`
hir::ItemImpl(_, hir::ImplPolarity::Positive, _, _, _, _) => {
self.check_impl(item);
}
hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), _, _) => {
let item_def_id = ccx.tcx.map.local_def_id(item.id);
let trait_ref = ccx.tcx.impl_trait_ref(item_def_id).unwrap();
ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id);
match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
Some(ty::BoundSend) | Some(ty::BoundSync) => {}
Some(_) | None => {
if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
wfcheck::error_192(ccx, item.span);
}
}
}
}
hir::ItemFn(..) => {
self.check_item_type(item);
}
hir::ItemStatic(..) => {
self.check_item_type(item);
}
hir::ItemConst(..) => {
self.check_item_type(item);
}
hir::ItemStruct(ref struct_def, ref ast_generics) => {
self.check_type_defn(item, |fcx| {
vec![struct_variant(fcx, struct_def)]
});
self.check_variances_for_type_defn(item, ast_generics);
}
hir::ItemEnum(ref enum_def, ref ast_generics) => {
self.check_type_defn(item, |fcx| {
enum_variants(fcx, enum_def)
});
self.check_variances_for_type_defn(item, ast_generics);
}
hir::ItemTrait(_, _, _, ref items) => {
let trait_predicates =
ccx.tcx.lookup_predicates(ccx.tcx.map.local_def_id(item.id));
reject_non_type_param_bounds(ccx.tcx, item.span, &trait_predicates);
if ccx.tcx.trait_has_default_impl(ccx.tcx.map.local_def_id(item.id)) {
if !items.is_empty() {
wfcheck::error_380(ccx, item.span);
}
}
}
_ => {}
}
}
fn with_fcx<F>(&mut self, item: &hir::Item, mut f: F) where
F: for<'fcx> FnMut(&mut CheckTypeWellFormedVisitor<'ccx, 'tcx>, &FnCtxt<'fcx, 'tcx>),
{
let ccx = self.ccx;
let item_def_id = ccx.tcx.map.local_def_id(item.id);
let type_scheme = ccx.tcx.lookup_item_type(item_def_id);
let type_predicates = ccx.tcx.lookup_predicates(item_def_id);
reject_non_type_param_bounds(ccx.tcx, item.span, &type_predicates);
let free_id_outlive = ccx.tcx.region_maps.item_extent(item.id);
let param_env = ccx.tcx.construct_parameter_environment(item.span,
&type_scheme.generics,
&type_predicates,
free_id_outlive);
let tables = RefCell::new(ty::Tables::empty());
let inh = Inherited::new(ccx.tcx, &tables, param_env);
let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(type_scheme.ty), item.id);
f(self, &fcx);
fcx.select_all_obligations_or_error();
regionck::regionck_item(&fcx, item.id, item.span, &[]);
}
/// In a type definition, we check that to ensure that the types of the fields are well-formed.
fn check_type_defn<F>(&mut self, item: &hir::Item, mut lookup_fields: F) where
F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>) -> Vec<AdtVariant<'tcx>>,
{
self.with_fcx(item, |this, fcx| {
let variants = lookup_fields(fcx);
let mut bounds_checker = BoundsChecker::new(fcx,
item.id,
Some(&mut this.cache));
debug!("check_type_defn at bounds_checker.scope: {:?}", bounds_checker.scope);
for variant in &variants {
for field in &variant.fields {
// Regions are checked below.
bounds_checker.check_traits_in_ty(field.ty, field.span);
}
// For DST, all intermediate types must be sized.
if let Some((_, fields)) = variant.fields.split_last() {
for field in fields {
fcx.register_builtin_bound(
field.ty,
ty::BoundSized,
traits::ObligationCause::new(field.span,
fcx.body_id,
traits::FieldSized));
}
}
}
for field in variants.iter().flat_map(|v| v.fields.iter()) {
fcx.register_old_wf_obligation(field.ty, field.span, traits::MiscObligation);
}
});
}
fn check_item_type(&mut self,
item: &hir::Item)
{
self.with_fcx(item, |this, fcx| {
let mut bounds_checker = BoundsChecker::new(fcx,
item.id,
Some(&mut this.cache));
debug!("check_item_type at bounds_checker.scope: {:?}", bounds_checker.scope);
let item_def_id = fcx.tcx().map.local_def_id(item.id);
let type_scheme = fcx.tcx().lookup_item_type(item_def_id);
let item_ty = fcx.instantiate_type_scheme(item.span,
&fcx.inh
.infcx
.parameter_environment
.free_substs,
&type_scheme.ty);
bounds_checker.check_traits_in_ty(item_ty, item.span);
});
}
fn check_impl(&mut self,
item: &hir::Item)
{
self.with_fcx(item, |this, fcx| {
let mut bounds_checker = BoundsChecker::new(fcx,
item.id,
Some(&mut this.cache));
debug!("check_impl at bounds_checker.scope: {:?}", bounds_checker.scope);
// Find the impl self type as seen from the "inside" --
// that is, with all type parameters converted from bound
// to free.
let self_ty = fcx.tcx().node_id_to_type(item.id);
let self_ty = fcx.instantiate_type_scheme(item.span,
&fcx.inh
.infcx
.parameter_environment
.free_substs,
&self_ty);
bounds_checker.check_traits_in_ty(self_ty, item.span);
// Similarly, obtain an "inside" reference to the trait
// that the impl implements.
let trait_ref = match fcx.tcx().impl_trait_ref(fcx.tcx().map.local_def_id(item.id)) {
None => { return; }
Some(t) => { t }
};
let trait_ref = fcx.instantiate_type_scheme(item.span,
&fcx.inh
.infcx
.parameter_environment
.free_substs,
&trait_ref);
// We are stricter on the trait-ref in an impl than the
// self-type. In particular, we enforce region
// relationships. The reason for this is that (at least
// presently) "applying" an impl does not require that the
// application site check the well-formedness constraints on the
// trait reference. Instead, this is done at the impl site.
// Arguably this is wrong and we should treat the trait-reference
// the same way as we treat the self-type.
bounds_checker.check_trait_ref(&trait_ref, item.span);
let cause =
traits::ObligationCause::new(
item.span,
fcx.body_id,
traits::ItemObligation(trait_ref.def_id));
// Find the supertrait bounds. This will add `int:Bar`.
let poly_trait_ref = ty::Binder(trait_ref);
let predicates = fcx.tcx().lookup_super_predicates(poly_trait_ref.def_id());
let predicates = predicates.instantiate_supertrait(fcx.tcx(), &poly_trait_ref);
let predicates = {
let selcx = &mut traits::SelectionContext::new(fcx.infcx());
traits::normalize(selcx, cause.clone(), &predicates)
};
for predicate in predicates.value.predicates {
fcx.register_predicate(traits::Obligation::new(cause.clone(), predicate));
}
for obligation in predicates.obligations {
fcx.register_predicate(obligation);
}
});
}
fn check_variances_for_type_defn(&self,
item: &hir::Item,
ast_generics: &hir::Generics)
{
let item_def_id = self.tcx().map.local_def_id(item.id);
let ty_predicates = self.tcx().lookup_predicates(item_def_id);
let variances = self.tcx().item_variances(item_def_id);
let mut constrained_parameters: HashSet<_> =
variances.types
.iter_enumerated()
.filter(|&(_, _, &variance)| variance != ty::Bivariant)
.map(|(space, index, _)| self.param_ty(ast_generics, space, index))
.map(|p| Parameter::Type(p))
.collect();
identify_constrained_type_params(self.tcx(),
ty_predicates.predicates.as_slice(),
None,
&mut constrained_parameters);
for (space, index, _) in variances.types.iter_enumerated() {
let param_ty = self.param_ty(ast_generics, space, index);
if constrained_parameters.contains(&Parameter::Type(param_ty)) {
continue;
}
let span = self.ty_param_span(ast_generics, item, space, index);
self.report_bivariance(span, param_ty.name);
}
for (space, index, &variance) in variances.regions.iter_enumerated() {
if variance != ty::Bivariant {
continue;
}
assert_eq!(space, TypeSpace);
let span = ast_generics.lifetimes[index].lifetime.span;
let name = ast_generics.lifetimes[index].lifetime.name;
self.report_bivariance(span, name);
}
}
fn param_ty(&self,
ast_generics: &hir::Generics,
space: ParamSpace,
index: usize)
-> ty::ParamTy
{
let name = match space {
TypeSpace => ast_generics.ty_params[index].name,
SelfSpace => special_idents::type_self.name,
FnSpace => self.tcx().sess.bug("Fn space occupied?"),
};
ty::ParamTy { space: space, idx: index as u32, name: name }
}
fn ty_param_span(&self,
ast_generics: &hir::Generics,
item: &hir::Item,
space: ParamSpace,
index: usize)
-> Span
{
match space {
TypeSpace => ast_generics.ty_params[index].span,
SelfSpace => item.span,
FnSpace => self.tcx().sess.span_bug(item.span, "Fn space occupied?"),
}
}
fn report_bivariance(&self,
span: Span,
param_name: ast::Name)
{
wfcheck::error_392(self.tcx(), span, param_name);
let suggested_marker_id = self.tcx().lang_items.phantom_data();
match suggested_marker_id {
Some(def_id) => {
self.tcx().sess.fileline_help(
span,
&format!("consider removing `{}` or using a marker such as `{}`",
param_name,
self.tcx().item_path_str(def_id)));
}
None => {
// no lang items, no help!
}
}
}
}
// Reject any predicates that do not involve a type parameter.
fn reject_non_type_param_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
span: Span,
predicates: &ty::GenericPredicates<'tcx>) {
for predicate in &predicates.predicates {
match predicate {
&ty::Predicate::Trait(ty::Binder(ref tr)) => {
let found_param = tr.input_types().iter()
.flat_map(|ty| ty.walk())
.any(is_ty_param);
if !found_param { report_bound_error(tcx, span, tr.self_ty() )}
}
&ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(ty, _))) => {
let found_param = ty.walk().any(|t| is_ty_param(t));
if !found_param { report_bound_error(tcx, span, ty) }
}
_ => {}
};
}
fn report_bound_error<'t>(tcx: &ty::ctxt<'t>,
span: Span,
bounded_ty: ty::Ty<'t>) {
span_err!(tcx.sess, span, E0193,
"cannot bound type `{}`, where clause \
bounds may only be attached to types involving \
type parameters",
bounded_ty)
}
fn is_ty_param(ty: ty::Ty) -> bool {
match &ty.sty {
&ty::TyParam(_) => true,
_ => false
}
}
}
fn reject_shadowing_type_parameters<'tcx>(tcx: &ty::ctxt<'tcx>,
span: Span,
generics: &ty::Generics<'tcx>) {
let impl_params = generics.types.get_slice(subst::TypeSpace).iter()
.map(|tp| tp.name).collect::<HashSet<_>>();
for method_param in generics.types.get_slice(subst::FnSpace) {
if impl_params.contains(&method_param.name) {
wfcheck::error_194(tcx, span, method_param.name);
}
}
}
impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
fn visit_item(&mut self, i: &hir::Item) {
self.check_item_well_formed(i);
intravisit::walk_item(self, i);
}
fn visit_fn(&mut self,
fk: FnKind<'v>, fd: &'v hir::FnDecl,
b: &'v hir::Block, span: Span, id: ast::NodeId) {
match fk {
FnKind::Closure | FnKind::ItemFn(..) => {}
FnKind::Method(..) => {
match self.tcx().impl_or_trait_item(self.tcx().map.local_def_id(id)) {
ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
reject_shadowing_type_parameters(self.tcx(), span, &ty_method.generics)
}
_ => {}
}
}
}
intravisit::walk_fn(self, fk, fd, b, span)
}
fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
if let hir::MethodTraitItem(_, None) = trait_item.node {
match self.tcx().impl_or_trait_item(self.tcx().map.local_def_id(trait_item.id)) {
ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
reject_non_type_param_bounds(
self.tcx(),
trait_item.span,
&ty_method.predicates);
reject_shadowing_type_parameters(
self.tcx(),
trait_item.span,
&ty_method.generics);
}
_ => {}
}
}
intravisit::walk_trait_item(self, trait_item)
}
}
pub struct BoundsChecker<'cx,'tcx:'cx> {
fcx: &'cx FnCtxt<'cx,'tcx>,
span: Span,
scope: region::CodeExtent,
binding_count: usize,
cache: Option<&'cx mut HashSet<Ty<'tcx>>>,
}
impl<'cx,'tcx> BoundsChecker<'cx,'tcx> {
pub fn new(fcx: &'cx FnCtxt<'cx,'tcx>,
scope: ast::NodeId,
cache: Option<&'cx mut HashSet<Ty<'tcx>>>)
-> BoundsChecker<'cx,'tcx> {
let scope = fcx.tcx().region_maps.item_extent(scope);
BoundsChecker { fcx: fcx, span: DUMMY_SP, scope: scope,
cache: cache, binding_count: 0 }
}
/// Given a trait ref like `A : Trait<B>`, where `Trait` is defined as (say):
///
/// trait Trait<B:OtherTrait> : Copy { ... }
///
/// This routine will check that `B : OtherTrait` and `A : Trait<B>`. It will also recursively
/// check that the types `A` and `B` are well-formed.
///
/// Note that it does not (currently, at least) check that `A : Copy` (that check is delegated
/// to the point where impl `A : Trait<B>` is implemented).
pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, span: Span) {
let trait_predicates = self.fcx.tcx().lookup_predicates(trait_ref.def_id);
let bounds = self.fcx.instantiate_bounds(span,
trait_ref.substs,
&trait_predicates);
self.fcx.add_obligations_for_parameters(
traits::ObligationCause::new(
span,
self.fcx.body_id,
traits::ItemObligation(trait_ref.def_id)),
&bounds);
for &ty in &trait_ref.substs.types {
self.check_traits_in_ty(ty, span);
}
}
fn check_traits_in_ty(&mut self, ty: Ty<'tcx>, span: Span) {
self.span = span;
// When checking types outside of a type def'n, we ignore
// region obligations. See discussion below in fold_ty().
self.binding_count += 1;
ty.fold_with(self);
self.binding_count -= 1;
}
}
impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
fn tcx(&self) -> &ty::ctxt<'tcx> {
self.fcx.tcx()
}
fn fold_binder<T>(&mut self, binder: &ty::Binder<T>) -> ty::Binder<T>
where T : TypeFoldable<'tcx>
{
self.binding_count += 1;
let value = self.fcx.tcx().liberate_late_bound_regions(
self.scope,
binder);
debug!("BoundsChecker::fold_binder: late-bound regions replaced: {:?} at scope: {:?}",
value, self.scope);
let value = value.fold_with(self);
self.binding_count -= 1;
ty::Binder(value)
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
debug!("BoundsChecker t={:?}",
t);
match self.cache {
Some(ref mut cache) => {
if !cache.insert(t) {
// Already checked this type! Don't check again.
debug!("cached");
return t;
}
}
None => { }
}
match t.sty{
ty::TyStruct(def, substs) |
ty::TyEnum(def, substs) => {
let type_predicates = def.predicates(self.fcx.tcx());
let bounds = self.fcx.instantiate_bounds(self.span, substs,
&type_predicates);
if self.binding_count == 0 {
self.fcx.add_obligations_for_parameters(
traits::ObligationCause::new(self.span,
self.fcx.body_id,
traits::ItemObligation(def.did)),
&bounds);
} else {
// There are two circumstances in which we ignore
// region obligations.
//
// The first is when we are inside of a closure
// type. This is because in that case the region
// obligations for the parameter types are things
// that the closure body gets to assume and the
// caller must prove at the time of call. In other
// words, if there is a type like `<'a, 'b> | &'a
// &'b int |`, it is well-formed, and caller will
// have to show that `'b : 'a` at the time of
// call.
//
// The second is when we are checking for
// well-formedness outside of a type def'n or fn
// body. This is for a similar reason: in general,
// we only do WF checking for regions in the
// result of expressions and type definitions, so
// to as allow for implicit where clauses.
//
// (I believe we should do the same for traits, but
// that will require an RFC. -nmatsakis)
let bounds = filter_to_trait_obligations(bounds);
self.fcx.add_obligations_for_parameters(
traits::ObligationCause::new(self.span,
self.fcx.body_id,
traits::ItemObligation(def.did)),
&bounds);
}
self.fold_substs(substs);
}
_ => {
super_fold_ty(self, t);
}
}
t // we're not folding to produce a new type, so just return `t` here
}
}
///////////////////////////////////////////////////////////////////////////
// ADT
struct AdtVariant<'tcx> {
fields: Vec<AdtField<'tcx>>,
}
struct AdtField<'tcx> {
ty: Ty<'tcx>,
span: Span,
}
fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
struct_def: &hir::VariantData)
-> AdtVariant<'tcx> {
let fields =
struct_def.fields().iter()
.map(|field| {
let field_ty = fcx.tcx().node_id_to_type(field.node.id);
let field_ty = fcx.instantiate_type_scheme(field.span,
&fcx.inh
.infcx
.parameter_environment
.free_substs,
&field_ty);
AdtField { ty: field_ty, span: field.span }
})
.collect();
AdtVariant { fields: fields }
}
fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
enum_def: &hir::EnumDef)
-> Vec<AdtVariant<'tcx>> {
enum_def.variants.iter()
.map(|variant| struct_variant(fcx, &variant.node.data))
.collect()
}
fn filter_to_trait_obligations<'tcx>(bounds: ty::InstantiatedPredicates<'tcx>)
-> ty::InstantiatedPredicates<'tcx>
{
let mut result = ty::InstantiatedPredicates::empty();
for (space, _, predicate) in bounds.predicates.iter_enumerated() {
match *predicate {
ty::Predicate::Trait(..) |
ty::Predicate::Projection(..) => {
result.predicates.push(space, predicate.clone())
}
ty::Predicate::WellFormed(..) |
ty::Predicate::ObjectSafe(..) |
ty::Predicate::Equate(..) |
ty::Predicate::TypeOutlives(..) |
ty::Predicate::RegionOutlives(..) => {
}
}
}
result
}

View File

@ -21,7 +21,6 @@ use middle::ty::fold::{TypeFolder};
use std::cell::RefCell;
use std::collections::HashSet;
use std::rc::Rc;
use syntax::ast;
use syntax::codemap::{Span};
use syntax::parse::token::{special_idents};
@ -38,8 +37,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
-> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
CheckTypeWellFormedVisitor {
ccx: ccx,
code: traits::ObligationCauseCode::RFC1214(
Rc::new(traits::ObligationCauseCode::MiscObligation))
code: traits::ObligationCauseCode::MiscObligation
}
}
@ -311,8 +309,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
ty::wf::trait_obligations(fcx.infcx(),
fcx.body_id,
&trait_ref,
ast_trait_ref.path.span,
true);
ast_trait_ref.path.span);
for obligation in obligations {
fcx.register_predicate(obligation);
}
@ -343,8 +340,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
.flat_map(|p| ty::wf::predicate_obligations(fcx.infcx(),
fcx.body_id,
p,
span,
true));
span));
for obligation in obligations {
fcx.register_predicate(obligation);

View File

@ -190,7 +190,7 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
None => { }
}
}
hir::ItemImpl(_, _, _, Some(_), ref self_ty, _) => {
hir::ItemImpl(_, _, _, Some(_), _, _) => {
let impl_def_id = self.tcx.map.local_def_id(item.id);
let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
let trait_def_id = trait_ref.def_id;
@ -200,16 +200,10 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
if !traits::is_object_safe(self.tcx, data.principal_def_id()) {
// FIXME(#27579). This just means the
// self-ty is illegal; WF will report this
// error. But it will do so as a warning
// for a release or two. For backwards
// compat reasons, then, we continue to
// report it here so that things which
// were errors remain errors.
span_err!(self.tcx.sess, self_ty.span, E0372,
"the trait `{}` cannot be made into an object",
self.tcx.item_path_str(data.principal_def_id()));
// This is an error, but it will be
// reported by wfcheck. Ignore it
// here. This is tested by
// `coherence-impl-trait-for-trait-object-safe.rs`.
} else {
let mut supertrait_def_ids =
traits::supertrait_def_ids(self.tcx, data.principal_def_id());

View File

@ -3114,14 +3114,6 @@ impl Baz for Bar { } // Note: This is OK
```
"##,
E0372: r##"
Trying to implement a trait for a trait object (as in `impl Trait1 for
Trait2 { ... }`) does not work if the trait is not object-safe. Please see the
[RFC 255] for more details on object safety rules.
[RFC 255]: https://github.com/rust-lang/rfcs/pull/255
"##,
E0379: r##"
Trait methods cannot be declared `const` by design. For more information, see
[RFC 911].
@ -3486,6 +3478,7 @@ register_diagnostics! {
// E0319, // trait impls for defaulted traits allowed just for structs/enums
E0320, // recursive overflow during dropck
E0328, // cannot implement Unsize explicitly
// E0372, // coherence not object safe
E0374, // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures with one field being coerced, none found
E0375, // the trait `CoerceUnsized` may only be implemented for a coercion

View File

@ -346,8 +346,8 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
coherence::check_coherence(&ccx));
});
time(time_passes, "wf checking (old)", ||
check::check_wf_old(&ccx));
time(time_passes, "wf checking", ||
check::check_wf_new(&ccx));
time(time_passes, "item-types checking", ||
check::check_item_types(&ccx));
@ -358,11 +358,6 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
time(time_passes, "drop-impl checking", ||
check::check_drop_impls(&ccx));
// Do this last so that if there are errors in the old code, they
// get reported, and we don't get extra warnings.
time(time_passes, "wf checking (new)", ||
check::check_wf_new(&ccx));
check_for_entry_fn(&ccx);
tcx.sess.abort_if_errors();
}

View File

@ -13,7 +13,7 @@
#![crate_type="lib"]
pub trait Bar {
pub trait Bar: Sized {
type T;
fn get(x: Option<Self>) -> <Self as Bar>::T;

View File

@ -11,7 +11,7 @@
#![crate_name="static_methods_crate"]
#![crate_type = "lib"]
pub trait read {
pub trait read: Sized {
fn readMaybe(s: String) -> Option<Self>;
}

View File

@ -25,10 +25,7 @@ trait Get {
trait Other {
fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
// (note that we no longer catch the error here, since the
// error below aborts compilation.
// See also associated-types-no-suitable-supertrait-2.rs
// which checks that this error would be caught eventually.)
//~^ ERROR the trait `Get` is not implemented for the type `Self`
}
impl<T:Get> Other for T {

View File

@ -13,7 +13,7 @@
use std::sync::mpsc::{channel, Sender};
trait Foo : Sync+'static {
trait Foo : Sized+Sync+'static {
fn foo(self, mut chan: Sender<Self>) { }
}

View File

@ -13,9 +13,7 @@
// If the trait is not object-safe, we give a more tailored message
// because we're such schnuckels:
trait NotObjectSafe { fn eq(&self, other: &Self); }
impl NotObjectSafe for NotObjectSafe { //~ ERROR E0372
fn eq(&self, other: &Self) { panic!(); }
}
trait NotObjectSafe { fn eq(&self, other: Self); }
impl NotObjectSafe for NotObjectSafe { } //~ ERROR E0038
fn main() { }

View File

@ -21,14 +21,15 @@ trait Foo<X,Y>: Bar<X> {
trait Bar<X> { }
fn vacuous<A>()
// We don't always check where clauses for sanity, but in this case
// wfcheck does report an error here:
fn vacuous<A>() //~ ERROR the trait `Bar<u32>` is not implemented for the type `i32`
where i32: Foo<u32, A>
{
// vacuous could never be called, because it requires that i32:
// Bar<u32>. But the code doesn't check that this could never be
// satisfied.
// ... the original intention was to check that we don't use that
// vacuous where clause (which could never be satisfied) to accept
// the following line and then mess up calls elsewhere.
require::<i32, u32>();
//~^ ERROR the trait `Bar<u32>` is not implemented for the type `i32`
}
fn require<A,B>()

View File

@ -10,7 +10,7 @@
trait FromStructReader<'a> { }
trait ResponseHook {
fn get<'a, T: FromStructReader<'a>>(&'a self);
fn get(&self);
}
fn foo(res : Box<ResponseHook>) { res.get } //~ ERROR attempted to take value of method
fn main() {}

View File

@ -13,11 +13,14 @@ trait Node {
}
trait Graph<N: Node> {
fn nodes<'a, I: Iterator<Item=&'a N>>(&'a self) -> I;
fn nodes<'a, I: Iterator<Item=&'a N>>(&'a self) -> I
where N: 'a;
}
impl<N: Node> Graph<N> for Vec<N> {
fn nodes<'a, I: Iterator<Item=&'a N>>(&self) -> I {
fn nodes<'a, I: Iterator<Item=&'a N>>(&self) -> I
where N: 'a
{
self.iter() //~ ERROR mismatched types
}
}

View File

@ -12,7 +12,7 @@ use std::fmt::Debug;
trait Str {}
trait Something {
trait Something: Sized {
fn yay<T: Debug>(_: Option<Self>, thing: &[T]);
}

View File

@ -19,14 +19,12 @@ impl Foo for Thing {
#[inline(never)]
fn foo(b: &Bar) {
//~^ ERROR E0038
b.foo(&0)
//~^ ERROR the trait `Foo` is not implemented for the type `Bar`
//~| ERROR E0038
//~| WARNING E0038
}
fn main() {
let mut thing = Thing;
let test: &Bar = &mut thing; //~ ERROR E0038
let test: &Bar = &mut thing;
foo(test);
}

View File

@ -19,10 +19,10 @@ impl Qiz for Foo {
struct Bar {
foos: &'static [&'static (Qiz + 'static)]
//~^ ERROR E0038
}
const FOO : Foo = Foo;
const BAR : Bar = Bar { foos: &[&FOO]};
//~^ ERROR E0038
fn main() { }

View File

@ -15,13 +15,10 @@ trait From<Src> {
}
trait To {
fn to<Dst>(
self //~ error: the trait `core::marker::Sized` is not implemented
fn to<Dst>( //~ ERROR the trait `core::marker::Sized` is not implemented
self
) -> <Dst as From<Self>>::Result where Dst: From<Self> {
From::from( //~ error: the trait `core::marker::Sized` is not implemented
//~^ ERROR E0277
self
)
From::from(self)
}
}

View File

@ -38,6 +38,8 @@ impl<'a> Publisher<'a> for MyStruct<'a> {
fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
// Not obvious, but there is an implicit lifetime here -------^
//~^^ ERROR cannot infer
//~| ERROR cannot infer
//~| ERROR cannot infer
//
// The fact that `Publisher` is using an implicit lifetime is
// what was causing the debruijn accounting to be off, so

View File

@ -17,11 +17,11 @@ trait Foo {
fn foo(self);
}
fn foo<'a,'b,T>(x: &'a T, y: &'b T)
fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations required
where &'a T : Foo,
&'b T : Foo
{
x.foo(); //~ ERROR type annotations required
x.foo();
y.foo();
}

View File

@ -13,5 +13,5 @@ fn main()
{
fn bar(x:i32) ->i32 { 3*x };
let b:Box<Any> = Box::new(bar as fn(_)->_);
b.downcast_ref::<fn(_)->_>(); //~ ERROR E0101
b.downcast_ref::<fn(_)->_>(); //~ ERROR E0282
}

View File

@ -13,6 +13,6 @@ pub trait ToNbt<T> {
}
impl ToNbt<Self> {} //~ ERROR use of `Self` outside of an impl or trait
//~^ WARNING the trait `ToNbt` cannot be made into an object
//~^ ERROR the trait `ToNbt` cannot be made into an object
fn main() {}

View File

@ -18,6 +18,6 @@ struct S {
}
fn bar(_x: Foo) {}
//~^ ERROR E0277
//~^ ERROR E0038
fn main() {}

View File

@ -22,16 +22,13 @@ trait Quux {
}
fn make_bar<T:Bar>(t: &T) -> &Bar {
t
//~^ ERROR E0038
//~| NOTE method `bar` has generic type parameters
t
}
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
t as &Bar
//~^ ERROR E0038
//~| NOTE method `bar` has generic type parameters
//~| ERROR E0038
}
fn make_quux<T:Quux>(t: &T) -> &Quux {

View File

@ -25,29 +25,15 @@ trait Quux {
}
fn make_bar<T:Bar>(t: &T) -> &Bar {
t
//~^ ERROR E0038
//~| NOTE method `bar` references the `Self` type in its arguments or return type
}
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
t as &Bar
//~^ ERROR E0038
//~| NOTE method `bar` references the `Self` type in its arguments or return type
//~| ERROR E0038
loop { }
}
fn make_baz<T:Baz>(t: &T) -> &Baz {
//~^ ERROR E0038
//~| NOTE method `bar` references the `Self` type in its arguments or return type
t
//~^ ERROR E0038
//~| NOTE method `bar` references the `Self` type in its arguments or return type
}
fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
t as &Baz
//~^ ERROR E0038
//~| NOTE method `bar` references the `Self` type in its arguments or return type
//~| ERROR E0038
}
fn make_quux<T:Quux>(t: &T) -> &Quux {

View File

@ -16,16 +16,8 @@ trait Foo {
}
fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> {
b
//~^ ERROR E0038
//~| NOTE method `foo` has no receiver
}
fn foo_explicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> {
b as Box<Foo>
//~^ ERROR E0038
//~| NOTE method `foo` has no receiver
//~| ERROR E0038
//~^ ERROR E0038
loop { }
}
fn main() {

View File

@ -18,16 +18,8 @@ trait Bar
}
fn make_bar<T:Bar>(t: &T) -> &Bar {
t
//~^ ERROR E0038
//~| NOTE the trait cannot require that `Self : Sized`
}
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
t as &Bar
//~^ ERROR E0038
//~| NOTE the trait cannot require that `Self : Sized`
//~| ERROR E0038
loop { }
}
fn main() {

View File

@ -16,16 +16,9 @@ trait Bar : Sized {
}
fn make_bar<T:Bar>(t: &T) -> &Bar {
//~^ ERROR E0038
//~| NOTE the trait cannot require that `Self : Sized`
t
//~^ ERROR E0038
//~| NOTE the trait cannot require that `Self : Sized`
}
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
t as &Bar
//~^ ERROR E0038
//~| NOTE the trait cannot require that `Self : Sized`
//~| ERROR E0038
}
fn main() {

View File

@ -26,10 +26,10 @@ fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
// oh dear!
box B(&*v) as Box<X>
//~^ ERROR the parameter type `T` may not live long enough
//~| WARNING the parameter type `T` may not live long enough
//~| WARNING the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| WARNING the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
}

View File

@ -0,0 +1,21 @@
// Copyright 2012 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.
// Tests that callees correctly infer an ordering between free regions
// that appear in their parameter list. See also
// regions-free-region-ordering-caller.rs
fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
//~^ ERROR reference has a longer lifetime than the data it references
// Do not infer ordering from closure argument types.
let z: Option<&'a &'b usize> = None;
}
fn main() {}

View File

@ -30,11 +30,7 @@ fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize {
panic!();
}
fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) {
// Do not infer ordering from closure argument types.
let z: Option<&'a &'b usize> = None;
//~^ ERROR reference has a longer lifetime than the data it references
}
// see regions-free-region-ordering-callee-4.rs
fn ordering5<'a, 'b>(a: &'a usize, b: &'b usize, x: Option<&'a &'b usize>) {
let z: Option<&'a &'b usize> = None;

View File

@ -24,16 +24,13 @@ trait Trait2<'a, 'b> {
type Foo;
}
fn wf<T>() { }
// As a side-effect of the conservative process above, this argument
// is not automatically considered well-formed, since for it to be WF,
// we would need to know that `'y: 'x`, but we do not infer that.
fn callee<'x, 'y, T>(
t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
{
wf::<&'x &'y i32>();
// As a side-effect of the conservative process above, the type of
// this argument `t` is not automatically considered well-formed,
// since for it to be WF, we would need to know that `'y: 'x`, but we
// do not infer that.
fn callee<'x, 'y, T>(t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
//~^ ERROR reference has a longer lifetime than the data it references
{
}
fn main() { }

View File

@ -14,8 +14,7 @@
trait TheTrait<'t>: 't { }
struct Foo<'a,'b> {
x: Box<TheTrait<'a>+'b>
//~^ ERROR reference has a longer lifetime
x: Box<TheTrait<'a>+'b> //~ ERROR E0478
}
fn main() { }

View File

@ -1,37 +0,0 @@
// Copyright 2015 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.
// Test that an RFC1214 warning from an earlier function (`foo`) does
// not suppress an error for the same problem (`WantEq<NotEq>`,
// `NotEq: !Eq`) in a later function (`bar)`. Earlier versions of the
// warning mechanism had an issue due to caching.
#![allow(dead_code)]
#![allow(unused_variables)]
struct WantEq<T:Eq> { t: T }
struct NotEq;
trait Trait<T> { }
fn foo() {
let x: Box<Trait<WantEq<NotEq>>> = loop { };
//~^ WARN E0277
}
fn bar() {
wf::<WantEq<NotEq>>();
//~^ ERROR E0277
}
fn wf<T>() { }
fn main() { }

View File

@ -14,7 +14,7 @@ trait Iterator<A> {
fn next(&mut self) -> Option<A>;
}
trait IteratorUtil<A>
trait IteratorUtil<A>: Sized
{
fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>;
}

View File

@ -22,5 +22,4 @@ fn main() {
//~^ ERROR E0038
//~| ERROR E0038
//~| ERROR E0277
//~| WARNING E0038
}

View File

@ -0,0 +1,36 @@
// Copyright 2015 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.
// ignore-tidy-linelength
// Test that when a `..` impl applies, we also check that any
// supertrait conditions are met.
#![feature(optin_builtin_traits)]
trait NotImplemented { }
trait MyTrait: Sized
where Option<Self> : NotImplemented
{}
impl NotImplemented for i32 {}
impl MyTrait for .. {}
fn bar<T:NotImplemented>() { }
fn test() {
bar::<Option<i32>>();
//~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<i32>`
}
fn main() {
}

View File

@ -17,7 +17,7 @@
trait NotImplemented { }
trait MyTrait
trait MyTrait: Sized
where Option<Self> : NotImplemented
{}
@ -26,20 +26,11 @@ impl NotImplemented for i32 {}
impl MyTrait for .. {}
fn foo<T:MyTrait>() {
bar::<Option<T>>()
//~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<T>`
//
// This should probably typecheck. This is #20671.
}
fn bar<T:NotImplemented>() { }
fn test() {
bar::<Option<i32>>();
//~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<i32>`
}
fn main() {
foo::<u32>();
//~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<u32>`
}

View File

@ -15,13 +15,13 @@ trait Get {
}
fn get_min_from_max<'min, 'max, G>()
where 'max : 'min, &'max G : Get
where 'max : 'min, &'max G : Get, G : 'max
{
impls_get::<&'min G>(); //~ ERROR mismatched types
}
fn get_max_from_min<'min, 'max, G>()
where 'max : 'min, &'min G : Get
where 'max : 'min, &'min G : Get, G : 'min
{
impls_get::<&'max G>(); //~ ERROR mismatched types
}

View File

@ -14,8 +14,8 @@
#![allow(dead_code)]
struct Foo {
foo: [[u8]], //~ WARN E0277
foo: [[u8]], //~ ERROR E0277
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -16,11 +16,11 @@
trait ExtraCopy<T:Copy> { }
enum SomeEnum<T,U> //~ WARN E0277
enum SomeEnum<T,U> //~ ERROR E0277
where T: ExtraCopy<U>
{
SomeVariant(T,U)
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -16,9 +16,9 @@
trait ExtraCopy<T:Copy> { }
fn foo<T,U>() where T: ExtraCopy<U> //~ WARN E0277
fn foo<T,U>() where T: ExtraCopy<U> //~ ERROR E0277
{
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -17,8 +17,8 @@ pub trait Foo<'a> {
}
impl<'a, T> Foo<'a> for T {
type Bar = &'a T; //~ WARN E0309
type Bar = &'a T; //~ ERROR E0309
}
#[rustc_error]
fn main() { } //~ ERROR compilation
fn main() { }

View File

@ -25,9 +25,9 @@ pub trait Foo {
impl<T> Foo for T {
type Bar = MySet<T>;
//~^ WARN the trait `MyHash` is not implemented for the type `T`
//~^ ERROR the trait `MyHash` is not implemented for the type `T`
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -20,13 +20,13 @@ struct MustBeCopy<T:Copy> {
struct Foo<T> {
// needs T: 'static
x: fn() -> &'static T //~ WARN E0310
x: fn() -> &'static T //~ ERROR E0310
}
struct Bar<T> {
// needs T: Copy
x: fn(&'static T) //~ WARN E0310
x: fn(&'static T) //~ ERROR E0310
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -16,10 +16,10 @@
trait MustBeCopy<T:Copy> {
}
fn bar<T,U>() //~ WARN E0277
fn bar<T,U>() //~ ERROR E0277
where T: MustBeCopy<U>
{
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -21,8 +21,8 @@ struct MustBeCopy<T:Copy> {
struct Foo<T> {
// needs T: 'static
x: Object<&'static T> //~ WARN E0310
x: Object<&'static T> //~ ERROR E0310
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -19,9 +19,9 @@ trait ExtraCopy<T:Copy> { }
struct Foo<T,U>(T,U);
impl<T,U> Foo<T,U> {
fn foo(self) where T: ExtraCopy<U> //~ WARN E0277
fn foo(self) where T: ExtraCopy<U> //~ ERROR E0277
{}
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -18,9 +18,9 @@ trait ExtraCopy<T:Copy> { }
struct Foo<T,U>(T,U);
impl<T,U> Foo<T,U> where T: ExtraCopy<U> //~ WARN E0277
impl<T,U> Foo<T,U> where T: ExtraCopy<U> //~ ERROR E0277
{
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -19,14 +19,14 @@ trait Trait<T> { }
struct Foo<'a,T> {
f: &'a fn(T),
//~^ WARN E0309
//~^ ERROR E0309
}
struct Bar<'a,T> {
f: &'a Trait<T>,
//~^ WARN E0309
//~^ ERROR E0309
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -16,11 +16,11 @@
trait ExtraCopy<T:Copy> { }
struct SomeStruct<T,U> //~ WARN E0277
struct SomeStruct<T,U> //~ ERROR E0277
where T: ExtraCopy<U>
{
data: (T,U)
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -16,9 +16,9 @@
trait ExtraCopy<T:Copy> { }
trait SomeTrait<T> { //~ WARN E0277
trait SomeTrait<T> { //~ ERROR E0277
type Type1: ExtraCopy<T>;
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -17,8 +17,8 @@
trait SomeTrait<'a> {
type Type1;
type Type2 = &'a Self::Type1;
//~^ WARN E0309
//~^ ERROR E0309
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -19,8 +19,8 @@ struct IsCopy<T:Copy> { x: T }
trait SomeTrait {
type Type1;
type Type2 = IsCopy<Self::Type1>;
//~^ WARN E0277
//~^ ERROR E0277
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -16,10 +16,10 @@
trait ExtraCopy<T:Copy> { }
trait SomeTrait<T,U> //~ WARN E0277
trait SomeTrait<T,U> //~ ERROR E0277
where T: ExtraCopy<U>
{
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -19,11 +19,11 @@ struct Bar<T:Eq+?Sized> { value: Box<T> }
trait Foo {
fn bar(&self, x: &Bar<Self>) {
//~^ WARN E0277
//~^ ERROR E0277
//
// Here, Eq ought to be implemented.
}
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -19,12 +19,11 @@ struct Bar<T:Eq+?Sized> { value: Box<T> }
trait Foo {
fn bar(&self) -> Bar<Self> {
//~^ WARN E0277
//~^ ERROR E0277
//
// Here, Eq ought to be implemented.
loop { }
}
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -19,11 +19,11 @@ trait Bar<T:Eq+?Sized> { }
trait Foo {
fn bar<A>(&self) where A: Bar<Self> {
//~^ WARN E0277
//~^ ERROR E0277
//
// Here, Eq ought to be implemented.
}
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -18,10 +18,9 @@ struct Bar<T:Eq+?Sized> { value: Box<T> }
trait Foo {
fn bar(&self, x: &Bar<Self>);
//~^ WARN E0277
//~^ ERROR E0277
//
// Here, Eq ought to be implemented.
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -18,10 +18,9 @@ struct Bar<T:Eq+?Sized> { value: Box<T> }
trait Foo {
fn bar(&self) -> &Bar<Self>;
//~^ WARN E0277
//~^ ERROR E0277
//
// Here, Eq ought to be implemented.
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -18,10 +18,10 @@ struct Bar<T:Eq+?Sized> { value: Box<T> }
trait Foo {
fn bar(&self) where Bar<Self>: Copy;
//~^ WARN E0277
//~^ ERROR E0277
//
// Here, Eq ought to be implemented.
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -16,8 +16,7 @@
trait ExtraCopy<T:Copy> { }
trait SomeTrait<T>: ExtraCopy<T> { //~ WARN E0277
trait SomeTrait<T>: ExtraCopy<T> { //~ ERROR E0277
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful
fn main() { }

View File

@ -15,4 +15,6 @@
trait Chromosome<X: Chromosome<i32>> {
}
impl Chromosome<i32> for i32 { }
fn main() { }

View File

@ -22,4 +22,12 @@ trait Get<A> {
struct Struct<C:Chromosome> { c: C }
impl Chromosome for i32 { }
impl Get<Struct<i32>> for i32 {
fn get(&self) -> Struct<i32> {
Struct { c: *self }
}
}
fn main() { }

View File

@ -14,7 +14,9 @@ fn main() {
println!("{:?}",y);
}
trait Foo {
trait Foo
where for<'a> &'a Self: Bar
{
fn foo<'a>(&'a self) -> <&'a Self as Bar>::Output;
}

View File

@ -22,7 +22,7 @@ pub fn size_of_val<T>(val: &T) -> usize {
val.size_of_val()
}
pub trait TypeInfo {
pub trait TypeInfo: Sized {
fn size_of(_lame_type_hint: Option<Self>) -> usize;
fn size_of_val(&self) -> usize;
}

View File

@ -17,7 +17,7 @@
use std::ops::Deref;
pub trait ToOwned {
pub trait ToOwned: Sized {
type Owned: Borrow<Self>;
fn to_owned(&self) -> Self::Owned;
}

View File

@ -22,7 +22,7 @@ trait UseLife01 {
}
trait UseLife02 {
fn refs<'a, T, H: HasType<&'a T>>(&'a self) -> H;
fn refs<'a, T: 'a, H: HasType<&'a T>>(&'a self) -> H;
}
@ -33,7 +33,7 @@ pub trait HasType<T>
trait UseLife03<T> {
fn refs<'a, H: HasType<&'a T>>(&'a self) -> H;
fn refs<'a, H: HasType<&'a T>>(&'a self) -> H where T: 'a;
}
@ -45,7 +45,7 @@ pub fn top_refs_1<'a, H: HasLife<'a>>(_s: &'a ()) -> H {
unimplemented!()
}
pub fn top_refs_2<'a, T, H: HasType<&'a T>>(_s: &'a ()) -> H {
pub fn top_refs_2<'a, T: 'a, H: HasType<&'a T>>(_s: &'a ()) -> H {
unimplemented!()
}

View File

@ -16,7 +16,7 @@
use std::cmp::PartialOrd;
pub trait NumCast {
pub trait NumCast: Sized {
fn from(i: i32) -> Option<Self>;
}

View File

@ -10,7 +10,7 @@
// pretty-expanded FIXME #23616
pub trait NumCast {
pub trait NumCast: Sized {
fn from(i: i32) -> Option<Self>;
}

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub trait NumCast {
pub trait NumCast: Sized {
fn from(i: i32) -> Option<Self>;
}

View File

@ -10,7 +10,7 @@
// pretty-expanded FIXME #23616
pub trait NumCast {
pub trait NumCast: Sized {
fn from(i: i32) -> Option<Self>;
}

View File

@ -17,7 +17,7 @@ pub trait FuzzyEq<Eps> {
fn fuzzy_eq_eps(&self, other: &Self, epsilon: &Eps) -> bool;
}
trait Float: FuzzyEq<Self> {
trait Float: Sized+FuzzyEq<Self> {
fn two_pi() -> Self;
}

View File

@ -12,7 +12,7 @@ trait Foo<T> {
fn f(&self, x: &T);
}
trait Bar : Foo<Self> {
trait Bar : Sized + Foo<Self> {
fn g(&self);
}

View File

@ -13,7 +13,7 @@ pub trait Add<RHS,Result> {
fn add(&self, rhs: &RHS) -> Result;
}
trait MyNum : Add<Self,Self> { }
trait MyNum : Sized + Add<Self,Self> { }
struct MyInt { val: isize }

View File

@ -17,7 +17,7 @@ trait Add<RHS,Result>: Panda<RHS> {
fn add(&self, rhs: &RHS) -> Result;
}
trait MyNum : Add<Self,Self> { }
trait MyNum : Sized + Add<Self,Self> { }
struct MyInt { val: isize }

View File

@ -67,26 +67,26 @@ fn f7<X: ?Sized+T3>(x: &X) {
trait T4<X> {
fn dummy(&self) { }
fn m1(x: &T4<X>, y: X);
fn m2(x: &T5<X>, y: X);
fn m1(&self, x: &T4<X>, y: X);
fn m2(&self, x: &T5<X>, y: X);
}
trait T5<X: ?Sized> {
fn dummy(&self) { }
// not an error (for now)
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
fn m1(&self, x: &T4<X>);
fn m2(&self, x: &T5<X>);
}
trait T6<X: T> {
fn dummy(&self) { }
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
fn m1(&self, x: &T4<X>);
fn m2(&self, x: &T5<X>);
}
trait T7<X: ?Sized+T> {
fn dummy(&self) { }
// not an error (for now)
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
fn m1(&self, x: &T4<X>);
fn m2(&self, x: &T5<X>);
}
// The last field in a struct or variant may be unsized