Skip to content

Commit c6c58e7

Browse files
committed
Make wf check the bounds of built-in types
Fixes rust-lang#24957
1 parent 4ee6820 commit c6c58e7

12 files changed

+165
-33
lines changed

src/librustc/middle/traits/error_reporting.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,24 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
430430
"the return type of a function must have a \
431431
statically known size");
432432
}
433+
ObligationCauseCode::ArgumentType => {
434+
tcx.sess.span_note(
435+
cause_span,
436+
"the type of a function's argument must have a \
437+
statically known size");
438+
}
439+
ObligationCauseCode::TupleElemSized => {
440+
tcx.sess.span_note(
441+
cause_span,
442+
"tuples can only contain elements with a \
443+
statically known size");
444+
}
445+
ObligationCauseCode::VecElemSized => {
446+
tcx.sess.span_note(
447+
cause_span,
448+
"arrays can only contain elements with a \
449+
statically known size");
450+
}
433451
ObligationCauseCode::AssignmentLhsSized => {
434452
tcx.sess.span_note(
435453
cause_span,

src/librustc/middle/traits/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,17 @@ pub enum ObligationCauseCode<'tcx> {
114114
StructInitializerSized, // S { ... } must be Sized
115115
VariableType(ast::NodeId), // Type of each variable must be Sized
116116
ReturnType, // Return type must be Sized
117+
ArgumentType, // Argument type must be Sized
118+
VecElemSized, // Array element must be Sized
119+
TupleElemSized, // Tuple element must be Sized
120+
FieldSized, // Types of fields (other than the last)
121+
// in a struct must be sized.
117122
RepeatVec, // [T,..n] --> T must be Copy
118123

119124
// Captures of variable the given id by a closure (span is the
120125
// span of the closure)
121126
ClosureCapture(ast::NodeId, Span, ty::BuiltinBound),
122127

123-
// Types of fields (other than the last) in a struct must be sized.
124-
FieldSized,
125128

126129
// static items must have `Sync` type
127130
SharedStatic,

src/librustc_typeck/check/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,6 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
667667
.collect();
668668

669669
if let ty::FnConverging(ret_ty) = ret_ty {
670-
fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
671670
fn_sig_tys.push(ret_ty);
672671
}
673672

src/librustc_typeck/check/wf.rs

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use middle::region;
1616
use middle::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
1717
use middle::traits;
1818
use middle::ty::{self, Ty};
19-
use middle::ty::liberate_late_bound_regions;
2019
use middle::ty_fold::{TypeFolder, TypeFoldable, super_fold_ty};
2120
use util::ppaux::{Repr, UserString};
2221

@@ -510,10 +509,7 @@ impl<'cx,'tcx> BoundsChecker<'cx,'tcx> {
510509
&trait_predicates);
511510

512511
self.fcx.add_obligations_for_parameters(
513-
traits::ObligationCause::new(
514-
self.span,
515-
self.fcx.body_id,
516-
traits::ItemObligation(trait_ref.def_id)),
512+
self.cause(traits::ItemObligation(trait_ref.def_id)),
517513
&bounds);
518514

519515
for &ty in trait_ref.substs.types.iter() {
@@ -532,8 +528,13 @@ impl<'cx,'tcx> BoundsChecker<'cx,'tcx> {
532528
ty.fold_with(self);
533529
self.binding_count -= 1;
534530
}
531+
532+
fn cause(&self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
533+
traits::ObligationCause::new(self.span, self.fcx.body_id, code)
534+
}
535535
}
536536

537+
// Note: TypeFolder here is used as a visitor.
537538
impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
538539
fn tcx(&self) -> &ty::ctxt<'tcx> {
539540
self.fcx.tcx()
@@ -543,7 +544,7 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
543544
where T : TypeFoldable<'tcx> + Repr<'tcx>
544545
{
545546
self.binding_count += 1;
546-
let value = liberate_late_bound_regions(
547+
let value = ty::liberate_late_bound_regions(
547548
self.fcx.tcx(),
548549
region::DestructionScopeData::new(self.scope),
549550
binder);
@@ -554,6 +555,24 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
554555
ty::Binder(value)
555556
}
556557

558+
559+
fn fold_fn_sig(&mut self, sig: &ty::FnSig<'tcx>) -> ty::FnSig<'tcx> {
560+
if let ty::FnConverging(ret) = sig.output {
561+
self.fcx.register_builtin_bound(self.fold_ty(ret),
562+
ty::BoundSized,
563+
self.cause(traits::ReturnType));
564+
}
565+
566+
for input in &sig.inputs {
567+
self.fcx.register_builtin_bound(self.fold_ty(input),
568+
ty::BoundSized,
569+
self.cause(traits::ArgumentType));
570+
}
571+
572+
sig.clone()
573+
}
574+
575+
557576
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
558577
debug!("BoundsChecker t={}",
559578
t.repr(self.tcx()));
@@ -569,7 +588,23 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
569588
None => { }
570589
}
571590

572-
match t.sty{
591+
match t.sty {
592+
ty::ty_vec(ety, _) => {
593+
self.fcx.register_builtin_bound(self.fold_ty(ety),
594+
ty::BoundSized,
595+
self.cause(traits::VecElemSized));
596+
t
597+
}
598+
ty::ty_tup(ref tys) => {
599+
for ty in tys {
600+
self.fcx.register_builtin_bound(self.fold_ty(ty),
601+
ty::BoundSized,
602+
self.cause(traits::TupleElemSized)
603+
);
604+
605+
}
606+
t
607+
}
573608
ty::ty_struct(type_id, substs) |
574609
ty::ty_enum(type_id, substs) => {
575610
let type_predicates = ty::lookup_predicates(self.fcx.tcx(), type_id);
@@ -578,9 +613,7 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
578613

579614
if self.binding_count == 0 {
580615
self.fcx.add_obligations_for_parameters(
581-
traits::ObligationCause::new(self.span,
582-
self.fcx.body_id,
583-
traits::ItemObligation(type_id)),
616+
self.cause(traits::ItemObligation(type_id)),
584617
&bounds);
585618
} else {
586619
// There are two circumstances in which we ignore
@@ -605,22 +638,22 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
605638
//
606639
// (I believe we should do the same for traits, but
607640
// that will require an RFC. -nmatsakis)
641+
//
642+
// TODO(arielb1): this also seems to be triggered
643+
// when you have something like
644+
// for<'a> Trait<&'a (), &'free1 &'free2 ()>
608645
let bounds = filter_to_trait_obligations(bounds);
609646
self.fcx.add_obligations_for_parameters(
610-
traits::ObligationCause::new(self.span,
611-
self.fcx.body_id,
612-
traits::ItemObligation(type_id)),
647+
self.cause(traits::ItemObligation(type_id)),
613648
&bounds);
614649
}
615-
616650
self.fold_substs(substs);
651+
t
617652
}
618653
_ => {
619-
super_fold_ty(self, t);
654+
super_fold_ty(self, t)
620655
}
621656
}
622-
623-
t // we're not folding to produce a new type, so just return `t` here
624657
}
625658
}
626659

src/test/compile-fail/associated-types-coherence-failure.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use std::marker::PhantomData;
1515
use std::ops::Deref;
1616

17-
pub struct Cow<'a, B: ?Sized>(PhantomData<(&'a (),B)>);
17+
pub struct Cow<'a, B: ?Sized+'a>(PhantomData<(&'a (),&'a B)>);
1818

1919
/// Trait for moving into a `Cow`
2020
pub trait IntoCow<'a, B: ?Sized> {

src/test/compile-fail/issue-18107.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010

1111
pub trait AbstractRenderer {}
1212

13-
fn _create_render(_: &()) ->
14-
AbstractRenderer
13+
fn _create_render(_: &()) -> AbstractRenderer
1514
//~^ ERROR: the trait `core::marker::Sized` is not implemented
1615
{
1716
match 0 {

src/test/compile-fail/issue-23041.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
use std::any::Any;
1212
fn main()
1313
{
14-
fn bar(x:i32) ->i32 { 3*x };
15-
let b:Box<Any> = Box::new(bar as fn(_)->_);
16-
b.downcast_ref::<fn(_)->_>();
17-
//~^ ERROR cannot determine a type for this expression: unconstrained type
14+
fn bar(x:&'static i32) -> &'static i32 { x };
15+
let b:Box<Any> = Box::new(bar as fn(&'static _)->&'static _);
16+
b.downcast_ref::<fn(&_)->&_>(); //~ ERROR unconstrained type
1817
}

src/test/compile-fail/issue-24957.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
pub enum BsonValue {
12+
//~^ ERROR the trait `core::marker::Sized` is not implemented
13+
//~^^ ERROR the trait `core::marker::Sized` is not implemented
14+
A([u8]),
15+
B([BsonValue]),
16+
}
17+
18+
pub fn set_value(_v:&BsonValue)
19+
{
20+
}
21+
22+
fn main()
23+
{
24+
}

src/test/compile-fail/issue-5883.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ struct Struct {
1616

1717
fn new_struct(r: A+'static)
1818
-> Struct { //~^ ERROR the trait `core::marker::Sized` is not implemented
19-
//~^ ERROR the trait `core::marker::Sized` is not implemented
2019
Struct { r: r }
2120
}
2221

src/test/compile-fail/unsized6.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212

1313
trait T {}
1414

15+
struct T2<U, V: ?Sized>(U, V);
16+
1517
fn f1<X: ?Sized>(x: &X) {
1618
let _: X; // <-- this is OK, no bindings created, no initializer.
17-
let _: (isize, (X, isize)); // same
19+
let _: T2<isize, T2<isize, X>>;
1820
let y: X; //~ERROR the trait `core::marker::Sized` is not implemented
19-
let y: (isize, (X, isize)); //~ERROR the trait `core::marker::Sized` is not implemented
21+
let y: T2<isize, T2<isize, X>>; //~ERROR the trait `core::marker::Sized` is not implemented
2022
}
2123
fn f2<X: ?Sized + T>(x: &X) {
2224
let y: X; //~ERROR the trait `core::marker::Sized` is not implemented
@@ -34,8 +36,5 @@ fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
3436
let (y, z) = (*x3, 4); //~ERROR the trait `core::marker::Sized` is not implemented
3537
}
3638

37-
fn g1<X: ?Sized>(x: X) {} //~ERROR the trait `core::marker::Sized` is not implemented
38-
fn g2<X: ?Sized + T>(x: X) {} //~ERROR the trait `core::marker::Sized` is not implemented
39-
4039
pub fn main() {
4140
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Check that we catch attempts to create non-well-formed types
12+
13+
trait Tr {}
14+
15+
fn g1<X: ?Sized>(x: X) {} //~ERROR the trait `core::marker::Sized` is not implemented
16+
fn g2<X: ?Sized + Tr>(x: X) {} //~ERROR the trait `core::marker::Sized` is not implemented
17+
18+
fn bogus( //~ERROR the trait `core::marker::Sized` is not implemented
19+
_: [u8])
20+
{
21+
loop {}
22+
}
23+
24+
struct S<T: Tr>(T);
25+
26+
fn b1() -> &'static [(u8,fn(&'static [S<()>]))]
27+
{} //~^ ERROR the trait `Tr` is not implemented
28+
fn b2() -> fn([u8])
29+
{} //~^ ERROR the trait `core::marker::Sized` is not implemented
30+
fn b3() -> fn()->[u8]
31+
{} //~^ ERROR the trait `core::marker::Sized` is not implemented
32+
fn b4() -> &'static [[u8]]
33+
{} //~^ ERROR the trait `core::marker::Sized` is not implemented
34+
fn b5() -> &'static [[u8]; 2]
35+
{} //~^ ERROR the trait `core::marker::Sized` is not implemented
36+
fn b6() -> &'static ([u8],)
37+
{} //~^ ERROR the trait `core::marker::Sized` is not implemented
38+
fn b7() -> &'static (u32,[u8],u32)
39+
{} //~^ ERROR the trait `core::marker::Sized` is not implemented
40+
41+
fn main() {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct Wrap<'a, T: ?Sized>(&'a (), T);
12+
13+
fn foo<'a, T>(a: for<'s> fn() -> Wrap<'s, T>) where Wrap<'a, T>: Sized {
14+
//~^ ERROR mismatched types
15+
//~^^ ERROR mismatched types
16+
}
17+
18+
fn main() {}

0 commit comments

Comments
 (0)