From 707f7a1617013f7684fe81a1bba2dd77acbaaa73 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 6 Mar 2015 08:07:50 -0500 Subject: [PATCH 1/2] Check that traits with default impls have no methods fixes #23080 --- src/librustc_typeck/check/mod.rs | 28 +++++++++++++++++++++++++++ src/test/compile-fail/issue-23080.rs | 29 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/test/compile-fail/issue-23080.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 595a2295674..57469d94ce8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -465,6 +465,29 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { } } +// Check that trait with default impls (`impl Trait for ..`) contain no methods +struct DefaultedTraitVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } + +impl<'a, 'tcx> Visitor<'tcx> for DefaultedTraitVisitor<'a, 'tcx> { + fn visit_item(&mut self, item: &ast::Item) { + let tcx = self.ccx.tcx; + + match item.node { + ast::ItemTrait(_, _, _, ref trait_methods) => { + if ty::trait_has_default_impl(tcx, local_def(item.id)) && + !trait_methods.is_empty() + { + tcx.sess.span_err( + item.span, + "traits with default impls (`e.g. impl Trait for ..`) must have no \ + methods") + } + }, + _ => {}, + } + } +} + pub fn check_item_types(ccx: &CrateCtxt) { let krate = ccx.tcx.map.krate(); let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx); @@ -478,6 +501,11 @@ pub fn check_item_types(ccx: &CrateCtxt) { visit::walk_crate(&mut visit, krate); ccx.tcx.sess.abort_if_errors(); + + let mut visit = DefaultedTraitVisitor { ccx: ccx }; + visit::walk_crate(&mut visit, krate); + + ccx.tcx.sess.abort_if_errors(); } fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, diff --git a/src/test/compile-fail/issue-23080.rs b/src/test/compile-fail/issue-23080.rs new file mode 100644 index 00000000000..61b9a1a14e0 --- /dev/null +++ b/src/test/compile-fail/issue-23080.rs @@ -0,0 +1,29 @@ +// 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(optin_builtin_traits)] + +unsafe trait Trait { +//~^ error: traits with default impls (`e.g. impl Trait for ..`) must have no methods + fn method(&self) { + println!("Hello"); + } +} + +unsafe impl Trait for .. {} + +fn call_method(x: T) { + x.method(); +} + +fn main() { + // ICE + call_method(()); +} From 8a391dd8cf2ff938a392cbd177dc0a21d644d627 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 6 Mar 2015 12:14:38 -0500 Subject: [PATCH 2/2] move check into wf pass, add a test for assoc types --- src/librustc_typeck/check/mod.rs | 28 ------------------------- src/librustc_typeck/check/wf.rs | 10 ++++++++- src/test/compile-fail/issue-23080-2.rs | 29 ++++++++++++++++++++++++++ src/test/compile-fail/issue-23080.rs | 4 +++- 4 files changed, 41 insertions(+), 30 deletions(-) create mode 100644 src/test/compile-fail/issue-23080-2.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 57469d94ce8..595a2295674 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -465,29 +465,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { } } -// Check that trait with default impls (`impl Trait for ..`) contain no methods -struct DefaultedTraitVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } - -impl<'a, 'tcx> Visitor<'tcx> for DefaultedTraitVisitor<'a, 'tcx> { - fn visit_item(&mut self, item: &ast::Item) { - let tcx = self.ccx.tcx; - - match item.node { - ast::ItemTrait(_, _, _, ref trait_methods) => { - if ty::trait_has_default_impl(tcx, local_def(item.id)) && - !trait_methods.is_empty() - { - tcx.sess.span_err( - item.span, - "traits with default impls (`e.g. impl Trait for ..`) must have no \ - methods") - } - }, - _ => {}, - } - } -} - pub fn check_item_types(ccx: &CrateCtxt) { let krate = ccx.tcx.map.krate(); let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx); @@ -501,11 +478,6 @@ pub fn check_item_types(ccx: &CrateCtxt) { visit::walk_crate(&mut visit, krate); ccx.tcx.sess.abort_if_errors(); - - let mut visit = DefaultedTraitVisitor { ccx: ccx }; - visit::walk_crate(&mut visit, krate); - - ccx.tcx.sess.abort_if_errors(); } fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index aa7e2b6dcce..8185f48cb8c 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -118,7 +118,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { self.check_variances_for_type_defn(item, ast_generics); } - ast::ItemTrait(_, ref ast_generics, _, _) => { + ast::ItemTrait(_, ref ast_generics, _, ref items) => { let trait_predicates = ty::lookup_predicates(ccx.tcx, local_def(item.id)); reject_non_type_param_bounds( @@ -127,6 +127,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { &trait_predicates); self.check_variances(item, ast_generics, &trait_predicates, self.tcx().lang_items.phantom_fn()); + if ty::trait_has_default_impl(ccx.tcx, local_def(item.id)) { + if !items.is_empty() { + ccx.tcx.sess.span_err( + item.span, + "traits with default impls (`e.g. unsafe impl Trait for ..`) must \ + have no methods or associated items") + } + } } _ => {} } diff --git a/src/test/compile-fail/issue-23080-2.rs b/src/test/compile-fail/issue-23080-2.rs new file mode 100644 index 00000000000..ff5ac9de8d9 --- /dev/null +++ b/src/test/compile-fail/issue-23080-2.rs @@ -0,0 +1,29 @@ +// 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. + +// ignore-tidy-linelength + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +unsafe trait Trait: MarkerTrait { +//~^ error: traits with default impls (`e.g. unsafe impl Trait for ..`) must have no methods or associated items + type Output; +} + +unsafe impl Trait for .. {} + +fn call_method(x: T) {} + +fn main() { + // ICE + call_method(()); +} diff --git a/src/test/compile-fail/issue-23080.rs b/src/test/compile-fail/issue-23080.rs index 61b9a1a14e0..99373a69697 100644 --- a/src/test/compile-fail/issue-23080.rs +++ b/src/test/compile-fail/issue-23080.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + #![feature(optin_builtin_traits)] unsafe trait Trait { -//~^ error: traits with default impls (`e.g. impl Trait for ..`) must have no methods +//~^ error: traits with default impls (`e.g. unsafe impl Trait for ..`) must have no methods or associated items fn method(&self) { println!("Hello"); }