support default impl
for specialization
`[default] [unsafe] impl` and typecheck
This commit is contained in:
parent
715811d0be
commit
b48eb5e0be
7 changed files with 44 additions and 46 deletions
|
@ -535,10 +535,11 @@ maybe_unsafe
|
||||||
| %empty { $$ = mk_none(); }
|
| %empty { $$ = mk_none(); }
|
||||||
;
|
;
|
||||||
|
|
||||||
maybe_default_impl
|
maybe_default_maybe_unsafe
|
||||||
: IMPL { $$ = mk_none(); }
|
: DEFAULT UNSAFE { $$ = mk_atom("DefaultUnsafe"); }
|
||||||
| DEFAULT IMPL { $$ = $1 }
|
| DEFAULT { $$ = mk_atom("Default"); }
|
||||||
;
|
| UNSAFE { $$ = mk_atom("Unsafe"); }
|
||||||
|
| %empty { $$ = mk_none(); }
|
||||||
|
|
||||||
trait_method
|
trait_method
|
||||||
: type_method { $$ = mk_node("Required", 1, $1); }
|
: type_method { $$ = mk_node("Required", 1, $1); }
|
||||||
|
@ -594,27 +595,27 @@ impl_method
|
||||||
// they are ambiguous with traits. We do the same here, regrettably,
|
// they are ambiguous with traits. We do the same here, regrettably,
|
||||||
// by splitting ty into ty and ty_prim.
|
// by splitting ty into ty and ty_prim.
|
||||||
item_impl
|
item_impl
|
||||||
: maybe_unsafe maybe_default_impl generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
|
: maybe_default_maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
|
||||||
{
|
{
|
||||||
$$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8, $2);
|
$$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8);
|
||||||
}
|
}
|
||||||
| maybe_unsafe maybe_default_impl generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
|
| maybe_default_maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
|
||||||
{
|
{
|
||||||
$$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10, $2);
|
$$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10);
|
||||||
}
|
}
|
||||||
| maybe_unsafe maybe_default_impl generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
|
| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
|
||||||
{
|
{
|
||||||
$$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10, $2);
|
$$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10);
|
||||||
}
|
}
|
||||||
| maybe_unsafe maybe_default_impl generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
|
| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
|
||||||
{
|
{
|
||||||
$$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11, $2);
|
$$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11);
|
||||||
}
|
}
|
||||||
| maybe_unsafe maybe_default_impl generic_params trait_ref FOR DOTDOT '{' '}'
|
| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}'
|
||||||
{
|
{
|
||||||
$$ = mk_node("ItemImplDefault", 3, $1, $3, $4);
|
$$ = mk_node("ItemImplDefault", 3, $1, $3, $4);
|
||||||
}
|
}
|
||||||
| maybe_unsafe maybe_default_impl generic_params '!' trait_ref FOR DOTDOT '{' '}'
|
| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}'
|
||||||
{
|
{
|
||||||
$$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4);
|
$$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1363,7 +1363,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
|
ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// [1] `defaultness.has_value()` is necer called for an `impl`, always `true` in order to
|
// [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to
|
||||||
// not cause an assertion failure inside the `lower_defaultness` function
|
// not cause an assertion failure inside the `lower_defaultness` function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
|
||||||
use ty::outlives::Component;
|
use ty::outlives::Component;
|
||||||
use util::nodemap::FxHashSet;
|
use util::nodemap::FxHashSet;
|
||||||
use hir::{self};
|
use hir::{self};
|
||||||
|
use traits::specialize::specialization_graph::NodeItem;
|
||||||
|
|
||||||
use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};
|
use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};
|
||||||
|
|
||||||
|
@ -525,6 +526,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn impl_item_is_final(self, node_item: &NodeItem<hir::Defaultness>) -> bool {
|
||||||
|
node_item.item.is_final() && !self.impl_is_default(node_item.node.def_id())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum TupleArgumentsFlag { Yes, No }
|
pub enum TupleArgumentsFlag { Yes, No }
|
||||||
|
|
|
@ -1141,12 +1141,10 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
.map(|node_item| node_item.map(|parent| parent.defaultness));
|
.map(|node_item| node_item.map(|parent| parent.defaultness));
|
||||||
|
|
||||||
if let Some(parent) = parent {
|
if let Some(parent) = parent {
|
||||||
if parent.item.is_final() {
|
if tcx.impl_item_is_final(&parent) {
|
||||||
if !tcx.impl_is_default(parent.node.def_id()) {
|
|
||||||
report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
|
report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1226,14 +1226,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match defaultness {
|
if let ast::Defaultness::Default = defaultness {
|
||||||
ast::Defaultness::Default => {
|
|
||||||
gate_feature_post!(&self, specialization,
|
gate_feature_post!(&self, specialization,
|
||||||
i.span,
|
i.span,
|
||||||
"specialization is unstable");
|
"specialization is unstable");
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -4918,13 +4918,10 @@ impl<'a> Parser<'a> {
|
||||||
allowed to have generics");
|
allowed to have generics");
|
||||||
}
|
}
|
||||||
|
|
||||||
match defaultness {
|
if let ast::Defaultness::Default = defaultness {
|
||||||
ast::Defaultness::Default => {
|
|
||||||
self.span_err(impl_span, "`default impl` is not allowed for \
|
self.span_err(impl_span, "`default impl` is not allowed for \
|
||||||
default trait implementations");
|
default trait implementations");
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.expect(&token::OpenDelim(token::Brace))?;
|
self.expect(&token::OpenDelim(token::Brace))?;
|
||||||
self.expect(&token::CloseDelim(token::Brace))?;
|
self.expect(&token::CloseDelim(token::Brace))?;
|
||||||
|
@ -5768,13 +5765,13 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
if (self.check_keyword(keywords::Unsafe) &&
|
if (self.check_keyword(keywords::Unsafe) &&
|
||||||
self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
|
self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
|
||||||
(self.check_keyword(keywords::Unsafe) &&
|
(self.check_keyword(keywords::Default) &&
|
||||||
self.look_ahead(1, |t| t.is_keyword(keywords::Default)) &&
|
self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
|
||||||
self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
|
self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
|
||||||
{
|
{
|
||||||
// IMPL ITEM
|
// IMPL ITEM
|
||||||
self.expect_keyword(keywords::Unsafe)?;
|
|
||||||
let defaultness = self.parse_defaultness()?;
|
let defaultness = self.parse_defaultness()?;
|
||||||
|
self.expect_keyword(keywords::Unsafe)?;
|
||||||
self.expect_keyword(keywords::Impl)?;
|
self.expect_keyword(keywords::Impl)?;
|
||||||
let (ident,
|
let (ident,
|
||||||
item_,
|
item_,
|
||||||
|
|
|
@ -17,61 +17,61 @@ unsafe trait Foo {
|
||||||
fn foo(&self) -> &'static str;
|
fn foo(&self) -> &'static str;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe default impl<T> Foo for T {
|
default unsafe impl<T> Foo for T {
|
||||||
fn foo(&self) -> &'static str {
|
fn foo(&self) -> &'static str {
|
||||||
"generic"
|
"generic"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe default impl<T: Clone> Foo for T {
|
default unsafe impl<T: Clone> Foo for T {
|
||||||
fn foo(&self) -> &'static str {
|
fn foo(&self) -> &'static str {
|
||||||
"generic Clone"
|
"generic Clone"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe default impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
|
default unsafe impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
|
||||||
fn foo(&self) -> &'static str {
|
fn foo(&self) -> &'static str {
|
||||||
"generic pair"
|
"generic pair"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe default impl<T: Clone> Foo for (T, T) {
|
default unsafe impl<T: Clone> Foo for (T, T) {
|
||||||
fn foo(&self) -> &'static str {
|
fn foo(&self) -> &'static str {
|
||||||
"generic uniform pair"
|
"generic uniform pair"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe default impl Foo for (u8, u32) {
|
default unsafe impl Foo for (u8, u32) {
|
||||||
fn foo(&self) -> &'static str {
|
fn foo(&self) -> &'static str {
|
||||||
"(u8, u32)"
|
"(u8, u32)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe default impl Foo for (u8, u8) {
|
default unsafe impl Foo for (u8, u8) {
|
||||||
fn foo(&self) -> &'static str {
|
fn foo(&self) -> &'static str {
|
||||||
"(u8, u8)"
|
"(u8, u8)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe default impl<T: Clone> Foo for Vec<T> {
|
default unsafe impl<T: Clone> Foo for Vec<T> {
|
||||||
fn foo(&self) -> &'static str {
|
fn foo(&self) -> &'static str {
|
||||||
"generic Vec"
|
"generic Vec"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Foo for Vec<i32> {
|
default unsafe impl Foo for Vec<i32> {
|
||||||
fn foo(&self) -> &'static str {
|
fn foo(&self) -> &'static str {
|
||||||
"Vec<i32>"
|
"Vec<i32>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Foo for String {
|
default unsafe impl Foo for String {
|
||||||
fn foo(&self) -> &'static str {
|
fn foo(&self) -> &'static str {
|
||||||
"String"
|
"String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Foo for i32 {
|
default unsafe impl Foo for i32 {
|
||||||
fn foo(&self) -> &'static str {
|
fn foo(&self) -> &'static str {
|
||||||
"i32"
|
"i32"
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ unsafe impl Foo for i32 {
|
||||||
struct NotClone;
|
struct NotClone;
|
||||||
|
|
||||||
unsafe trait MyMarker {}
|
unsafe trait MyMarker {}
|
||||||
unsafe default impl<T: Clone + MyMarker> Foo for T {
|
default unsafe impl<T: Clone + MyMarker> Foo for T {
|
||||||
fn foo(&self) -> &'static str {
|
fn foo(&self) -> &'static str {
|
||||||
"generic Clone + MyMarker"
|
"generic Clone + MyMarker"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue