From db9e395c7fa453458d35a27c5d6c7ac276331986 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Sun, 23 Aug 2015 18:36:26 -0700 Subject: [PATCH] Allow where clauses involving types which don't include a type parameter. There isn't any semantic reason to disallow a `where` clause based on the fact that it doesn't contain a type parameter. --- src/librustc_typeck/check/wf.rs | 46 ------------------- ...here-clause-lifetimes-in-concrete-types.rs | 36 +++++++++++++++ 2 files changed, 36 insertions(+), 46 deletions(-) create mode 100644 src/test/compile-fail/where-clause-lifetimes-in-concrete-types.rs diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 47eb1f472c31d..50ab853c5d606 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -115,9 +115,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { self.check_variances_for_type_defn(item, ast_generics); } ast::ItemTrait(_, _, _, ref items) => { - let trait_predicates = - ccx.tcx.lookup_predicates(local_def(item.id)); - reject_non_type_param_bounds(ccx.tcx, item.span, &trait_predicates); if ccx.tcx.trait_has_default_impl(local_def(item.id)) { if !items.is_empty() { wfcheck::error_380(ccx, item.span); @@ -135,7 +132,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { let item_def_id = local_def(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 param_env = ccx.tcx.construct_parameter_environment(item.span, &type_scheme.generics, &type_predicates, @@ -367,44 +363,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { } } -// 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>) { @@ -445,10 +403,6 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> { if let ast::MethodTraitItem(_, None) = trait_item.node { match self.tcx().impl_or_trait_item(local_def(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, diff --git a/src/test/compile-fail/where-clause-lifetimes-in-concrete-types.rs b/src/test/compile-fail/where-clause-lifetimes-in-concrete-types.rs new file mode 100644 index 0000000000000..741d6c0c30925 --- /dev/null +++ b/src/test/compile-fail/where-clause-lifetimes-in-concrete-types.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +use std::cmp::PartialEq; + +struct Input<'a> { + _bytes: &'a [u8], +} + +impl <'a> PartialEq for Input<'a> { + fn eq(&self, _other: &Input<'a>) -> bool { + panic!() + } +} + +struct Input2<'a> { + i: Input<'a> +} + +impl<'a, 'b> PartialEq> for Input2<'a> where Input<'a> : PartialEq> { + fn eq(&self, other: &Input2<'b>) -> bool { + self.i == other.i + } +} + +#[rustc_error] +fn main() { } //~ ERROR compilation successful