diff options
| author | Jared Roesch <roeschinc@gmail.com> | 2016-08-16 22:48:09 -0700 |
|---|---|---|
| committer | Jared Roesch <roeschinc@gmail.com> | 2016-09-02 11:58:02 -0700 |
| commit | 352fac95ad5305bf8b0e482b8255b2b0057adf09 (patch) | |
| tree | 500da3f0af1651d3ab4509f87c32f72b83c735d2 /src | |
| parent | f18c99072e6b9ec0075d913ea6454f0c5e75881c (diff) | |
| download | rust-352fac95ad5305bf8b0e482b8255b2b0057adf09.tar.gz rust-352fac95ad5305bf8b0e482b8255b2b0057adf09.zip | |
Reject certain auto trait declarations
Fixes #29859
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/ty/mod.rs | 10 | ||||
| -rw-r--r-- | src/librustc_typeck/check/wfcheck.rs | 53 | ||||
| -rw-r--r-- | src/librustc_typeck/diagnostics.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-29859-2.rs | 15 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-29859.rs | 6 |
5 files changed, 70 insertions, 16 deletions
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index e9c01f5bad6..414e7b71f7c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -762,6 +762,16 @@ pub struct GenericPredicates<'tcx> { } impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { + pub fn empty() -> GenericPredicates<'tcx> { + GenericPredicates { + predicates: VecPerParamSpace::empty(), + } + } + + pub fn is_empty(&self) -> bool { + self.predicates.is_empty() + } + pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) -> InstantiatedPredicates<'tcx> { let mut instantiated = InstantiatedPredicates::empty(); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 435442bd30a..0117dfa6730 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -251,6 +251,36 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { }); } + fn check_auto_trait(&mut self, + trait_def_id: DefId, + span: Span) + { + let predicates = self.tcx().lookup_predicates(trait_def_id); + + // If we must exclude the Self : Trait predicate contained by all + // traits. + let no_refl_predicates : Vec<_> = + predicates.predicates.iter().filter(|predicate| { + match *predicate { + &ty::Predicate::Trait(ref poly_trait_ref) => + poly_trait_ref.def_id() != trait_def_id, + _ => true, + } + }).collect(); + + let trait_def = self.tcx().lookup_trait_def(trait_def_id); + + // We use an if-else here, since the generics will also trigger + // an extraneous error message when we find predicates like + // `T : Sized` for a trait like: `trait Magic<T>`. + if !trait_def.generics.types.get_slice(ParamSpace::TypeSpace).is_empty() { + error_566(self.ccx, span); + } else if !no_refl_predicates.is_empty() { + error_565(self.ccx, span); + } + + } + fn check_trait(&mut self, item: &hir::Item, items: &[hir::TraitItem]) @@ -258,9 +288,18 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { let trait_def_id = self.tcx().map.local_def_id(item.id); if self.tcx().trait_has_default_impl(trait_def_id) { + // We want to both ensure: + // 1) that there are no items contained within + // the trait defintion + // + // 2) that the definition doesn't violate the no-super trait rule + // for auto traits. + if !items.is_empty() { error_380(self.ccx, item.span); } + + self.check_auto_trait(trait_def_id, item.span); } self.for_item(item).with_fcx(|fcx, this| { @@ -272,6 +311,8 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { }); } + + fn check_item_fn(&mut self, item: &hir::Item, body: &hir::Block) @@ -637,6 +678,18 @@ fn error_380(ccx: &CrateCtxt, span: Span) { Trait for ..`) must have no methods or associated items") } +fn error_565(ccx: &CrateCtxt, span: Span) { + span_err!(ccx.tcx.sess, span, E0565, + "traits with default impls (`e.g. unsafe impl \ + Trait for ..`) can not have predicates") +} + +fn error_566(ccx: &CrateCtxt, span: Span) { + span_err!(ccx.tcx.sess, span, E0566, + "traits with default impls (`e.g. unsafe impl \ + Trait for ..`) can not have type parameters") +} + fn error_392<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, span: Span, param_name: ast::Name) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!(ccx.tcx.sess, span, E0392, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 3f1374db369..7b7b4d2aa00 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4072,4 +4072,6 @@ register_diagnostics! { E0563, // cannot determine a type for this `impl Trait`: {} E0564, // only named lifetimes are allowed in `impl Trait`, // but `{}` was found in the type `{}` + E0565, // auto-traits can not have predicates, + E0566, // auto traits can not have type parameters } diff --git a/src/test/compile-fail/issue-29859-2.rs b/src/test/compile-fail/issue-29859-2.rs index c0e50185f93..258aafb15ba 100644 --- a/src/test/compile-fail/issue-29859-2.rs +++ b/src/test/compile-fail/issue-29859-2.rs @@ -10,16 +10,5 @@ #![feature(optin_builtin_traits)] -trait Magic: Copy {} -impl Magic for .. {} -impl<T:Magic> Magic for T {} - -fn copy<T: Magic>(x: T) -> (T, T) { (x, x) } - -#[derive(Debug)] -struct NoClone; - -fn main() { - let (a, b) = copy(NoClone); //~ ERROR E0277 - println!("{:?} {:?}", a, b); -} +trait Magic<T> {} //~ E0566 +impl Magic<isize> for .. {} diff --git a/src/test/compile-fail/issue-29859.rs b/src/test/compile-fail/issue-29859.rs index c0e50185f93..3419e66af13 100644 --- a/src/test/compile-fail/issue-29859.rs +++ b/src/test/compile-fail/issue-29859.rs @@ -10,8 +10,8 @@ #![feature(optin_builtin_traits)] -trait Magic: Copy {} -impl Magic for .. {} +trait Magic: Copy {} //~ ERROR E0565 +impl Magic for .. {} impl<T:Magic> Magic for T {} fn copy<T: Magic>(x: T) -> (T, T) { (x, x) } @@ -20,6 +20,6 @@ fn copy<T: Magic>(x: T) -> (T, T) { (x, x) } struct NoClone; fn main() { - let (a, b) = copy(NoClone); //~ ERROR E0277 + let (a, b) = copy(NoClone); println!("{:?} {:?}", a, b); } |
