Skip to content

Commit 21e11d5

Browse files
committed
---
yaml --- r: 171454 b: refs/heads/batch c: 2375a79 h: refs/heads/master v: v3
1 parent 28eeb58 commit 21e11d5

File tree

4 files changed

+111
-2
lines changed

4 files changed

+111
-2
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ refs/tags/0.12.0: f0c419429ef30723ceaf6b42f9b5a2aeb5d2e2d1
2929
refs/heads/issue-18208-method-dispatch-2: 9e1eae4fb9b6527315b4441cf8a0f5ca911d1671
3030
refs/heads/automation-fail: 1bf06495443584539b958873e04cc2f864ab10e4
3131
refs/heads/issue-18208-method-dispatch-3-quick-reject: 2009f85b9f99dedcec4404418eda9ddba90258a2
32-
refs/heads/batch: 3ed7f067dc0319cd9e7bb6a8253ba031d0bdf1f3
32+
refs/heads/batch: 2375a79152b8a6554c3e97a3f127fedd75f7495f
3333
refs/heads/building: 126db549b038c84269a1e4fe46f051b2c15d6970
3434
refs/heads/beta: 496dc4eae7de9d14cd49511a9acfbf5f11ae6c3f
3535
refs/heads/windistfix: 7608dbad651f02e837ed05eef3d74a6662a6e928

branches/batch/src/librustc/lint/builtin.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ impl LintPass for UnusedAttributes {
669669

670670
// FIXME: #19470 this shouldn't be needed forever
671671
"old_orphan_check",
672+
"old_impl_check",
672673
];
673674

674675
static CRATE_ATTRS: &'static [&'static str] = &[

branches/batch/src/librustc_typeck/collect.rs

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use middle::lang_items::SizedTraitLangItem;
3535
use middle::region;
3636
use middle::resolve_lifetime;
3737
use middle::subst;
38-
use middle::subst::{Substs};
38+
use middle::subst::{Substs, TypeSpace};
3939
use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
4040
use middle::ty::{self, RegionEscape, Ty, TypeScheme};
4141
use middle::ty_fold::{self, TypeFolder, TypeFoldable};
@@ -47,6 +47,7 @@ use util::ppaux;
4747
use util::ppaux::{Repr,UserString};
4848
use write_ty_to_tcx;
4949

50+
use std::collections::HashSet;
5051
use std::rc::Rc;
5152

5253
use syntax::abi;
@@ -644,6 +645,10 @@ fn convert(ccx: &CollectCtxt, it: &ast::Item) {
644645
Some(selfty),
645646
None);
646647
}
648+
649+
enforce_impl_ty_params_are_constrained(ccx.tcx,
650+
generics,
651+
local_def(it.id));
647652
},
648653
ast::ItemTrait(_, _, _, ref trait_methods) => {
649654
let trait_def = trait_def_of_item(ccx, it);
@@ -1605,3 +1610,96 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
16051610
})
16061611
}
16071612
}
1613+
1614+
/// Checks that all the type parameters on an impl
1615+
fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
1616+
ast_generics: &ast::Generics,
1617+
impl_def_id: ast::DefId)
1618+
{
1619+
let impl_scheme = ty::lookup_item_type(tcx, impl_def_id);
1620+
let impl_trait_ref = ty::impl_trait_ref(tcx, impl_def_id);
1621+
1622+
// The trait reference is an input, so find all type parameters
1623+
// reachable from there, to start (if this is an inherent impl,
1624+
// then just examine the self type).
1625+
let mut input_parameters: HashSet<_> =
1626+
impl_trait_ref.iter()
1627+
.flat_map(|t| t.input_types().iter()) // Types in trait ref, if any
1628+
.chain(Some(impl_scheme.ty).iter()) // Self type, always
1629+
.flat_map(|t| t.walk())
1630+
.filter_map(to_opt_param_ty)
1631+
.collect();
1632+
1633+
loop {
1634+
let num_inputs = input_parameters.len();
1635+
1636+
let mut projection_predicates =
1637+
impl_scheme.generics.predicates
1638+
.iter()
1639+
.filter_map(|predicate| {
1640+
match *predicate {
1641+
// Ignore higher-ranked binders. For the purposes
1642+
// of this check, they don't matter because they
1643+
// only affect named regions, and we're just
1644+
// concerned about type parameters here.
1645+
ty::Predicate::Projection(ref data) => Some(data.0.clone()),
1646+
_ => None,
1647+
}
1648+
});
1649+
1650+
for projection in projection_predicates {
1651+
// Special case: watch out for some kind of sneaky attempt
1652+
// to project out an associated type defined by this very trait.
1653+
if Some(projection.projection_ty.trait_ref.clone()) == impl_trait_ref {
1654+
continue;
1655+
}
1656+
1657+
let relies_only_on_inputs =
1658+
projection.projection_ty.trait_ref.input_types().iter()
1659+
.flat_map(|t| t.walk())
1660+
.filter_map(to_opt_param_ty)
1661+
.all(|t| input_parameters.contains(&t));
1662+
1663+
if relies_only_on_inputs {
1664+
input_parameters.extend(
1665+
projection.ty.walk().filter_map(to_opt_param_ty));
1666+
}
1667+
}
1668+
1669+
if input_parameters.len() == num_inputs {
1670+
break;
1671+
}
1672+
}
1673+
1674+
for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
1675+
let param_ty = ty::ParamTy { space: TypeSpace,
1676+
idx: index as u32,
1677+
name: ty_param.ident.name };
1678+
if !input_parameters.contains(&param_ty) {
1679+
if ty::has_attr(tcx, impl_def_id, "old_impl_check") {
1680+
tcx.sess.span_warn(
1681+
ty_param.span,
1682+
format!("the type parameter `{}` is not constrained by the \
1683+
impl trait, self type, or predicates",
1684+
param_ty.user_string(tcx)).as_slice());
1685+
} else {
1686+
tcx.sess.span_err(
1687+
ty_param.span,
1688+
format!("the type parameter `{}` is not constrained by the \
1689+
impl trait, self type, or predicates",
1690+
param_ty.user_string(tcx)).as_slice());
1691+
tcx.sess.span_help(
1692+
ty_param.span,
1693+
format!("you can temporarily opt out of this rule by placing \
1694+
the `#[old_impl_check]` attribute on the impl").as_slice());
1695+
}
1696+
}
1697+
}
1698+
1699+
fn to_opt_param_ty<'tcx>(ty: Ty<'tcx>) -> Option<ty::ParamTy> {
1700+
match ty.sty {
1701+
ty::ty_param(ref d) => Some(d.clone()),
1702+
_ => None,
1703+
}
1704+
}
1705+
}

branches/batch/src/libsyntax/feature_gate.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
8686
// A way to temporarily opt out of the new orphan rules. This will *never* be accepted.
8787
("old_orphan_check", Deprecated),
8888

89+
// A way to temporarily opt out of the new impl rules. This will *never* be accepted.
90+
("old_impl_check", Deprecated),
91+
8992
// OIBIT specific features
9093
("optin_builtin_traits", Active),
9194

@@ -294,6 +297,13 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
294297
i.span,
295298
"the new orphan check rules will eventually be strictly enforced");
296299
}
300+
301+
if attr::contains_name(i.attrs[],
302+
"old_impl_check") {
303+
self.gate_feature("old_impl_check",
304+
i.span,
305+
"`#[old_impl_check]` will be removed in the future");
306+
}
297307
}
298308

299309
_ => {}

0 commit comments

Comments
 (0)