Skip to content

Commit 0732b58

Browse files
committed
rustc_typeck: ensure type alias bounds are implied by the type being well-formed.
1 parent 3d2fc45 commit 0732b58

34 files changed

+298
-159
lines changed

src/librustc_typeck/check/mod.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,12 +1316,14 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item
13161316
hir::ItemKind::Union(..) => {
13171317
check_union(tcx, it.id, it.span);
13181318
}
1319-
hir::ItemKind::Existential(..) |
1320-
hir::ItemKind::Ty(..) => {
1319+
hir::ItemKind::Existential(..)
1320+
// HACK(eddyb) This is done in `wfcheck` for type aliases, instead.
1321+
// | hir::ItemKind::Ty(..)
1322+
=> {
13211323
let def_id = tcx.hir.local_def_id(it.id);
13221324
let pty_ty = tcx.type_of(def_id);
13231325
let generics = tcx.generics_of(def_id);
1324-
check_bounds_are_used(tcx, &generics, pty_ty);
1326+
let _ = check_params_are_used(tcx, &generics, pty_ty);
13251327
}
13261328
hir::ItemKind::ForeignMod(ref m) => {
13271329
check_abi(tcx, it.span, m.abi);
@@ -5240,14 +5242,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
52405242
}
52415243
}
52425244

5243-
pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
5244-
generics: &ty::Generics,
5245-
ty: Ty<'tcx>) {
5245+
fn check_params_are_used<'a, 'tcx>(
5246+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
5247+
generics: &ty::Generics,
5248+
ty: Ty<'tcx>,
5249+
) -> Result<(), ErrorReported> {
52465250
let own_counts = generics.own_counts();
5247-
debug!("check_bounds_are_used(n_tps={}, ty={:?})", own_counts.types, ty);
5251+
debug!("check_params_are_used(n_tps={}, ty={:?})", own_counts.types, ty);
52485252

52495253
if own_counts.types == 0 {
5250-
return;
5254+
return Ok(());
52515255
}
52525256
// Make a vector of booleans initially false, set to true when used.
52535257
let mut types_used = vec![false; own_counts.types];
@@ -5260,23 +5264,26 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
52605264
// If there is already another error, do not emit
52615265
// an error for not using a type Parameter.
52625266
assert!(tcx.sess.err_count() > 0);
5263-
return;
5267+
return Err(ErrorReported);
52645268
}
52655269
}
52665270

52675271
let types = generics.params.iter().filter(|param| match param.kind {
52685272
ty::GenericParamDefKind::Type { .. } => true,
52695273
_ => false,
52705274
});
5275+
let mut result = Ok(());
52715276
for (&used, param) in types_used.iter().zip(types) {
52725277
if !used {
52735278
let id = tcx.hir.as_local_node_id(param.def_id).unwrap();
52745279
let span = tcx.hir.span(id);
52755280
struct_span_err!(tcx.sess, span, E0091, "type parameter `{}` is unused", param.name)
52765281
.span_label(span, "unused type parameter")
52775282
.emit();
5283+
result = Err(ErrorReported);
52785284
}
52795285
}
5286+
result
52805287
}
52815288

