From 8fe63e23421f66b730afdbd14c3ec90e39950288 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Fri, 18 Dec 2015 14:38:28 -0800 Subject: Add `default` as contextual keyword, and parse it for impl items. --- src/libsyntax/parse/parser.rs | 33 ++++++++++++++- src/libsyntax/parse/token.rs | 97 ++++++++++++++++++++++--------------------- 2 files changed, 80 insertions(+), 50 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5884be40150..969d39056aa 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -18,7 +18,7 @@ use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind}; use ast::Block; use ast::{BlockCheckMode, CaptureBy}; use ast::{Constness, Crate, CrateConfig}; -use ast::{Decl, DeclKind}; +use ast::{Decl, DeclKind, Defaultness}; use ast::{EMPTY_CTXT, EnumDef, ExplicitSelf}; use ast::{Expr, ExprKind, RangeLimits}; use ast::{Field, FnDecl}; @@ -644,6 +644,25 @@ impl<'a> Parser<'a> { } } + pub fn check_contextual_keyword(&mut self, ident: Ident) -> bool { + let tok = token::Ident(ident, token::Plain); + self.expected_tokens.push(TokenType::Token(tok)); + if let token::Ident(ref cur_ident, _) = self.token { + cur_ident.name == ident.name + } else { + false + } + } + + pub fn eat_contextual_keyword(&mut self, ident: Ident) -> PResult { + if self.check_contextual_keyword(ident) { + try!(self.bump()); + Ok(true) + } else { + Ok(false) + } + } + /// If the given word is not a keyword, signal an error. /// If the next token is not the given word, signal an error. /// Otherwise, eat it. @@ -705,7 +724,6 @@ impl<'a> Parser<'a> { } } - /// Attempt to consume a `<`. If `<<` is seen, replace it with a single /// `<` and continue. If a `<` is not seen, return false. /// @@ -4846,6 +4864,7 @@ impl<'a> Parser<'a> { let mut attrs = try!(self.parse_outer_attributes()); let lo = self.span.lo; let vis = try!(self.parse_visibility()); + let defaultness = try!(self.parse_defaultness()); let (name, node) = if self.eat_keyword(keywords::Type) { let name = try!(self.parse_ident()); try!(self.expect(&token::Eq)); @@ -4872,6 +4891,7 @@ impl<'a> Parser<'a> { span: mk_sp(lo, self.last_span.hi), ident: name, vis: vis, + defaultness: defaultness, attrs: attrs, node: node }) @@ -5208,6 +5228,15 @@ impl<'a> Parser<'a> { else { Ok(Visibility::Inherited) } } + /// Parse defaultness: DEFAULT or nothing + fn parse_defaultness(&mut self) -> PResult { + if try!(self.eat_contextual_keyword(special_idents::DEFAULT)) { + Ok(Defaultness::Default) + } else { + Ok(Defaultness::Final) + } + } + /// Given a termination token, parse all of the items in a module fn parse_mod_items(&mut self, term: &token::Token, inner_lo: BytePos) -> PResult<'a, Mod> { let mut items = vec![]; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 294cbf35895..033ac9440bc 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -545,66 +545,67 @@ declare_special_idents_and_keywords! { (9, __unused1, "<__unused1>"); (super::SELF_TYPE_KEYWORD_NAME_NUM, type_self, "Self"); (11, prelude_import, "prelude_import"); + (12, DEFAULT, "default"); } pub mod keywords { // These ones are variants of the Keyword enum 'strict: - (12, As, "as"); - (13, Break, "break"); - (14, Crate, "crate"); - (15, Else, "else"); - (16, Enum, "enum"); - (17, Extern, "extern"); - (18, False, "false"); - (19, Fn, "fn"); - (20, For, "for"); - (21, If, "if"); - (22, Impl, "impl"); - (23, In, "in"); - (24, Let, "let"); - (25, Loop, "loop"); - (26, Match, "match"); - (27, Mod, "mod"); - (28, Move, "move"); - (29, Mut, "mut"); - (30, Pub, "pub"); - (31, Ref, "ref"); - (32, Return, "return"); + (13, As, "as"); + (14, Break, "break"); + (15, Crate, "crate"); + (16, Else, "else"); + (17, Enum, "enum"); + (18, Extern, "extern"); + (19, False, "false"); + (20, Fn, "fn"); + (21, For, "for"); + (22, If, "if"); + (23, Impl, "impl"); + (24, In, "in"); + (25, Let, "let"); + (26, Loop, "loop"); + (27, Match, "match"); + (28, Mod, "mod"); + (29, Move, "move"); + (30, Mut, "mut"); + (31, Pub, "pub"); + (32, Ref, "ref"); + (33, Return, "return"); // Static and Self are also special idents (prefill de-dupes) (super::STATIC_KEYWORD_NAME_NUM, Static, "static"); (super::SELF_KEYWORD_NAME_NUM, SelfValue, "self"); (super::SELF_TYPE_KEYWORD_NAME_NUM, SelfType, "Self"); - (33, Struct, "struct"); + (34, Struct, "struct"); (super::SUPER_KEYWORD_NAME_NUM, Super, "super"); - (34, True, "true"); - (35, Trait, "trait"); - (36, Type, "type"); - (37, Unsafe, "unsafe"); - (38, Use, "use"); - (39, While, "while"); - (40, Continue, "continue"); - (41, Box, "box"); - (42, Const, "const"); - (43, Where, "where"); + (35, True, "true"); + (36, Trait, "trait"); + (37, Type, "type"); + (38, Unsafe, "unsafe"); + (39, Use, "use"); + (40, While, "while"); + (41, Continue, "continue"); + (42, Box, "box"); + (43, Const, "const"); + (44, Where, "where"); 'reserved: - (44, Virtual, "virtual"); - (45, Proc, "proc"); - (46, Alignof, "alignof"); - (47, Become, "become"); - (48, Offsetof, "offsetof"); - (49, Priv, "priv"); - (50, Pure, "pure"); - (51, Sizeof, "sizeof"); - (52, Typeof, "typeof"); - (53, Unsized, "unsized"); - (54, Yield, "yield"); - (55, Do, "do"); - (56, Abstract, "abstract"); - (57, Final, "final"); - (58, Override, "override"); - (59, Macro, "macro"); + (45, Virtual, "virtual"); + (46, Proc, "proc"); + (47, Alignof, "alignof"); + (48, Become, "become"); + (49, Offsetof, "offsetof"); + (50, Priv, "priv"); + (51, Pure, "pure"); + (52, Sizeof, "sizeof"); + (53, Typeof, "typeof"); + (54, Unsized, "unsized"); + (55, Yield, "yield"); + (56, Do, "do"); + (57, Abstract, "abstract"); + (58, Final, "final"); + (59, Override, "override"); + (60, Macro, "macro"); } } -- cgit 1.4.1-3-g733a5 From 9734406a5f95393e8e888cf67b48861ea8a39de7 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Fri, 29 Jan 2016 16:25:18 -0800 Subject: Assorted fixed after rebasing --- src/librustc/middle/subst.rs | 4 +- src/librustc/middle/traits/select.rs | 1 - src/librustc/middle/traits/specialize.rs | 2 +- src/librustc/middle/ty/trait_def.rs | 9 ++++- src/librustc_trans/trans/meth.rs | 3 +- src/librustc_typeck/check/mod.rs | 20 +++++----- src/librustc_typeck/coherence/overlap.rs | 46 +++++++++------------- src/librustc_typeck/collect.rs | 3 +- src/libsyntax/parse/parser.rs | 12 +++--- .../coherence-projection-conflict-orphan.rs | 4 +- .../coherence-projection-conflict-ty-param.rs | 4 +- .../compile-fail/coherence-projection-conflict.rs | 4 +- 12 files changed, 56 insertions(+), 56 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 9f8e2a22133..510a3dd454b 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -162,9 +162,9 @@ impl<'tcx> Substs<'tcx> { pub fn with_method_from_subst(self, other: &Substs<'tcx>) -> Substs<'tcx> { let Substs { types, regions } = self; - let types = types.with_vec(FnSpace, other.types.get_slice(FnSpace).to_vec()); + let types = types.with_slice(FnSpace, other.types.get_slice(FnSpace)); let regions = regions.map(|r| { - r.with_vec(FnSpace, other.regions().get_slice(FnSpace).to_vec()) + r.with_slice(FnSpace, other.regions().get_slice(FnSpace)) }); Substs { types: types, regions: regions } } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index d319ac0219c..fd41007d0e2 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1621,7 +1621,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { true }, ParamCandidate(..) => false, - ErrorCandidate => false // propagate errors }, ImplCandidate(other_def) => { // See if we can toss out `victim` based on specialization. diff --git a/src/librustc/middle/traits/specialize.rs b/src/librustc/middle/traits/specialize.rs index 30897e9289d..91ddcc3b9e4 100644 --- a/src/librustc/middle/traits/specialize.rs +++ b/src/librustc/middle/traits/specialize.rs @@ -87,7 +87,7 @@ impl SpecializationGraph { for slot in possible_siblings.iter_mut() { let possible_sibling = *slot; - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false); + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None); let overlap = traits::overlapping_impls(&infcx, possible_sibling, impl_def_id); if let Some(trait_ref) = overlap { diff --git a/src/librustc/middle/ty/trait_def.rs b/src/librustc/middle/ty/trait_def.rs index 582b2894551..737bb873d6d 100644 --- a/src/librustc/middle/ty/trait_def.rs +++ b/src/librustc/middle/ty/trait_def.rs @@ -10,9 +10,10 @@ use dep_graph::DepNode; use middle::def_id::DefId; +use middle::traits; use middle::ty; use middle::ty::fast_reject; -use middle::ty::{Ty, TyCtxt}; +use middle::ty::{Ty, TyCtxt, TraitRef}; use std::borrow::{Borrow}; use std::cell::{Cell, Ref, RefCell}; use syntax::ast::Name; @@ -128,6 +129,12 @@ impl<'tcx> TraitDef<'tcx> { debug!("TraitDef::record_impl for {:?}, from {:?}", self, impl_trait_ref); + // Record the write into the impl set, but only for local + // impls: external impls are handled differently. + if impl_def_id.is_local() { + self.write_trait_impls(tcx); + } + // We don't want to borrow_mut after we already populated all impls, // so check if an impl is present with an immutable borrow first. if let Some(sty) = fast_reject::simplify_type(tcx, diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 073ef9797ed..072c1dfaa1d 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -33,7 +33,8 @@ use trans::glue; use trans::machine; use trans::type_::Type; use trans::type_of::*; -use middle::ty::{self, Ty, TyCtxt}; +use middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use middle::ty::MethodCall; use syntax::ast::{self, Name}; use syntax::attr; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index be2f63d1d1b..51b88612fe4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -872,22 +872,24 @@ fn check_specialization_validity<'tcx, F>(tcx: &ty::ctxt<'tcx>, { let parent_item_opt = traits::get_parent_impl_item(tcx, impl_id, f); if let Some((Defaultness::Final, parent_impl)) = parent_item_opt { - span_err!(tcx.sess, impl_item.span, E0520, - "item `{}` is provided by an implementation that \ - specializes another, but the item in the parent \ - implementations is not marked `default` and so it \ - cannot be specialized.", - impl_item.name); + let mut err = struct_span_err!( + tcx.sess, impl_item.span, E0520, + "item `{}` is provided by an implementation that \ + specializes another, but the item in the parent \ + implementations is not marked `default` and so it \ + cannot be specialized.", + impl_item.name); match tcx.span_of_impl(parent_impl) { Ok(span) => { - span_note!(tcx.sess, span, "parent implementation is here:"); + err.span_note(span, "parent implementation is here:"); } Err(cname) => { - tcx.sess.note(&format!("parent implementation is in crate `{}`", - cname)); + err.note(&format!("parent implementation is in crate `{}`", cname)); } } + + err.emit(); } } diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 97cdcd4ba34..8f125abaec0 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -20,11 +20,10 @@ use syntax::ast; use rustc::dep_graph::DepNode; use rustc_front::hir; use rustc_front::intravisit; -use util::nodemap::{DefIdMap, DefIdSet}; +use util::nodemap::DefIdMap; pub fn check(tcx: &TyCtxt) { let mut overlap = OverlapChecker { tcx: tcx, - traits_checked: DefIdSet(), default_impls: DefIdMap() }; // this secondary walk specifically checks for some other cases, @@ -35,14 +34,6 @@ pub fn check(tcx: &TyCtxt) { struct OverlapChecker<'cx, 'tcx:'cx> { tcx: &'cx TyCtxt<'tcx>, - // The set of traits where we have checked for overlap. This is - // used to avoid checking the same trait twice. - // - // NB. It's ok to skip tracking this set because we fully - // encapsulate it, and we always create a task - // (`CoherenceOverlapCheck`) corresponding to each entry. - traits_checked: DefIdSet, - // maps from a trait def-id to an impl id default_impls: DefIdMap, } @@ -120,20 +111,19 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { let impl_def_id = self.tcx.map.local_def_id(item.id); let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap(); - self.check_for_overlapping_impls_of_trait(trait_ref.def_id); - let prev_default_impl = self.default_impls.insert(trait_ref.def_id, item.id); if let Some(prev_id) = prev_default_impl { - span_err!(self.tcx.sess, - self.span_of_def_id(impl_def_id), E0519, - "redundant default implementations of trait `{}`:", - trait_ref); - span_note!(self.tcx.sess, - self.span_of_def_id(self.tcx.map.local_def_id(prev_id)), - "redundant implementation is here:"); + let mut err = struct_span_err!( + self.tcx.sess, + self.tcx.span_of_impl(impl_def_id).unwrap(), E0519, + "redundant default implementations of trait `{}`:", + trait_ref); + err.span_note(self.tcx.span_of_impl(self.tcx.map.local_def_id(prev_id)).unwrap(), + "redundant implementation is here:"); + err.emit(); } } - hir::ItemImpl(_, _, _, Some(_), ref self_ty, _) => { + hir::ItemImpl(_, _, _, Some(_), _, _) => { let impl_def_id = self.tcx.map.local_def_id(item.id); let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap(); let trait_def_id = trait_ref.def_id; @@ -162,20 +152,22 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { }).unwrap_or(String::new()) }; - span_err!(self.tcx.sess, self.span_of_def_id(impl_def_id), E0119, - "conflicting implementations of trait `{}`{}:", - overlap.on_trait_ref, - self_type); + let mut err = struct_span_err!( + self.tcx.sess, self.tcx.span_of_impl(impl_def_id).unwrap(), E0119, + "conflicting implementations of trait `{}`{}:", + overlap.on_trait_ref, + self_type); match self.tcx.span_of_impl(overlap.with_impl) { Ok(span) => { - span_note!(self.tcx.sess, span, "conflicting implementation is here:"); + err.span_note(span, "conflicting implementation is here:"); } Err(cname) => { - self.tcx.sess.note(&format!("conflicting implementation in crate `{}`", - cname)); + err.note(&format!("conflicting implementation in crate `{}`", cname)); } } + + err.emit(); } // check for overlap with the automatic `impl Trait for Trait` diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4a8ce70ccb9..831c9804d1b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -69,7 +69,6 @@ use middle::resolve_lifetime; use middle::const_eval::{self, ConstVal}; use middle::const_eval::EvalHint::UncheckedExprHint; use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace}; -use middle::traits; use middle::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; use middle::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme}; use middle::ty::{VariantKind}; @@ -871,7 +870,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { trait_item.id, hir::Inherited, sig, - hir::Defaultness::Default + hir::Defaultness::Default, tcx.mk_self_type(), &trait_def.generics, &trait_predicates); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 969d39056aa..6839f11cd70 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -654,12 +654,12 @@ impl<'a> Parser<'a> { } } - pub fn eat_contextual_keyword(&mut self, ident: Ident) -> PResult { + pub fn eat_contextual_keyword(&mut self, ident: Ident) -> bool { if self.check_contextual_keyword(ident) { - try!(self.bump()); - Ok(true) + self.bump(); + true } else { - Ok(false) + false } } @@ -5229,8 +5229,8 @@ impl<'a> Parser<'a> { } /// Parse defaultness: DEFAULT or nothing - fn parse_defaultness(&mut self) -> PResult { - if try!(self.eat_contextual_keyword(special_idents::DEFAULT)) { + fn parse_defaultness(&mut self) -> PResult<'a, Defaultness> { + if self.eat_contextual_keyword(special_idents::DEFAULT) { Ok(Defaultness::Default) } else { Ok(Defaultness::Final) diff --git a/src/test/compile-fail/coherence-projection-conflict-orphan.rs b/src/test/compile-fail/coherence-projection-conflict-orphan.rs index 3de79454398..3ed3549de89 100644 --- a/src/test/compile-fail/coherence-projection-conflict-orphan.rs +++ b/src/test/compile-fail/coherence-projection-conflict-orphan.rs @@ -21,8 +21,8 @@ pub trait Bar { type Output: 'static; } -impl Foo for i32 { } //~ ERROR E0119 +impl Foo for i32 { } -impl Foo for A { } +impl Foo for A { } //~ ERROR E0119 fn main() {} diff --git a/src/test/compile-fail/coherence-projection-conflict-ty-param.rs b/src/test/compile-fail/coherence-projection-conflict-ty-param.rs index 6880f3e9a3c..f04902a70f6 100644 --- a/src/test/compile-fail/coherence-projection-conflict-ty-param.rs +++ b/src/test/compile-fail/coherence-projection-conflict-ty-param.rs @@ -15,8 +15,8 @@ use std::marker::PhantomData; pub trait Foo

{} -impl > Foo

for Option {} //~ ERROR E0119 +impl > Foo

for Option {} -impl Foo for Option { } +impl Foo for Option { } //~ ERROR E0119 fn main() {} diff --git a/src/test/compile-fail/coherence-projection-conflict.rs b/src/test/compile-fail/coherence-projection-conflict.rs index 2236e71b53f..6d3ab32f06f 100644 --- a/src/test/compile-fail/coherence-projection-conflict.rs +++ b/src/test/compile-fail/coherence-projection-conflict.rs @@ -16,9 +16,9 @@ pub trait Bar { type Output: 'static; } -impl Foo for i32 { } //~ ERROR E0119 +impl Foo for i32 { } -impl Foo for A { } +impl Foo for A { } //~ ERROR E0119 impl Bar for i32 { type Output = i32; -- cgit 1.4.1-3-g733a5