Skip to content

Use more precise span when checking type definitions #26221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 12, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
32 changes: 15 additions & 17 deletions src/librustc_typeck/check/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand All @@ -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);
});
}

Expand All @@ -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);
Expand All @@ -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.
Expand All @@ -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(
Expand Down Expand Up @@ -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<Ty<'tcx>>>)
-> BoundsChecker<'cx,'tcx> {
BoundsChecker { fcx: fcx, span: span, scope: scope,
BoundsChecker { fcx: fcx, span: DUMMY_SP, scope: scope,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this span field is never used, can it be deleted? If it is used, it seems odd to use DUMMY_SP here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the patch, it is used, but not initialized here.

cache: cache, binding_count: 0 }
}

Expand All @@ -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<B>` 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;
Expand Down
20 changes: 12 additions & 8 deletions src/test/compile-fail/trait-bounds-on-structs-and-enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,27 @@ impl<T> Foo<T> {
}

struct Baz {
//~^ ERROR not implemented
a: Foo<isize>,
a: Foo<isize>, //~ ERROR not implemented
}

enum Boo {
//~^ ERROR not implemented
Quux(Bar<usize>),
Quux(Bar<usize>), //~ ERROR not implemented
}

struct Badness<U> {
//~^ ERROR not implemented
b: Foo<U>,
b: Foo<U>, //~ ERROR not implemented
}

enum MoreBadness<V> {
//~^ ERROR not implemented
EvenMoreBadness(Bar<V>),
EvenMoreBadness(Bar<V>), //~ ERROR not implemented
}

struct TupleLike(
Foo<i32>, //~ ERROR not implemented
);

enum Enum {
DictionaryLike { field: Bar<i32> }, //~ ERROR not implemented
}

trait PolyTrait<T>
Expand Down