52825289
fn fatally_break_rust(sess: &Session) {

src/librustc_typeck/check/wfcheck.rs

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,53 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def
118118
hir::ItemKind::Fn(..) => {
119119
check_item_fn(tcx, item);
120120
}
121-
hir::ItemKind::Static(..) => {
122-
check_item_type(tcx, item);
123-
}
121+
hir::ItemKind::Static(..) |
124122
hir::ItemKind::Const(..) => {
125-
check_item_type(tcx, item);
123+
for_item(tcx, item).with_fcx(|fcx, _this| {
124+
let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
125+
let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
126+
127+
fcx.register_wf_obligation(item_ty, item.span, ObligationCauseCode::MiscObligation);
128+
129+
vec![] // no implied bounds in a static/const
130+
});
131+
}
132+
hir::ItemKind::Ty(..) => {
133+
let def_id = tcx.hir.local_def_id(item.id);
134+
let item_ty = tcx.type_of(def_id);
135+
let generics = tcx.generics_of(def_id);
136+
let used_params = super::check_params_are_used(tcx, &generics, item_ty);
137+
for_item(tcx, item).with_fcx(|fcx, _this| {
138+
let item_ty = fcx.normalize_associated_types_in(item.span, &item_ty);
139+
140+
// Check the user-declared bounds, assuming the type is WF.
141+
// This ensures that by checking the WF of the aliased type, where
142+
// the alias is used, we don't ignore bounds written on the alias.
143+
// NB: this check only happens if *all* type parameters are used,
144+
// otherwise every unused type parameter can cause errors here.
145+
if let Ok(()) = used_params {
146+
let user_predicates = fcx.param_env.caller_bounds;
147+
let wf_predicates = ty::wf::obligations(
148+
&fcx.infcx,
149+
fcx.param_env,
150+
fcx.body_id,
151+
item_ty,
152+
item.span,
153+
).into_iter().flatten().map(|o| o.predicate).collect();
154+
let wf_predicates = traits::elaborate_predicates(fcx.tcx, wf_predicates);
155+
let wf_param_env = ty::ParamEnv {
156+
caller_bounds: fcx.tcx.mk_predicates(wf_predicates),
157+
reveal: fcx.param_env.reveal,
158+
};
159+
fcx.register_predicates(user_predicates.iter().map(|&predicate| {
160+
let code = ObligationCauseCode::MiscObligation;
161+
let cause = traits::ObligationCause::new(item.span, fcx.body_id, code);
162+
traits::Obligation::new(cause, wf_param_env, predicate)
163+
}));
164+
}
165+
166+
vec![item_ty]
167+
});
126168
}
127169
hir::ItemKind::Struct(ref struct_def, ref ast_generics) => {
128170
check_type_defn(tcx, item, false, |fcx| {
@@ -322,21 +364,6 @@ fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
322364
})
323365
}
324366

325-
fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
326-
item: &hir::Item)
327-
{
328-
debug!("check_item_type: {:?}", item);
329-
330-
for_item(tcx, item).with_fcx(|fcx, _this| {
331-
let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
332-
let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
333-
334-
fcx.register_wf_obligation(item_ty, item.span, ObligationCauseCode::MiscObligation);
335-
336-
vec![] // no implied bounds in a const etc
337-
});
338-
}
339-
340367
fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
341368
item: &hir::Item,
342369
ast_self_ty: &hir::Ty,

src/test/incremental/hashes/type_defs.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,12 @@ type ChangeNestedTupleField = (i32, (i64, i8));
132132

133133
// Add type param --------------------------------------------------------------
134134
#[cfg(cfail1)]
135-
type AddTypeParam<T1> = (T1, T1);
135+
type AddTypeParam<T1> = (T1, Option<T1>);
136136

137137
#[cfg(not(cfail1))]
138138
#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
139139
#[rustc_clean(cfg="cfail3")]
140-
type AddTypeParam<T1, T2> = (T1, T2);
140+
type AddTypeParam<T1, T2> = (T1, Option<T2>);
141141

142142

143143

@@ -148,18 +148,18 @@ type AddTypeParamBound<T1> = (T1, u32);
148148
#[cfg(not(cfail1))]
149149
#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
150150
#[rustc_clean(cfg="cfail3")]
151-
type AddTypeParamBound<T1: Clone> = (T1, u32);
151+
type AddTypeParamBound<T1: std::any::Any> = (T1, u32);
152152

153153

154154

155155
// Add type param bound in where clause ----------------------------------------
156156
#[cfg(cfail1)]
157-
type AddTypeParamBoundWhereClause<T1> where T1: Clone = (T1, u32);
157+
type AddTypeParamBoundWhereClause<T1> where T1: Sized = (T1, u32);
158158

159159
#[cfg(not(cfail1))]
160160
#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
161161
#[rustc_clean(cfg="cfail3")]
162-
type AddTypeParamBoundWhereClause<T1> where T1: Clone+Copy = (T1, u32);
162+
type AddTypeParamBoundWhereClause<T1> where T1: Sized+std::any::Any = (T1, u32);
163163

