Skip to content
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

Implement equality constraints in where clauses #22074

Closed
wants to merge 5 commits into from
Closed
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
7 changes: 5 additions & 2 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2382,13 +2382,18 @@ The currently implemented features of the reference compiler are:
semantics are likely to change, so this macro usage must be opted
into.

* `associated_types` - Allows type aliases in traits. Experimental.

* `concat_idents` - Allows use of the `concat_idents` macro, which is in many
ways insufficient for concatenating identifiers, and may be
removed entirely for something more wholesome.

* `default_type_params` - Allows use of default type parameters. The future of
this feature is uncertain.

* `equality_constraints` - Allows the use of `=` in where clauses. This
allows a user to demand that two type's normal forms are equal.

* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
are inherently unstable and no promise about them is made.

Expand Down Expand Up @@ -2465,8 +2470,6 @@ The currently implemented features of the reference compiler are:
Such items should not be allowed by the compiler to exist,
so if you need this there probably is a compiler bug.

* `associated_types` - Allows type aliases in traits. Experimental.

If a feature is promoted to a language feature, then all existing programs will
start to receive compilation warnings about #[feature] directives which enabled
the new feature (because the directive is no longer necessary). However, if a
Expand Down
16 changes: 10 additions & 6 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,12 +211,11 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
self.visit_lifetime_ref(bound);
}
}
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ id,
ref path,
ref ty,
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ ref ty_left,
ref ty_right,
.. }) => {
self.visit_path(path, id);
self.visit_ty(&**ty);
self.visit_ty(&**ty_left);
self.visit_ty(&**ty_right);
}
}
}
Expand Down Expand Up @@ -555,7 +554,12 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
collector.visit_lifetime_ref(bound);
}
}
&ast::WherePredicate::EqPredicate(_) => unimplemented!()
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref ty_left,
ref ty_right,
..}) => {
collector.visit_ty(&**ty_left);
collector.visit_ty(&**ty_right);
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1453,7 +1453,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
}
&ast::WherePredicate::RegionPredicate(_) => {}
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
self.visit_ty(&*eq_pred.ty);
self.visit_ty(&*eq_pred.ty_left);
self.visit_ty(&*eq_pred.ty_right);
}
}
}
Expand Down
13 changes: 2 additions & 11 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3205,17 +3205,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
&ast::WherePredicate::RegionPredicate(_) => {}
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) {
Some((def @ DefTyParam(..), last_private)) => {
self.record_def(eq_pred.id, (def, last_private));
}
_ => {
self.resolve_error(eq_pred.path.span,
"undeclared associated type");
}
}

self.resolve_type(&*eq_pred.ty);
self.resolve_type(&*eq_pred.ty_left);
self.resolve_type(&*eq_pred.ty_right);
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1293,10 +1293,11 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
}

&ast::WherePredicate::EqPredicate(ref eq_pred) => {
// FIXME(#20041)
ccx.tcx.sess.span_bug(eq_pred.span,
"Equality constraints are not yet \
implemented (#20041)")
let ty_left = ast_ty_to_ty(ccx, &ExplicitRscope, &*eq_pred.ty_left);
let ty_right = ast_ty_to_ty(ccx, &ExplicitRscope, &*eq_pred.ty_right);
result.predicates.push(space, ty::Predicate::Equate(
ty::Binder(ty::EquatePredicate(ty_left, ty_right))
));
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,8 @@ pub struct WhereRegionPredicate {
pub struct WhereEqPredicate {
pub id: NodeId,
pub span: Span,
pub path: Path,
pub ty: P<Ty>,
pub ty_left: P<Ty>,
pub ty_right: P<Ty>,
}

/// The set of MetaItems that define the compilation environment of the crate,
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/ext/deriving/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,8 @@ impl<'a> TraitDef<'a> {
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
id: ast::DUMMY_NODE_ID,
span: self.span,
path: we.path.clone(),
ty: we.ty.clone()
ty_right: we.ty_right.clone(),
ty_left: we.ty_left.clone()
})
}
}
Expand Down
19 changes: 18 additions & 1 deletion src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@ static KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
("staged_api", "1.0.0", Active),

