From 61aaf73ffb57643a654a4f51f38b665d8cce6121 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Sat, 7 Feb 2015 02:42:41 -0800 Subject: [PATCH 1/5] Refactor parser to accept equality constraints --- src/librustc/middle/resolve_lifetime.rs | 9 ++++---- src/librustc_privacy/lib.rs | 3 ++- src/librustc_resolve/lib.rs | 13 ++---------- src/libsyntax/ast.rs | 4 ++-- src/libsyntax/ext/deriving/generic/mod.rs | 4 ++-- src/libsyntax/fold.rs | 8 ++++---- src/libsyntax/parse/parser.rs | 25 +++++++++++------------ src/libsyntax/print/pprust.rs | 6 +++--- src/libsyntax/visit.rs | 9 ++++---- 9 files changed, 35 insertions(+), 46 deletions(-) diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 5e27023e026fb..80e398e3811f4 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -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); } } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index aa9b6c479bb78..dd96957f5aeca 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -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); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a261599a70656..54c7fdcb2ae09 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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); } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 7e1bf7a2230b8..36f407014f9fa 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -458,8 +458,8 @@ pub struct WhereRegionPredicate { pub struct WhereEqPredicate { pub id: NodeId, pub span: Span, - pub path: Path, - pub ty: P, + pub ty_left: P, + pub ty_right: P, } /// The set of MetaItems that define the compilation environment of the crate, diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 28573ef757b12..1c3cc22a69d24 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -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() }) } } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index b0ddb655882a8..fb660f7ed4b70 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -825,13 +825,13 @@ pub fn noop_fold_where_predicate( }) } 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) }) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3107f47de7859..ee5043b7d598b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index c177cd1fafa55..75bee0d5e4204 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2516,11 +2516,11 @@ 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)); } } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 21cb62b0a0c11..1c7ce992120ca 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -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); } } } From a2b9dc8085e27d94fbe9b342830d9a20f829df2b Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Sat, 7 Feb 2015 17:23:02 -0800 Subject: [PATCH 2/5] Translate equality predicates in collect --- src/librustc/middle/resolve_lifetime.rs | 7 ++++++- src/librustc_typeck/collect.rs | 7 +++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 80e398e3811f4..1ffacb4e9d477 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -554,7 +554,12 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec { 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); + } } } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index ce26658cf4b93..7049d3a4e8865 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1293,10 +1293,9 @@ 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)))); } } } From 82ba7d65b5d53be8e62200a23987e97b6395da38 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Sat, 7 Feb 2015 18:32:47 -0800 Subject: [PATCH 3/5] Fixed pretty failures --- src/librustc_typeck/collect.rs | 4 +++- src/libsyntax/print/pprust.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 7049d3a4e8865..f582664a6cbf0 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1295,7 +1295,9 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, &ast::WherePredicate::EqPredicate(ref eq_pred) => { 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)))); + result.predicates.push(space, ty::Predicate::Equate( + ty::Binder(ty::EquatePredicate(ty_left, ty_right)) + )); } } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 75bee0d5e4204..8105d9876090e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2516,7 +2516,9 @@ impl<'a> State<'a> { } } } - &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref ty_left, ref ty_right, ..}) => { + &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("=")); From f88201f39b4c226d7f26821dd132cb72aba6a37c Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Sat, 7 Feb 2015 18:37:51 -0800 Subject: [PATCH 4/5] Add tests --- .../where-clause-equality-constraint.rs | 29 +++++++++++++++++++ .../where-clause-equality-constraint.rs | 26 +++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/test/compile-fail/where-clause-equality-constraint.rs create mode 100644 src/test/run-pass/where-clause-equality-constraint.rs diff --git a/src/test/compile-fail/where-clause-equality-constraint.rs b/src/test/compile-fail/where-clause-equality-constraint.rs new file mode 100644 index 0000000000000..18e6ffa2c65cc --- /dev/null +++ b/src/test/compile-fail/where-clause-equality-constraint.rs @@ -0,0 +1,29 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +trait Foo where A = isize { + type Inner; + + fn foo_bar(&self) where Self::Inner = String {} +} + +// Failure to meet equality constraint on a trait definiton. +impl Foo 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() +} diff --git a/src/test/run-pass/where-clause-equality-constraint.rs b/src/test/run-pass/where-clause-equality-constraint.rs new file mode 100644 index 0000000000000..f962ebfbd31d6 --- /dev/null +++ b/src/test/run-pass/where-clause-equality-constraint.rs @@ -0,0 +1,26 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +trait Foo where A = isize { + type Inner; + + fn foo_bar(&self) where Self::Inner = String {} +} + +impl Foo for () { + type Inner = String; + + fn foo_bar(&self) {} +} + +fn main() { + ().foo_bar() +} From 83cd3b68707867559ca5c09d9d35664a74652073 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Fri, 13 Feb 2015 21:40:09 -0800 Subject: [PATCH 5/5] Add feature gate for equality constraints --- src/doc/reference.md | 7 +++++-- src/libsyntax/feature_gate.rs | 19 ++++++++++++++++++- .../where-clause-equality-constraint.rs | 1 + .../where-clause-equality-constraint.rs | 1 + 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 9851e1c28fbf0..d6a4375536b34 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2382,6 +2382,8 @@ 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. @@ -2389,6 +2391,9 @@ The currently implemented features of the reference compiler are: * `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. @@ -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 diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 12efd959918e1..6948813800507 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -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 { @@ -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(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate, diff --git a/src/test/compile-fail/where-clause-equality-constraint.rs b/src/test/compile-fail/where-clause-equality-constraint.rs index 18e6ffa2c65cc..58b76f71e910c 100644 --- a/src/test/compile-fail/where-clause-equality-constraint.rs +++ b/src/test/compile-fail/where-clause-equality-constraint.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(equality_constraints)] trait Foo where A = isize { type Inner; diff --git a/src/test/run-pass/where-clause-equality-constraint.rs b/src/test/run-pass/where-clause-equality-constraint.rs index f962ebfbd31d6..b802d2ab8c0d2 100644 --- a/src/test/run-pass/where-clause-equality-constraint.rs +++ b/src/test/run-pass/where-clause-equality-constraint.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(equality_constraints)] trait Foo where A = isize { type Inner;