164164

165165

@@ -203,7 +203,9 @@ where 'b: 'a,
203203

204204
// Change Trait Bound Indirectly -----------------------------------------------
205205
trait ReferencedTrait1 {}
206+
impl<T> ReferencedTrait1 for T {}
206207
trait ReferencedTrait2 {}
208+
impl<T> ReferencedTrait2 for T {}
207209

208210
mod change_trait_bound_indirectly {
209211
#[cfg(cfail1)]

src/test/run-pass/attr-on-generic-formals.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
3030
trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); }
3131

3232
type TyLt<#[rustc_lt_type] 'd> = &'d u32;
33-
type TyTy<#[rustc_ty_type] L> = (L, );
33+
type TyTy<#[rustc_ty_type] L> = Option<L>;
3434

3535
impl<#[rustc_lt_inherent] 'e> StLt<'e> { }
3636
impl<#[rustc_ty_inherent] M> StTy<M> { }

src/test/run-pass/type-param.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212

1313
// pretty-expanded FIXME #23616
1414

15-
type lteq<T> = extern fn(T) -> bool;
15+
type lteq<T: ?Sized> = extern fn(T) -> bool;
1616

1717
pub fn main() { }

src/test/ui/consts/const-eval/pub_const_err.stderr

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
warning: this constant cannot be used
2-
--> $DIR/pub_const_err.rs:16:1
1+
warning: attempt to subtract with overflow
2+
--> $DIR/pub_const_err.rs:19:22
33
|
4-
LL | pub const Z: u32 = 0 - 1;
5-
| ^^^^^^^^^^^^^^^^^^^-----^
6-
| |
7-
| attempt to subtract with overflow
4+
LL | pub type Foo = [i32; 0 - 1];
5+
| ^^^^^
86
|
97
note: lint level defined here
108
--> $DIR/pub_const_err.rs:12:9
119
|
1210
LL | #![warn(const_err)]
1311
| ^^^^^^^^^
1412

15-
warning: attempt to subtract with overflow
16-
--> $DIR/pub_const_err.rs:19:22
13+
warning: this constant cannot be used
14+
--> $DIR/pub_const_err.rs:16:1
1715
|
18-
LL | pub type Foo = [i32; 0 - 1];
19-
| ^^^^^
16+
LL | pub const Z: u32 = 0 - 1;
17+
| ^^^^^^^^^^^^^^^^^^^-----^
18+
| |
19+
| attempt to subtract with overflow
2020

2121
warning: this array length cannot be used
2222
--> $DIR/pub_const_err.rs:19:22

src/test/ui/consts/const-eval/pub_const_err_bin.stderr

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
warning: this constant cannot be used
2-
--> $DIR/pub_const_err_bin.rs:14:1
1+
warning: attempt to subtract with overflow
2+
--> $DIR/pub_const_err_bin.rs:17:22
33
|
4-
LL | pub const Z: u32 = 0 - 1;
5-
| ^^^^^^^^^^^^^^^^^^^-----^
6-
| |
7-
| attempt to subtract with overflow
4+
LL | pub type Foo = [i32; 0 - 1];
5+
| ^^^^^
86
|
97
note: lint level defined here
108
--> $DIR/pub_const_err_bin.rs:12:9
119
|
1210
LL | #![warn(const_err)]
1311
| ^^^^^^^^^
1412

15-
warning: attempt to subtract with overflow
16-
--> $DIR/pub_const_err_bin.rs:17:22
13+
warning: this constant cannot be used
14+
--> $DIR/pub_const_err_bin.rs:14:1
1715
|
18-
LL | pub type Foo = [i32; 0 - 1];
19-
| ^^^^^
16+
LL | pub const Z: u32 = 0 - 1;
17+
| ^^^^^^^^^^^^^^^^^^^-----^
18+
| |
19+
| attempt to subtract with overflow
2020

2121
warning: this array length cannot be used
2222
--> $DIR/pub_const_err_bin.rs:17:22