// Allows using items which are missing stability attributes
("unmarked_api", "1.0.0", Active)
("unmarked_api", "1.0.0", Active),

// Enables equality constraints in where clauses.
("equality_constraints", "1.0.0", Active)
];

enum Status {
Expand Down Expand Up @@ -503,6 +506,20 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
}
visit::walk_fn(self, fn_kind, fn_decl, block, span);
}

fn visit_generics(&mut self, generics: &'v ast::Generics) {
for pred in generics.where_clause.predicates.iter() {
match pred {
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{span, ..}) => {
self.gate_feature("equality_constraints",
span, "equality constraints are experimental")
},
_ => {}
}
}

visit::walk_generics(self, generics);
}
}

fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate,
Expand Down
8 changes: 4 additions & 4 deletions src/libsyntax/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,13 +825,13 @@ pub fn noop_fold_where_predicate<T: Folder>(
})
}
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
path,
ty,
ty_left,
ty_right,
span}) => {
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{
id: fld.new_id(id),
path: fld.fold_path(path),
ty:fld.fold_ty(ty),
ty_left: fld.fold_ty(ty_left),
ty_right: fld.fold_ty(ty_right),
span: fld.new_span(span)
})
}
Expand Down
25 changes: 12 additions & 13 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4245,21 +4245,20 @@ impl<'a> Parser<'a> {

parsed_something = true;
} else if self.eat(&token::Eq) {
// let ty = self.parse_ty();
let ty = self.parse_ty();
let hi = self.span.hi;
let span = mk_sp(lo, hi);
// generics.where_clause.predicates.push(
// ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
// id: ast::DUMMY_NODE_ID,
// span: span,
// path: panic!("NYI"), //bounded_ty,
// ty: ty,
// }));
// parsed_something = true;
// // FIXME(#18433)
self.span_err(span,
"equality constraints are not yet supported \
in where clauses (#20041)");
generics.where_clause.predicates.push(
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
id: ast::DUMMY_NODE_ID,
span: span,
ty_left: bounded_ty,
ty_right: ty,
}));
parsed_something = true;
// self.span_err(span,
// "equality constraints are not yet supported \
// in where clauses (#20041)");
} else {
let last_span = self.last_span;
self.span_err(last_span,
Expand Down
8 changes: 5 additions & 3 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2516,11 +2516,13 @@ impl<'a> State<'a> {
}
}
}
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
try!(self.print_path(path, false));
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref ty_left,
ref ty_right,
..}) => {
try!(self.print_type(&**ty_left));
try!(space(&mut self.s));
try!(self.word_space("="));
try!(self.print_type(&**ty));
try!(self.print_type(&**ty_right));
}
}
}
Expand Down
9 changes: 4 additions & 5 deletions src/libsyntax/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -597,12 +597,11 @@ pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics
visitor.visit_lifetime_ref(bound);
}
}
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
ref path,
ref ty,
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref ty_left,
ref ty_right,
..}) => {
visitor.visit_path(path, id);
visitor.visit_ty(&**ty);
visitor.visit_ty(&**ty_left);
visitor.visit_ty(&**ty_right);
}
}
}
Expand Down
30 changes: 30 additions & 0 deletions src/test/compile-fail/where-clause-equality-constraint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(equality_constraints)]

trait Foo<A> where A = isize {
type Inner;

fn foo_bar(&self) where Self::Inner = String {}
}

// Failure to meet equality constraint on a trait definiton.
impl Foo<String> for () {
//~^ the requirement `collections::string::String == isize` is not satisfied
type Inner = bool;

fn foo_bar(&self) {}
}

fn main() {
// Failure to meet associated type constraint on a method
().foo_bar()
}
27 changes: 27 additions & 0 deletions src/test/run-pass/where-clause-equality-constraint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(equality_constraints)]

trait Foo<A> where A = isize {
type Inner;

fn foo_bar(&self) where Self::Inner = String {}
}

impl Foo<isize> for () {
type Inner = String;

fn foo_bar(&self) {}
}

fn main() {
().foo_bar()
}