// 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),
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(),
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(),
_ => {
// 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(
}
}
- if is_warning {
- self.tcx.sess.note_rfc_1214(origin.span());
- }
-
self.note_region_origin(&origin);
}
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);
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(_) => {
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};
/// 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>),
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,
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TraitErrorKey<'tcx> {
- is_warning: bool,
span: Span,
predicate: ty::Predicate<'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)
}
}
}
-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>)
// 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);
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);
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());
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);
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);
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);
report_object_safety_error(infcx.tcx,
obligation.cause.span,
trait_def_id,
- violations,
- is_warning);
+ violations);
note_obligation_cause(infcx, obligation);
}
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(),
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);
}
}
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));
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
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));
}
}
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,
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
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;
}
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"
// 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)
}
}
}
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
}
}
- 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())
}
}
/// 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,
}
}
-/// 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 {
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,
// 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;
}
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 =>
// 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()
// 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
}
}
- // 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) => {
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);
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;
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();
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()
}
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 {
// 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.
vec!(),
Component::UnresolvedInferenceVariable(..) =>
vec!(),
- Component::RFC1214(components) =>
- implied_bounds_from_components(sub_region, components),
}
})
.collect()
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>> {
.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>) {
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(_) |
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) => {
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
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) {
if self.opts.treat_err_as_bug {
self.span_bug(sp, msg);
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;
}
pub mod demand;
pub mod method;
mod upvar;
-mod wf;
mod wfcheck;
mod cast;
mod closure;
}
}
-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();
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};
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),
_ =>
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);
- }
}
}
}
+++ /dev/null
-// 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
-}
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};
-> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
CheckTypeWellFormedVisitor {
ccx: ccx,
- code: traits::ObligationCauseCode::RFC1214(
- Rc::new(traits::ObligationCauseCode::MiscObligation))
+ code: traits::ObligationCauseCode::MiscObligation
}
}
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);
}
.flat_map(|p| ty::wf::predicate_obligations(fcx.infcx(),
fcx.body_id,
p,
- span,
- true));
+ span));
for obligation in obligations {
fcx.register_predicate(obligation);
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;
// 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());
```
"##,
-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].
// 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
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));
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();
}
#![crate_type="lib"]
-pub trait Bar {
+pub trait Bar: Sized {
type T;
fn get(x: Option<Self>) -> <Self as Bar>::T;
#![crate_name="static_methods_crate"]
#![crate_type = "lib"]
-pub trait read {
+pub trait read: Sized {
fn readMaybe(s: String) -> Option<Self>;
}
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 {
use std::sync::mpsc::{channel, Sender};
-trait Foo : Sync+'static {
+trait Foo : Sized+Sync+'static {
fn foo(self, mut chan: Sender<Self>) { }
}
// 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() { }
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>()
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() {}
}
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
}
}
trait Str {}
-trait Something {
+trait Something: Sized {
fn yay<T: Debug>(_: Option<Self>, thing: &[T]);
}
#[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);
}
struct Bar {
foos: &'static [&'static (Qiz + 'static)]
+//~^ ERROR E0038
}
const FOO : Foo = Foo;
const BAR : Bar = Bar { foos: &[&FOO]};
-//~^ ERROR E0038
fn main() { }
}
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)
}
}
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
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();
}
{
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
}
}
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() {}
}
fn bar(_x: Foo) {}
-//~^ ERROR E0277
+//~^ ERROR E0038
fn main() {}
}
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 {
}
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 {
- 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
+ t
}
fn make_quux<T:Quux>(t: &T) -> &Quux {
}
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() {
}
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() {
}
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
+ t
}
fn main() {
// 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
}
--- /dev/null
+// 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() {}
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;
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() { }
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() { }
+++ /dev/null
-// 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() { }
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>;
}
//~^ ERROR E0038
//~| ERROR E0038
//~| ERROR E0277
- //~| WARNING E0038
}
--- /dev/null
+// 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() {
+}
trait NotImplemented { }
-trait MyTrait
+trait MyTrait: Sized
where Option<Self> : NotImplemented
{}
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>`
}
}
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
}
#![allow(dead_code)]
struct Foo {
- foo: [[u8]], //~ WARN E0277
+ foo: [[u8]], //~ ERROR E0277
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
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() { }
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() { }
}
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() { }
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() { }
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() { }
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() { }
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() { }
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() { }
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() { }
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() { }
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() { }
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() { }
trait SomeTrait<'a> {
type Type1;
type Type2 = &'a Self::Type1;
- //~^ WARN E0309
+ //~^ ERROR E0309
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
trait SomeTrait {
type Type1;
type Type2 = IsCopy<Self::Type1>;
- //~^ WARN E0277
+ //~^ ERROR E0277
}
#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
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() { }
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() { }
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() { }
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() { }
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() { }
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() { }
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() { }
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() { }
trait Chromosome<X: Chromosome<i32>> {
}
+impl Chromosome<i32> for i32 { }
+
fn main() { }
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() { }
println!("{:?}",y);
}
-trait Foo {
+trait Foo
+ where for<'a> &'a Self: Bar
+{
fn foo<'a>(&'a self) -> <&'a Self as Bar>::Output;
}
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;
}
use std::ops::Deref;
-pub trait ToOwned {
+pub trait ToOwned: Sized {
type Owned: Borrow<Self>;
fn to_owned(&self) -> Self::Owned;
}
}
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;
}
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;
}
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!()
}
use std::cmp::PartialOrd;
-pub trait NumCast {
+pub trait NumCast: Sized {
fn from(i: i32) -> Option<Self>;
}
// pretty-expanded FIXME #23616
-pub trait NumCast {
+pub trait NumCast: Sized {
fn from(i: i32) -> Option<Self>;
}
// 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>;
}
// pretty-expanded FIXME #23616
-pub trait NumCast {
+pub trait NumCast: Sized {
fn from(i: i32) -> Option<Self>;
}
fn fuzzy_eq_eps(&self, other: &Self, epsilon: &Eps) -> bool;
}
-trait Float: FuzzyEq<Self> {
+trait Float: Sized+FuzzyEq<Self> {
fn two_pi() -> Self;
}
fn f(&self, x: &T);
}
-trait Bar : Foo<Self> {
+trait Bar : Sized + Foo<Self> {
fn g(&self);
}
fn add(&self, rhs: &RHS) -> Result;
}
-trait MyNum : Add<Self,Self> { }
+trait MyNum : Sized + Add<Self,Self> { }
struct MyInt { val: isize }
fn add(&self, rhs: &RHS) -> Result;
}
-trait MyNum : Add<Self,Self> { }
+trait MyNum : Sized + Add<Self,Self> { }
struct MyInt { val: isize }
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