src/test/ui/dst/dst-bad-assign-3.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
#![feature(unsized_tuple_coercion)]
1414

15-
type Fat<T> = (isize, &'static str, T);
15+
type Fat<T: ?Sized> = (isize, &'static str, T);
1616

1717
#[derive(PartialEq,Eq)]
1818
struct Bar;

src/test/ui/feature-gates/feature-gate-trivial_bounds.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ trait T where i32: Foo {} //~ ERROR
2525

2626
union U where i32: Foo { f: i32 } //~ ERROR
2727

28-
type Y where i32: Foo = (); // OK - bound is ignored
28+
type Y where i32: Foo = (); //~ ERROR
2929

3030
impl Foo for () where i32: Foo { //~ ERROR
3131
fn test(&self) {

src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ LL | union U where i32: Foo { f: i32 } //~ ERROR
3434
= help: see issue #48214
3535
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
3636

37+
error[E0277]: the trait bound `i32: Foo` is not satisfied
38+
--> $DIR/feature-gate-trivial_bounds.rs:28:1
39+
|
40+
LL | type Y where i32: Foo = (); //~ ERROR
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
42+
|
43+
= help: see issue #48214
44+
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
45+
3746
error[E0277]: the trait bound `i32: Foo` is not satisfied
3847
--> $DIR/feature-gate-trivial_bounds.rs:30:1
3948
|
@@ -125,6 +134,6 @@ LL | | }
125134
= help: see issue #48214
126135
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
127136

128-
error: aborting due to 11 previous errors
137+
error: aborting due to 12 previous errors
129138

130139
For more information about this error, try `rustc --explain E0277`.

src/test/ui/generic/generic-param-attrs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ enum EnTy<#[rustc_ty_enum] J> { A(J), B }
2828
trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
2929
trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); }
3030
type TyLt<#[rustc_lt_type] 'd> = &'d u32;
31-
type TyTy<#[rustc_ty_type] L> = (L, );
31+
type TyTy<#[rustc_ty_type] L> = Option<L>;
3232

3333
impl<#[rustc_lt_inherent] 'e> StLt<'e> { }
3434
impl<#[rustc_ty_inherent] M> StTy<M> { }

src/test/ui/issues/issue-47715.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ union Union<T: Iterable<Item = impl Foo> + Copy> {
3131
x: T,
3232
}
3333

34-
type Type<T: Iterable<Item = impl Foo>> = T;
34+
type Type<T: Iterable<Item = impl Foo>> = Container<T>;
3535
//~^ ERROR `impl Trait` not allowed
3636

3737
fn main() {

src/test/ui/issues/issue-47715.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ LL | union Union<T: Iterable<Item = impl Foo> + Copy> {
1919
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
2020
--> $DIR/issue-47715.rs:34:30
2121
|
22-
LL | type Type<T: Iterable<Item = impl Foo>> = T;
22+
LL | type Type<T: Iterable<Item = impl Foo>> = Container<T>;
2323
| ^^^^^^^^
2424

2525
error: aborting due to 4 previous errors

src/test/ui/issues/issue-6936.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ mod t4 {
3131
}
3232

3333
mod t5 {
34-
type Bar<T> = T;
34+
type Bar<T: ?Sized> = T;
3535
mod Bar {} //~ ERROR the name `Bar` is defined multiple times
3636
}
3737

src/test/ui/issues/issue-6936.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ LL | enum Foo {} //~ ERROR the name `Foo` is defined multiple times
3131
error[E0428]: the name `Bar` is defined multiple times
3232
--> $DIR/issue-6936.rs:35:5
3333
|
34-
LL | type Bar<T> = T;
35-
| ---------------- previous definition of the type `Bar` here
34+
LL | type Bar<T: ?Sized> = T;
35+
| ------------------------ previous definition of the type `Bar` here
3636
LL | mod Bar {} //~ ERROR the name `Bar` is defined multiple times
3737
| ^^^^^^^ `Bar` redefined here
3838
|

0 commit comments

Comments
 (0)