From 16d5c83d5fe19a89ad6740ca4f53750f997e2def Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Fri, 12 Jun 2015 01:44:42 +0900 Subject: [PATCH 1/2] Use more precise span when checking type definitions --- src/librustc_typeck/check/mod.rs | 3 +- src/librustc_typeck/check/wf.rs | 32 +++++++++---------- .../trait-bounds-on-structs-and-enums.rs | 12 +++---- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 601db229c41..c524c3024eb 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1626,10 +1626,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let t = ast_ty_to_ty(self, self, ast_t); let mut bounds_checker = wf::BoundsChecker::new(self, - ast_t.span, self.body_id, None); - bounds_checker.check_ty(t); + bounds_checker.check_ty(t, ast_t.span); t } diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 62790a1d0a8..c1d260815f6 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -23,7 +23,7 @@ use util::ppaux::{Repr, UserString}; use std::collections::HashSet; use syntax::ast; use syntax::ast_util::local_def; -use syntax::codemap::Span; +use syntax::codemap::{DUMMY_SP, Span}; use syntax::parse::token::{self, special_idents}; use syntax::visit; use syntax::visit::Visitor; @@ -162,15 +162,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { self.with_fcx(item, |this, fcx| { let variants = lookup_fields(fcx); let mut bounds_checker = BoundsChecker::new(fcx, - item.span, item.id, Some(&mut this.cache)); debug!("check_type_defn at bounds_checker.scope: {:?}", bounds_checker.scope); - for variant in &variants { + for variant in &variants { for field in &variant.fields { // Regions are checked below. - bounds_checker.check_traits_in_ty(field.ty); + bounds_checker.check_traits_in_ty(field.ty, field.span); } // For DST, all intermediate types must be sized. @@ -199,7 +198,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { { self.with_fcx(item, |this, fcx| { let mut bounds_checker = BoundsChecker::new(fcx, - item.span, item.id, Some(&mut this.cache)); debug!("check_item_type at bounds_checker.scope: {:?}", bounds_checker.scope); @@ -209,7 +207,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { &fcx.inh.param_env.free_substs, &type_scheme.ty); - bounds_checker.check_traits_in_ty(item_ty); + bounds_checker.check_traits_in_ty(item_ty, item.span); }); } @@ -218,7 +216,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { { self.with_fcx(item, |this, fcx| { let mut bounds_checker = BoundsChecker::new(fcx, - item.span, item.id, Some(&mut this.cache)); debug!("check_impl at bounds_checker.scope: {:?}", bounds_checker.scope); @@ -231,7 +228,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { &fcx.inh.param_env.free_substs, &self_ty); - bounds_checker.check_traits_in_ty(self_ty); + bounds_checker.check_traits_in_ty(self_ty, item.span); // Similarly, obtain an "inside" reference to the trait // that the impl implements. @@ -252,7 +249,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { // 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); + bounds_checker.check_trait_ref(&trait_ref, item.span); let cause = traits::ObligationCause::new( @@ -483,11 +480,10 @@ pub struct BoundsChecker<'cx,'tcx:'cx> { impl<'cx,'tcx> BoundsChecker<'cx,'tcx> { pub fn new(fcx: &'cx FnCtxt<'cx,'tcx>, - span: Span, scope: ast::NodeId, cache: Option<&'cx mut HashSet>>) -> BoundsChecker<'cx,'tcx> { - BoundsChecker { fcx: fcx, span: span, scope: scope, + BoundsChecker { fcx: fcx, span: DUMMY_SP, scope: scope, cache: cache, binding_count: 0 } } @@ -500,30 +496,32 @@ impl<'cx,'tcx> BoundsChecker<'cx,'tcx> { /// /// Note that it does not (currently, at least) check that `A : Copy` (that check is delegated /// to the point where impl `A : Trait` is implemented). - pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) { + pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, span: Span) { let trait_predicates = ty::lookup_predicates(self.fcx.tcx(), trait_ref.def_id); - let bounds = self.fcx.instantiate_bounds(self.span, + let bounds = self.fcx.instantiate_bounds(span, trait_ref.substs, &trait_predicates); self.fcx.add_obligations_for_parameters( traits::ObligationCause::new( - self.span, + 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); + self.check_traits_in_ty(ty, span); } } - pub fn check_ty(&mut self, ty: Ty<'tcx>) { + pub fn check_ty(&mut self, ty: Ty<'tcx>, span: Span) { + self.span = span; ty.fold_with(self); } - fn check_traits_in_ty(&mut self, ty: Ty<'tcx>) { + 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; diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs index c18c5b386e8..9a1e4ee2471 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs @@ -32,23 +32,19 @@ impl Foo { } struct Baz { -//~^ ERROR not implemented - a: Foo, + a: Foo, //~ ERROR not implemented } enum Boo { -//~^ ERROR not implemented - Quux(Bar), + Quux(Bar), //~ ERROR not implemented } struct Badness { -//~^ ERROR not implemented - b: Foo, + b: Foo, //~ ERROR not implemented } enum MoreBadness { -//~^ ERROR not implemented - EvenMoreBadness(Bar), + EvenMoreBadness(Bar), //~ ERROR not implemented } trait PolyTrait From 793d9fcb5237f2148a7a40f2f17d4a8dcb6128cb Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Fri, 12 Jun 2015 21:09:17 +0900 Subject: [PATCH 2/2] Add tests for tuple-like structs and dictionary-like enum variants --- .../compile-fail/trait-bounds-on-structs-and-enums.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs index 9a1e4ee2471..c13f7346b11 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs @@ -47,6 +47,14 @@ enum MoreBadness { EvenMoreBadness(Bar), //~ ERROR not implemented } +struct TupleLike( + Foo, //~ ERROR not implemented +); + +enum Enum { + DictionaryLike { field: Bar }, //~ ERROR not implemented +} + trait PolyTrait { fn whatever(&self, t: T) {}