From 6a2f16e1365160d05a3d360f21756039d1bd3254 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Thu, 22 Jan 2015 22:14:52 +0100 Subject: [PATCH 01/32] Add support for default trait impls in libsyntax --- src/libsyntax/ast.rs | 7 +++- src/libsyntax/ast_map/mod.rs | 1 + src/libsyntax/ast_util.rs | 8 +++-- src/libsyntax/ext/deriving/generic/mod.rs | 2 +- src/libsyntax/fold.rs | 5 ++- src/libsyntax/parse/parser.rs | 41 +++++++++++++++-------- src/libsyntax/print/pprust.rs | 12 +++++++ src/libsyntax/visit.rs | 3 ++ 8 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 140e21b5d04..d57b23b8b1b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1641,6 +1641,10 @@ pub enum Item_ { Generics, TyParamBounds, Vec), + + // Default trait implementations + // `impl Trait for ..` + ItemDefTrait(Unsafety, TraitRef), ItemImpl(Unsafety, ImplPolarity, Generics, @@ -1666,7 +1670,8 @@ impl Item_ { ItemStruct(..) => "struct", ItemTrait(..) => "trait", ItemMac(..) | - ItemImpl(..) => "item" + ItemImpl(..) | + ItemDefTrait(..) => "item" } } } diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index ba08f61b557..7903a3a1bfc 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -1044,6 +1044,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { ItemStruct(..) => "struct", ItemTrait(..) => "trait", ItemImpl(..) => "impl", + ItemDefTrait(..) => "default impl", ItemMac(..) => "macro" }; format!("{} {}{}", item_str, path_str, id_str) diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index f660296fcd7..f1228c1d363 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -252,8 +252,12 @@ pub fn name_to_dummy_lifetime(name: Name) -> Lifetime { /// hint of where they came from, (previously they would all just be /// listed as `__extensions__::method_name::hash`, with no indication /// of the type). -pub fn impl_pretty_name(trait_ref: &Option, ty: &Ty) -> Ident { - let mut pretty = pprust::ty_to_string(ty); +pub fn impl_pretty_name(trait_ref: &Option, ty: Option<&Ty>) -> Ident { + let mut pretty = match ty { + Some(t) => pprust::ty_to_string(t), + None => String::from_str("..") + }; + match *trait_ref { Some(ref trait_ref) => { pretty.push('.'); diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index b912ed34ae0..df6b73b4c97 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -498,7 +498,7 @@ impl<'a> TraitDef<'a> { // Just mark it now since we know that it'll end up used downstream attr::mark_used(&attr); let opt_trait_ref = Some(trait_ref); - let ident = ast_util::impl_pretty_name(&opt_trait_ref, &*self_type); + let ident = ast_util::impl_pretty_name(&opt_trait_ref, Some(&*self_type)); let mut a = vec![attr]; a.extend(self.attributes.iter().cloned()); cx.item( diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1fb0642d24f..31e5a876374 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -999,6 +999,9 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ { let struct_def = folder.fold_struct_def(struct_def); ItemStruct(struct_def, folder.fold_generics(generics)) } + ItemDefTrait(unsafety, ref trait_ref) => { + ItemDefTrait(unsafety, folder.fold_trait_ref((*trait_ref).clone())) + } ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => { let new_impl_items = impl_items.into_iter().flat_map(|item| { folder.fold_impl_item(item).into_iter() @@ -1150,7 +1153,7 @@ pub fn noop_fold_item_simple(Item {id, ident, attrs, node, vis, span} let ident = match node { // The node may have changed, recompute the "pretty" impl name. ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => { - ast_util::impl_pretty_name(maybe_trait, &**ty) + ast_util::impl_pretty_name(maybe_trait, Some(&**ty)) } _ => ident }; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 370201e5382..55c4afc36a5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -31,7 +31,7 @@ use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst}; -use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy}; +use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, ItemDefTrait}; use ast::{ItemExternCrate, ItemUse}; use ast::{LifetimeDef, Lit, Lit_}; use ast::{LitBool, LitChar, LitByte, LitBinary}; @@ -4783,10 +4783,13 @@ impl<'a> Parser<'a> { (impl_items, inner_attrs) } - /// Parses two variants (with the region/type params always optional): + /// Parses items implementations variants /// impl Foo { ... } - /// impl ToString for ~[T] { ... } + /// impl ToString for &'static T { ... } + /// impl Send for .. {} fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo { + let impl_span = self.span; + // First, parse type parameters if necessary. let mut generics = self.parse_generics(); @@ -4807,7 +4810,7 @@ impl<'a> Parser<'a> { // Parse traits, if necessary. let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { // New-style trait. Reinterpret the type as a trait. - let opt_trait_ref = match ty.node { + match ty.node { TyPath(ref path, node_id) => { Some(TraitRef { path: (*path).clone(), @@ -4818,10 +4821,7 @@ impl<'a> Parser<'a> { self.span_err(ty.span, "not a trait"); None } - }; - - ty = self.parse_ty_sum(); - opt_trait_ref + } } else { match polarity { ast::ImplPolarity::Negative => { @@ -4834,14 +4834,27 @@ impl<'a> Parser<'a> { None }; - self.parse_where_clause(&mut generics); - let (impl_items, attrs) = self.parse_impl_items(); + if self.eat(&token::DotDot) { + if generics.is_parameterized() { + self.span_err(impl_span, "default trait implementations are not \ + allowed to have genercis"); + } - let ident = ast_util::impl_pretty_name(&opt_trait, &*ty); + self.expect(&token::OpenDelim(token::Brace)); + self.expect(&token::CloseDelim(token::Brace)); + (ast_util::impl_pretty_name(&opt_trait, None), + ItemDefTrait(unsafety, opt_trait.unwrap()), None) + } else { + if opt_trait.is_some() { + ty = self.parse_ty_sum(); + } + self.parse_where_clause(&mut generics); + let (impl_items, attrs) = self.parse_impl_items(); - (ident, - ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items), - Some(attrs)) + (ast_util::impl_pretty_name(&opt_trait, Some(&*ty)), + ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items), + Some(attrs)) + } } /// Parse a::B diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f26578e7401..d5b17b5798b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -926,6 +926,18 @@ impl<'a> State<'a> { try!(self.print_struct(&**struct_def, generics, item.ident, item.span)); } + ast::ItemDefTrait(unsafety, ref trait_ref) => { + try!(self.head("")); + try!(self.print_visibility(item.vis)); + try!(self.print_unsafety(unsafety)); + try!(self.word_nbsp("impl")); + try!(self.print_trait_ref(trait_ref)); + try!(space(&mut self.s)); + try!(self.word_space("for")); + try!(self.word_space("..")); + try!(self.bopen()); + try!(self.bclose(item.span)); + } ast::ItemImpl(unsafety, polarity, ref generics, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 21cb62b0a0c..9654e7a005b 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -282,6 +282,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_generics(type_parameters); walk_enum_def(visitor, enum_definition, type_parameters) } + ItemDefTrait(_, ref trait_ref) => { + visitor.visit_trait_ref(trait_ref) + } ItemImpl(_, _, ref type_parameters, ref trait_reference, From 4148d5361a7d0ace1cf3b64d07c6252bbce087af Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Thu, 22 Jan 2015 22:15:02 +0100 Subject: [PATCH 02/32] Fix fallout from libsyntax implementation --- src/librustc/metadata/decoder.rs | 8 +++++--- src/librustc/metadata/encoder.rs | 12 ++++++++++++ src/librustc/middle/reachable.rs | 3 ++- src/librustc/middle/resolve_lifetime.rs | 1 + src/librustc_privacy/lib.rs | 5 +++-- src/librustc_resolve/build_reduced_graph.rs | 3 ++- src/librustc_resolve/lib.rs | 5 ++++- src/librustc_typeck/collect.rs | 4 ++++ src/librustc_typeck/variance.rs | 2 ++ 9 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index e5576de6e84..d4512f51980 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -126,6 +126,7 @@ enum Family { TupleVariant, // v StructVariant, // V Impl, // i + DefTrait, // d Trait, // I Struct, // S PublicField, // g @@ -151,6 +152,7 @@ fn item_family(item: rbml::Doc) -> Family { 'v' => TupleVariant, 'V' => StructVariant, 'i' => Impl, + 'd' => DefTrait, 'I' => Trait, 'S' => Struct, 'g' => PublicField, @@ -357,7 +359,7 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) } Trait => DlDef(def::DefTrait(did)), Enum => DlDef(def::DefTy(did, true)), - Impl => DlImpl(did), + Impl | DefTrait => DlImpl(did), PublicField | InheritedField => DlField, } } @@ -480,7 +482,7 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd, let item_doc = lookup_item(id, cdata.data()); let fam = item_family(item_doc); match fam { - Family::Impl => { + Family::Impl | Family::DefTrait => { reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| { doc_trait_ref(tp, tcx, cdata) }) @@ -1356,7 +1358,7 @@ pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) let parent_item_doc = lookup_item(parent_item_id.node, cdata.data()); match item_family(parent_item_doc) { Trait => Some(item_def_id(parent_item_doc, cdata)), - Impl => { + Impl | DefTrait => { reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref) .map(|_| item_trait_ref(parent_item_doc, tcx, cdata).def_id) } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 42a70cec5df..fc9d2a13834 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1201,6 +1201,18 @@ fn encode_info_for_item(ecx: &EncodeContext, None => {} } } + ast::ItemDefTrait(unsafety, ref ast_trait_ref) => { + add_to_index(item, rbml_w, index); + rbml_w.start_tag(tag_items_data_item); + encode_def_id(rbml_w, def_id); + encode_family(rbml_w, 'd'); + encode_name(rbml_w, item.ident.name); + encode_unsafety(rbml_w, unsafety); + + let trait_ref = ty::node_id_to_trait_ref(tcx, ast_trait_ref.ref_id); + encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref); + rbml_w.end_tag(); + } ast::ItemImpl(unsafety, polarity, _, ref opt_trait, ref ty, ref ast_items) => { // We need to encode information about the default methods we // have inherited, so we drive this based on the impl structure. diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 0af226de251..73a9f179fa0 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -301,7 +301,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { ast::ItemTy(..) | ast::ItemStatic(_, _, _) | ast::ItemMod(..) | ast::ItemForeignMod(..) | ast::ItemImpl(..) | ast::ItemTrait(..) | - ast::ItemStruct(..) | ast::ItemEnum(..) => {} + ast::ItemStruct(..) | ast::ItemEnum(..) | + ast::ItemDefTrait(..) => {} _ => { self.tcx.sess.span_bug(item.span, diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 3ba08c10320..ac3c85acd61 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -115,6 +115,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { ast::ItemUse(_) | ast::ItemMod(..) | ast::ItemMac(..) | + ast::ItemDefTrait(..) | ast::ItemForeignMod(..) | ast::ItemStatic(..) | ast::ItemConst(..) => { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 5662a74a53d..0f13bd30d53 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -209,7 +209,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { match item.node { // impls/extern blocks do not break the "public chain" because they // cannot have visibility qualifiers on them anyway - ast::ItemImpl(..) | ast::ItemForeignMod(..) => {} + ast::ItemImpl(..) | ast::ItemDefTrait(..) | ast::ItemForeignMod(..) => {} // Traits are a little special in that even if they themselves are // not public they may still be exported. @@ -1145,6 +1145,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { } } + ast::ItemDefTrait(..) | ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemStruct(..) | ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) | ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemMac(..) => {} @@ -1204,7 +1205,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { } } - ast::ItemExternCrate(_) | ast::ItemUse(_) | + ast::ItemDefTrait(..) | ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemStatic(..) | ast::ItemConst(..) | ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) | ast::ItemMac(..) => {} diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 2f25f34a92a..acea3f5851e 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -40,7 +40,7 @@ use syntax::ast::{Block, Crate}; use syntax::ast::{DeclItem, DefId}; use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic}; use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn}; -use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; +use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefTrait}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse}; use syntax::ast::{MethodImplItem, Name, NamedField, NodeId}; use syntax::ast::{PathListIdent, PathListMod}; @@ -656,6 +656,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { parent.clone() } + ItemDefTrait(_, _) | ItemImpl(_, _, _, Some(_), _, _) => parent.clone(), ItemTrait(_, _, _, ref items) => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 333d32d76b6..82a3cdaa8cc 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -70,7 +70,7 @@ use syntax::ast::{ExprClosure, ExprLoop, ExprWhile, ExprMethodCall}; use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl}; use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics}; use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate}; -use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; +use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefTrait}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse}; use syntax::ast::{Local, MethodImplItem, Mod, Name, NodeId}; use syntax::ast::{Pat, PatEnum, PatIdent, PatLit}; @@ -2840,6 +2840,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } + ItemDefTrait(_, ref trait_ref) => { + self.resolve_trait_reference(item.id, trait_ref, TraitImplementation); + } ItemImpl(_, _, ref generics, ref implemented_traits, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0b78af18e26..6fa019a2914 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -648,6 +648,9 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { predicates, &enum_definition.variants); }, + ast::ItemDefTrait(_, ref ast_trait_ref) => { + + } ast::ItemImpl(_, _, ref generics, ref opt_trait_ref, @@ -1141,6 +1144,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs)); ty::TypeScheme { ty: t, generics: ty_generics } } + ast::ItemDefTrait(..) | ast::ItemTrait(..) | ast::ItemImpl(..) | ast::ItemMod(..) | diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index 1adcf133bf3..7ba589019c5 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -476,6 +476,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> { ast::ItemExternCrate(_) | ast::ItemUse(_) | + ast::ItemDefTrait(..) | ast::ItemImpl(..) | ast::ItemStatic(..) | ast::ItemConst(..) | @@ -626,6 +627,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { ast::ItemForeignMod(..) | ast::ItemTy(..) | ast::ItemImpl(..) | + ast::ItemDefTrait(..) | ast::ItemMac(..) => { } } From a962d47ef8a93ad125571a5628a883d0b50a97e7 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Sat, 24 Jan 2015 14:17:24 +0100 Subject: [PATCH 03/32] look for default trait candidates --- src/librustc/metadata/csearch.rs | 4 ++++ src/librustc/metadata/decoder.rs | 9 ++++++++ src/librustc/middle/traits/mod.rs | 11 ++++++--- src/librustc/middle/traits/project.rs | 1 + src/librustc/middle/traits/select.rs | 16 ++++++++++++-- src/librustc/middle/traits/util.rs | 3 +++ src/librustc/middle/ty.rs | 32 ++++++++++++++++++++++++--- src/librustc/middle/ty_fold.rs | 1 + src/librustc_trans/trans/meth.rs | 3 +++ src/librustc_typeck/collect.rs | 3 +++ 10 files changed, 75 insertions(+), 8 deletions(-) diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 7eeb0589118..db7e0f4d60f 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -410,3 +410,7 @@ pub fn is_associated_type(cstore: &cstore::CStore, def: ast::DefId) -> bool { decoder::is_associated_type(&*cdata, def.node) } +pub fn is_default_trait(cstore: &cstore::CStore, def: ast::DefId) -> bool { + let cdata = cstore.get_crate_data(def.krate); + decoder::is_default_trait(&*cdata, def.node) +} diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index d4512f51980..065d78879f1 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1563,3 +1563,12 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool { Some(item) => item_sort(item) == 't', } } + + +pub fn is_default_trait<'tcx>(cdata: Cmd, id: ast::NodeId) -> bool { + let item_doc = lookup_item(id, cdata.data()); + match item_family(item_doc) { + Family::DefTrait => true, + _ => false + } +} diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index a63dcfc24a1..9c71650c7be 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -221,6 +221,9 @@ pub enum Vtable<'tcx, N> { /// Vtable identifying a particular impl. VtableImpl(VtableImplData<'tcx, N>), + /// Vtable for default trait implementations + VtableDefaultTrait(ast::DefId), + /// Successful resolution to an obligation provided by the caller /// for some type parameter. The `Vec` represents the /// obligations incurred from normalizing the where-clause (if @@ -513,17 +516,18 @@ impl<'tcx, N> Vtable<'tcx, N> { pub fn iter_nested(&self) -> Iter { match *self { VtableImpl(ref i) => i.iter_nested(), - VtableFnPointer(..) => (&[]).iter(), - VtableClosure(..) => (&[]).iter(), VtableParam(ref n) => n.iter(), - VtableObject(_) => (&[]).iter(), VtableBuiltin(ref i) => i.iter_nested(), + VtableObject(_) | + VtableDefaultTrait(..) | VtableFnPointer(..) | + VtableClosure(..) => (&[]).iter(), } } pub fn map_nested(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M { match *self { VtableImpl(ref i) => VtableImpl(i.map_nested(op)), + VtableDefaultTrait(t) => VtableDefaultTrait(t), VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()), VtableClosure(d, ref s) => VtableClosure(d, s.clone()), VtableParam(ref n) => VtableParam(n.iter().map(op).collect()), @@ -539,6 +543,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableImpl(i) => VtableImpl(i.map_move_nested(op)), VtableFnPointer(sig) => VtableFnPointer(sig), VtableClosure(d, s) => VtableClosure(d, s), + VtableDefaultTrait(t) => VtableDefaultTrait(t), VtableParam(n) => VtableParam(n.into_iter().map(op).collect()), VtableObject(p) => VtableObject(p), VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)), diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 13f309e129a..ecfd02b69fc 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -709,6 +709,7 @@ fn assemble_candidates_from_impls<'cx,'tcx>( // projection. And the projection where clause is handled // in `assemble_candidates_from_param_env`. } + super::VtableDefaultTrait(..) | super::VtableBuiltin(..) => { // These traits have no associated types. selcx.tcx().sess.span_bug( diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 0e298920841..15a1e3ad34b 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -26,7 +26,7 @@ use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch use super::{Selection}; use super::{SelectionResult}; use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure, - VtableFnPointer, VtableObject}; + VtableFnPointer, VtableObject, VtableDefaultTrait}; use super::{VtableImplData, VtableObjectData, VtableBuiltinData}; use super::object_safety; use super::{util}; @@ -136,6 +136,7 @@ enum SelectionCandidate<'tcx> { BuiltinCandidate(ty::BuiltinBound), ParamCandidate(ty::PolyTraitRef<'tcx>), ImplCandidate(ast::DefId), + DefaultTraitCandidate(ast::DefId), /// This is a trait matching with a projected type as `Self`, and /// we found an applicable bound in the trait definition. @@ -1130,7 +1131,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); debug!("assemble_candidates_from_impls(self_ty={})", self_ty.repr(self.tcx())); - let all_impls = self.all_impls(obligation.predicate.def_id()); + let def_id = obligation.predicate.def_id(); + let all_impls = self.all_impls(def_id); for &impl_def_id in &all_impls { self.infcx.probe(|snapshot| { let (skol_obligation_trait_pred, skol_map) = @@ -1144,6 +1146,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } }); } + + if self.tcx().default_trait_impls.borrow().contains(&def_id) { + candidates.vec.push(DefaultTraitCandidate(def_id.clone())) + } + Ok(()) } @@ -1646,6 +1653,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(VtableParam(obligations)) } + DefaultTraitCandidate(trait_def_id) => { + Ok(VtableDefaultTrait(trait_def_id)) + } + ImplCandidate(impl_def_id) => { let vtable_impl = try!(self.confirm_impl_candidate(obligation, impl_def_id)); @@ -2308,6 +2319,7 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> { BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b), ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)), ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)), + DefaultTraitCandidate(t) => format!("DefaultTraitCandidate({:?})", t), ProjectionCandidate => format!("ProjectionCandidate"), FnPointerCandidate => format!("FnPointerCandidate"), ObjectCandidate => { diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 6c54da1c134..a0affcff2ce 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -444,6 +444,9 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> { super::VtableImpl(ref v) => v.repr(tcx), + super::VtableDefaultTrait(ref t) => + format!("VtableDefaultTrait({:?})", t), + super::VtableClosure(ref d, ref s) => format!("VtableClosure({},{})", d.repr(tcx), diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index e9908397f97..5652f23a16d 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -757,6 +757,9 @@ pub struct ctxt<'tcx> { /// Maps a trait onto a list of impls of that trait. pub trait_impls: RefCell>>>>, + /// Maps a trait onto a list of *default* trait implementations + pub default_trait_impls: RefCell, + /// Maps a DefId of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. @@ -2493,6 +2496,7 @@ pub fn mk_ctxt<'tcx>(s: Session, destructor_for_type: RefCell::new(DefIdMap()), destructors: RefCell::new(DefIdSet()), trait_impls: RefCell::new(DefIdMap()), + default_trait_impls: RefCell::new(DefIdSet()), inherent_impls: RefCell::new(DefIdMap()), impl_items: RefCell::new(DefIdMap()), used_unsafe: RefCell::new(NodeSet()), @@ -5992,6 +5996,18 @@ pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc { || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id))) } +/// Records a trait-to-implementation mapping. +pub fn record_default_trait_implementation(tcx: &ctxt, trait_def_id: DefId) { + + //assert!(did.krate != ast::LOCAL_CRATE); + if tcx.default_trait_impls.borrow().contains(&trait_def_id) { + return; + } + + tcx.default_trait_impls.borrow_mut().insert(trait_def_id); +} + + /// Records a trait-to-implementation mapping. pub fn record_trait_implementation(tcx: &ctxt, trait_def_id: DefId, @@ -6074,11 +6090,21 @@ pub fn populate_implementations_for_trait_if_necessary( } csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id, - |implementation_def_id| { + |implementation_def_id|{ let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id); - // Record the trait->implementation mapping. - record_trait_implementation(tcx, trait_id, implementation_def_id); + if csearch::is_default_trait(&tcx.sess.cstore, implementation_def_id) { + record_default_trait_implementation(tcx, trait_id); + tcx.populated_external_traits.borrow_mut().insert(trait_id); + + // Nothing else to do for default trait implementations since + // they are not allowed to have type parameters, methods, or any + // other item that could be associated to a trait implementation. + return; + } else { + // Record the trait->implementation mapping. + record_trait_implementation(tcx, trait_id, implementation_def_id); + } // For any methods that use a default implementation, add them to // the map. This is a bit unfortunate. diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 5e46ce08e4f..3f11655e16e 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -519,6 +519,7 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> fn fold_with>(&self, folder: &mut F) -> traits::Vtable<'tcx, N> { match *self { traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)), + traits::VtableDefaultTrait(t) => traits::VtableDefaultTrait(t), traits::VtableClosure(d, ref s) => { traits::VtableClosure(d, s.fold_with(folder)) } diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 1d5d24a6403..1f90e4ae023 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -390,6 +390,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Callee { bcx: bcx, data: Fn(llfn) } } traits::VtableBuiltin(..) | + traits::VtableDefaultTrait(..) | traits::VtableParam(..) => { bcx.sess().bug( &format!("resolved vtable bad vtable {} in trans", @@ -714,6 +715,8 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let methods = traits::supertraits(tcx, trait_ref.clone()).flat_map(|trait_ref| { let vtable = fulfill_obligation(ccx, DUMMY_SP, trait_ref.clone()); match vtable { + // Should default trait error here? + traits::VtableDefaultTrait(_) | traits::VtableBuiltin(_) => { Vec::new().into_iter() } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 6fa019a2914..a20fa54f822 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -649,7 +649,10 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { &enum_definition.variants); }, ast::ItemDefTrait(_, ref ast_trait_ref) => { + let trait_ref = astconv::instantiate_trait_ref(ccx, &ExplicitRscope, + ast_trait_ref, None, None); + ty::record_default_trait_implementation(tcx, trait_ref.def_id) } ast::ItemImpl(_, _, ref generics, From 839a9de8d385a082b571a88ff5a7f0c620afed1c Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Sat, 24 Jan 2015 15:08:01 +0100 Subject: [PATCH 04/32] Prefer other implementations over default ones --- src/librustc/middle/traits/select.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 15a1e3ad34b..b670c9cb1e1 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1273,6 +1273,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // #18453. true } + (&DefaultTraitCandidate(_), _) => { + // Prefer other candidates over default implementations. + true + } (&ProjectionCandidate, &ParamCandidate(_)) => { // FIXME(#20297) -- this gives where clauses precedent // over projections. Really these are just two means From ad3e748128dc52d55820acc07aa034f61f90006d Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Mon, 26 Jan 2015 20:08:43 +0100 Subject: [PATCH 05/32] Don't allow default impls for traits outside their crate --- src/librustc_typeck/coherence/orphan.rs | 10 ++++++++++ src/librustc_typeck/diagnostics.rs | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index f43469363cd..9a730093c7d 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -96,6 +96,16 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { } } } + ast::ItemDefTrait(_, ref ast_trait_ref) => { + // "Trait" impl + debug!("coherence2::orphan check: default trait impl {}", item.repr(self.tcx)); + let trait_ref = ty::node_id_to_trait_ref(self.tcx, ast_trait_ref.ref_id); + if trait_ref.def_id.krate != ast::LOCAL_CRATE { + span_err!(self.tcx.sess, item.span, E0316, + "cannot create default implementations for traits outside the \ + crate they're defined in; define a new trait instead."); + } + } _ => { // Not an impl } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 17cf92d39d8..f610f71cd42 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -171,7 +171,8 @@ register_diagnostics! { E0247, // found module name used as a type E0248, // found value name used as a type E0249, // expected constant expr for array length - E0250 // expected constant expr for array length + E0250, // expected constant expr for array length + E0316 // can't create default impls for traits outside their crates } __build_diagnostic_array! { DIAGNOSTICS } From bd511f73be526640ae98012d302201a019f9b458 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Mon, 26 Jan 2015 21:30:56 +0100 Subject: [PATCH 06/32] Add negative impls for `*const T` and `*mut T` --- src/libcore/lib.rs | 1 + src/libcore/marker.rs | 6 ++++++ src/librustc/middle/traits/select.rs | 6 ++++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 3c58480ff0c..0370d6473d7 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -68,6 +68,7 @@ #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(rustc_attrs)] +#![feature(optin_builtin_traits)] #[macro_use] mod macros; diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index d284eb34179..eefb6ef7703 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -49,6 +49,9 @@ pub unsafe trait Send : MarkerTrait { // empty. } +impl !Send for *const T { } +impl !Send for *mut T { } + /// Types with a constant size known at compile-time. #[stable(feature = "rust1", since = "1.0.0")] #[lang="sized"] @@ -214,6 +217,9 @@ pub unsafe trait Sync : MarkerTrait { // Empty } +impl !Sync for *const T { } +impl !Sync for *mut T { } + /// A type which is considered "not POD", meaning that it is not /// implicitly copyable. This is typically embedded in other types to /// ensure that they are never copied, even if they lack a destructor. diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index b670c9cb1e1..53fdab1cd07 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1377,8 +1377,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::BoundSync | ty::BoundSend => { - // sync and send are not implemented for *const, *mut - Err(Unimplemented) + self.tcx().sess.bug( + &format!( + "raw pointers should have a negative \ + impl for `Send` and `Sync`")[]); } } } From 7ae8889286535446f9a7c0d4c3e214b55d7063e6 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Mon, 26 Jan 2015 23:10:24 +0100 Subject: [PATCH 07/32] Add negative impls for Sync --- src/libcore/cell.rs | 4 +++- src/libcore/marker.rs | 2 ++ src/librustc/middle/traits/select.rs | 20 ++++---------------- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index eb138e6142b..b8a22c30f9e 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -144,7 +144,7 @@ use clone::Clone; use cmp::PartialEq; use default::Default; -use marker::{Copy, Send}; +use marker::{Copy, Send, Sync}; use ops::{Deref, DerefMut, Drop}; use option::Option; use option::Option::{None, Some}; @@ -660,6 +660,8 @@ pub struct UnsafeCell { pub value: T, } +impl !Sync for UnsafeCell {} + impl UnsafeCell { /// Construct a new instance of `UnsafeCell` which will wrap the specified /// value. diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index eefb6ef7703..b5d533f104c 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -51,6 +51,7 @@ pub unsafe trait Send : MarkerTrait { impl !Send for *const T { } impl !Send for *mut T { } +impl !Send for Managed { } /// Types with a constant size known at compile-time. #[stable(feature = "rust1", since = "1.0.0")] @@ -219,6 +220,7 @@ pub unsafe trait Sync : MarkerTrait { impl !Sync for *const T { } impl !Sync for *mut T { } +impl !Sync for Managed { } /// A type which is considered "not POD", meaning that it is not /// implicitly copyable. This is typically embedded in other types to diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 53fdab1cd07..9fade728b36 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -826,6 +826,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => { + // Ideally, we shouldn't sepcial case Send/Sync. This will be unified + // as soon as default trait implementations for these traits land. try!(self.assemble_candidates_from_impls(obligation, &mut candidates)); // No explicit impls were declared for this type, consider the fallback rules. @@ -1599,27 +1601,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { -> Result,SelectionError<'tcx>> { // First check for markers and other nonsense. - let tcx = this.tcx(); match bound { - ty::BoundSend => { - if Some(def_id) == tcx.lang_items.managed_bound() { - return Err(Unimplemented) - } - } - ty::BoundCopy => { return Ok(ParameterBuiltin) } - ty::BoundSync => { - if - Some(def_id) == tcx.lang_items.managed_bound() || - Some(def_id) == tcx.lang_items.unsafe_cell_type() - { - return Err(Unimplemented) - } - } - + ty::BoundSend | + ty::BoundSync | ty::BoundSized => { } } From 58a8103df9077d581a7b17824a7a4b9be695ec5f Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Tue, 27 Jan 2015 00:35:03 +0100 Subject: [PATCH 08/32] Fix rustdoc fallout --- src/librustdoc/doctree.rs | 8 ++++++++ src/librustdoc/visit_ast.rs | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index ba5df56f4fb..555e66e3a1e 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -39,6 +39,7 @@ pub struct Module { pub vis: ast::Visibility, pub stab: Option, pub impls: Vec, + pub def_traits: Vec, pub foreigns: Vec, pub macros: Vec, pub is_crate: bool, @@ -65,6 +66,7 @@ impl Module { constants : Vec::new(), traits : Vec::new(), impls : Vec::new(), + def_traits : Vec::new(), foreigns : Vec::new(), macros : Vec::new(), is_crate : false, @@ -196,6 +198,12 @@ pub struct Impl { pub id: ast::NodeId, } +pub struct DefaultTrait { + pub unsafety: ast::Unsafety, + pub trait_: ast::TraitRef, + pub id: ast::NodeId, +} + pub struct Macro { pub name: Ident, pub id: ast::NodeId, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index c52b0bab1fa..e77510785e9 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -358,6 +358,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; om.impls.push(i); }, + ast::ItemDefTrait(unsafety, ref trait_ref) => { + let i = DefaultTrait { + unsafety: unsafety, + trait_: trait_ref.clone(), + id: item.id + }; + om.def_traits.push(i); + } ast::ItemForeignMod(ref fm) => { om.foreigns.push(fm.clone()); } From 4b09209efea1ef7275b34ff3b9d3c4859aa45c8f Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Mon, 2 Feb 2015 12:14:01 +0100 Subject: [PATCH 09/32] Ensure default trait impls hold --- src/librustc/middle/traits/mod.rs | 37 ++++++- src/librustc/middle/traits/select.rs | 160 +++++++++++++++++++++++++-- src/librustc/middle/traits/util.rs | 47 ++++++-- src/librustc/middle/ty.rs | 4 +- src/librustc/middle/ty_fold.rs | 11 +- 5 files changed, 239 insertions(+), 20 deletions(-) diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 9c71650c7be..93e5d38637f 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -222,7 +222,7 @@ pub enum Vtable<'tcx, N> { VtableImpl(VtableImplData<'tcx, N>), /// Vtable for default trait implementations - VtableDefaultTrait(ast::DefId), + VtableDefaultTrait(VtableDefaultTraitData), /// Successful resolution to an obligation provided by the caller /// for some type parameter. The `Vec` represents the @@ -262,6 +262,12 @@ pub struct VtableImplData<'tcx, N> { pub nested: subst::VecPerParamSpace } +#[derive(Debug,Clone)] +pub struct VtableDefaultTraitData { + pub trait_def_id: ast::DefId, + pub nested: subst::VecPerParamSpace +} + #[derive(Debug,Clone)] pub struct VtableBuiltinData { pub nested: subst::VecPerParamSpace @@ -527,7 +533,7 @@ impl<'tcx, N> Vtable<'tcx, N> { pub fn map_nested(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M { match *self { VtableImpl(ref i) => VtableImpl(i.map_nested(op)), - VtableDefaultTrait(t) => VtableDefaultTrait(t), + VtableDefaultTrait(ref t) => VtableDefaultTrait(t.map_nested(op)), VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()), VtableClosure(d, ref s) => VtableClosure(d, s.clone()), VtableParam(ref n) => VtableParam(n.iter().map(op).collect()), @@ -543,7 +549,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableImpl(i) => VtableImpl(i.map_move_nested(op)), VtableFnPointer(sig) => VtableFnPointer(sig), VtableClosure(d, s) => VtableClosure(d, s), - VtableDefaultTrait(t) => VtableDefaultTrait(t), + VtableDefaultTrait(t) => VtableDefaultTrait(t.map_move_nested(op)), VtableParam(n) => VtableParam(n.into_iter().map(op).collect()), VtableObject(p) => VtableObject(p), VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)), @@ -578,6 +584,31 @@ impl<'tcx, N> VtableImplData<'tcx, N> { } } +impl VtableDefaultTraitData { + pub fn iter_nested(&self) -> Iter { + self.nested.iter() + } + + pub fn map_nested(&self, op: F) -> VtableDefaultTraitData where + F: FnMut(&N) -> M, + { + VtableDefaultTraitData { + trait_def_id: self.trait_def_id, + nested: self.nested.map(op) + } + } + + pub fn map_move_nested(self, op: F) -> VtableDefaultTraitData where + F: FnMut(N) -> M, + { + let VtableDefaultTraitData { trait_def_id, nested } = self; + VtableDefaultTraitData { + trait_def_id: trait_def_id, + nested: nested.map_move(op) + } + } +} + impl VtableBuiltinData { pub fn iter_nested(&self) -> Iter { self.nested.iter() diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 9fade728b36..2a920721963 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -21,13 +21,13 @@ use super::{DerivedObligationCause}; use super::{project}; use super::project::Normalized; use super::{PredicateObligation, TraitObligation, ObligationCause}; -use super::{ObligationCauseCode, BuiltinDerivedObligation}; +use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation}; use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch}; use super::{Selection}; use super::{SelectionResult}; use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure, VtableFnPointer, VtableObject, VtableDefaultTrait}; -use super::{VtableImplData, VtableObjectData, VtableBuiltinData}; +use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableDefaultTraitData}; use super::object_safety; use super::{util}; @@ -1535,7 +1535,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::struct_fields(self.tcx(), def_id, substs).iter() .map(|f| f.mt.ty) .collect(); - nominal(self, bound, def_id, types) + nominal(bound, types) } ty::ty_enum(def_id, substs) => { @@ -1545,7 +1545,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .flat_map(|variant| variant.args.iter()) .cloned() .collect(); - nominal(self, bound, def_id, types) + nominal(bound, types) } ty::ty_projection(_) | @@ -1594,9 +1594,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } }; - fn nominal<'cx, 'tcx>(this: &mut SelectionContext<'cx, 'tcx>, - bound: ty::BuiltinBound, - def_id: ast::DefId, + fn nominal<'cx, 'tcx>(bound: ty::BuiltinBound, types: Vec>) -> Result,SelectionError<'tcx>> { @@ -1615,6 +1613,89 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + fn constituent_types(&self, t: Ty<'tcx>) -> Vec> { + match t.sty { + ty::ty_uint(_) | + ty::ty_int(_) | + ty::ty_bool | + ty::ty_float(_) | + ty::ty_bare_fn(..) | + ty::ty_str | + ty::ty_err | + ty::ty_char => { + Vec::new() + } + + ty::ty_projection(..) | + ty::ty_param(..) | + ty::ty_infer(..) => { + self.tcx().sess.bug( + &format!( + "asked to assemble constituent types of unexpected type: {}", + t.repr(self.tcx()))[]); + } + + ty::ty_uniq(referent_ty) => { // Box + vec![referent_ty] + } + + + ty::ty_trait(ref data) => { + // Recursively check all supertraits to find out if any further + // bounds are required and thus we must fulfill. + let principal = + data.principal_trait_ref_with_self_ty(self.tcx(), + self.tcx().types.err); + + + util::supertraits(self.tcx(), principal).map(|tr| tr.self_ty()).collect() + } + + ty::ty_open(element_ty) => {vec![element_ty]}, + + ty::ty_ptr(ty::mt { ty: element_ty, ..}) | + ty::ty_rptr(_, ty::mt { ty: element_ty, ..}) => { + vec![element_ty] + }, + + ty::ty_vec(element_ty, _) => { + vec![element_ty] + } + + ty::ty_tup(ref tys) => { + // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet + tys.clone() + } + + ty::ty_closure(def_id, _, substs) => { + assert_eq!(def_id.krate, ast::LOCAL_CRATE); + + match self.closure_typer.closure_upvars(def_id, substs) { + Some(upvars) => { + upvars.iter().map(|c| c.ty).collect() + } + None => { + Vec::new() + } + } + } + + ty::ty_struct(def_id, substs) => { + ty::struct_fields(self.tcx(), def_id, substs).iter() + .map(|f| f.mt.ty) + .collect() + } + + ty::ty_enum(def_id, substs) => { + ty::substd_enum_variants(self.tcx(), def_id, substs) + .iter() + .flat_map(|variant| variant.args.iter()) + .map(|&ty| ty) + .collect() + } + } + } + /////////////////////////////////////////////////////////////////////////// // CONFIRMATION // @@ -1648,7 +1729,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } DefaultTraitCandidate(trait_def_id) => { - Ok(VtableDefaultTrait(trait_def_id)) + let data = try!(self.confirm_default_impl_candidate(obligation, trait_def_id)); + Ok(VtableDefaultTrait(data)) } ImplCandidate(impl_def_id) => { @@ -1783,6 +1865,68 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { VtableBuiltinData { nested: obligations } } + fn confirm_default_impl_candidate(&mut self, + obligation: &TraitObligation<'tcx>, + impl_def_id: ast::DefId) + -> Result>, + SelectionError<'tcx>> + { + debug!("confirm_default_impl_candidate({}, {})", + obligation.repr(self.tcx()), + impl_def_id.repr(self.tcx())); + + let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty()); + let types = self.constituent_types(self_ty); + Ok(self.vtable_default_impl(obligation, impl_def_id, types)) + } + + fn vtable_default_impl(&mut self, + obligation: &TraitObligation<'tcx>, + trait_def_id: ast::DefId, + nested: Vec>) + -> VtableDefaultTraitData> + { + let derived_cause = self.derived_cause(obligation, ImplDerivedObligation); + let obligations = nested.iter().map(|&nested_ty| { + // the obligation might be higher-ranked, e.g. for<'a> &'a + // int : Copy. In that case, we will wind up with + // late-bound regions in the `nested` vector. So for each + // one we instantiate to a skolemized region, do our work + // to produce something like `&'0 int : Copy`, and then + // re-bind it. This is a bit of busy-work but preserves + // the invariant that we only manipulate free regions, not + // bound ones. + self.infcx.try(|snapshot| { + let (skol_ty, skol_map) = + self.infcx().skolemize_late_bound_regions(&ty::Binder(nested_ty), snapshot); + let skol_predicate = + util::predicate_for_default_trait_impl( + self.tcx(), + derived_cause.clone(), + trait_def_id, + obligation.recursion_depth + 1, + skol_ty); + match skol_predicate { + Ok(skol_predicate) => Ok(self.infcx().plug_leaks(skol_map, snapshot, + &skol_predicate)), + Err(ErrorReported) => Err(ErrorReported) + } + }) + }).collect::>(); + let obligations = match obligations { + Ok(o) => o, + Err(ErrorReported) => Vec::new() + }; + + let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new()); + debug!("vtable_default_impl_data: obligations={}", obligations.repr(self.tcx())); + + VtableDefaultTraitData { + trait_def_id: trait_def_id, + nested: obligations + } + } + fn confirm_impl_candidate(&mut self, obligation: &TraitObligation<'tcx>, impl_def_id: ast::DefId) diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index a0affcff2ce..771c6ad3a5e 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -20,7 +20,7 @@ use util::nodemap::FnvHashSet; use util::ppaux::Repr; use super::{Obligation, ObligationCause, PredicateObligation, - VtableImpl, VtableParam, VtableImplData}; + VtableImpl, VtableParam, VtableImplData, VtableDefaultTraitData}; struct PredicateSet<'a,'tcx:'a> { tcx: &'a ty::ctxt<'tcx>, @@ -323,6 +323,35 @@ pub fn trait_ref_for_builtin_bound<'tcx>( } } +pub fn predicate_for_trait_ref<'tcx>( + tcx: &ty::ctxt<'tcx>, + cause: ObligationCause<'tcx>, + trait_ref: Rc>, + recursion_depth: uint) + -> Result, ErrorReported> +{ + Ok(Obligation { + cause: cause, + recursion_depth: recursion_depth, + predicate: trait_ref.as_predicate(), + }) +} + +pub fn predicate_for_default_trait_impl<'tcx>( + tcx: &ty::ctxt<'tcx>, + cause: ObligationCause<'tcx>, + trait_def_id: ast::DefId, + recursion_depth: uint, + param_ty: Ty<'tcx>) + -> Result, ErrorReported> +{ + let trait_ref = Rc::new(ty::TraitRef { + def_id: trait_def_id, + substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty)) + }); + predicate_for_trait_ref(tcx, cause, trait_ref, recursion_depth) +} + pub fn predicate_for_builtin_bound<'tcx>( tcx: &ty::ctxt<'tcx>, cause: ObligationCause<'tcx>, @@ -332,11 +361,7 @@ pub fn predicate_for_builtin_bound<'tcx>( -> Result, ErrorReported> { let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty)); - Ok(Obligation { - cause: cause, - recursion_depth: recursion_depth, - predicate: trait_ref.as_predicate(), - }) + predicate_for_trait_ref(tcx, cause, trait_ref, recursion_depth) } /// Cast a trait reference into a reference to one of its super @@ -445,7 +470,7 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> { v.repr(tcx), super::VtableDefaultTrait(ref t) => - format!("VtableDefaultTrait({:?})", t), + t.repr(tcx), super::VtableClosure(ref d, ref s) => format!("VtableClosure({},{})", @@ -486,6 +511,14 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData { } } +impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableDefaultTraitData { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { + format!("VtableDefaultTraitData(trait_def_id={}, nested={})", + self.trait_def_id.repr(tcx), + self.nested.repr(tcx)) + } +} + impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { format!("VtableObject(object_ty={})", diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 5652f23a16d..2fcee3d6213 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -5175,6 +5175,9 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) &None => None } } + ast::ItemDefTrait(_, ref ast_trait_ref) => { + Some(ty::node_id_to_trait_ref(cx, ast_trait_ref.ref_id)) + } _ => None } } @@ -5999,7 +6002,6 @@ pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc { /// Records a trait-to-implementation mapping. pub fn record_default_trait_implementation(tcx: &ctxt, trait_def_id: DefId) { - //assert!(did.krate != ast::LOCAL_CRATE); if tcx.default_trait_impls.borrow().contains(&trait_def_id) { return; } diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 3f11655e16e..8ed6af652ce 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -507,6 +507,15 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData< } } +impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultTraitData { + fn fold_with>(&self, folder: &mut F) -> traits::VtableDefaultTraitData { + traits::VtableDefaultTraitData { + trait_def_id: self.trait_def_id, + nested: self.nested.fold_with(folder), + } + } +} + impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinData { fn fold_with>(&self, folder: &mut F) -> traits::VtableBuiltinData { traits::VtableBuiltinData { @@ -519,7 +528,7 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> fn fold_with>(&self, folder: &mut F) -> traits::Vtable<'tcx, N> { match *self { traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)), - traits::VtableDefaultTrait(t) => traits::VtableDefaultTrait(t), + traits::VtableDefaultTrait(ref t) => traits::VtableDefaultTrait(t.fold_with(folder)), traits::VtableClosure(d, ref s) => { traits::VtableClosure(d, s.fold_with(folder)) } From d523acb495eaacd76d4297362c98c571cae87089 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Wed, 4 Feb 2015 11:51:17 +0100 Subject: [PATCH 10/32] Use a Vec instead of VecPerParamSpace --- src/librustc/middle/traits/mod.rs | 6 +++--- src/librustc/middle/traits/select.rs | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 93e5d38637f..a829f35b690 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -265,7 +265,7 @@ pub struct VtableImplData<'tcx, N> { #[derive(Debug,Clone)] pub struct VtableDefaultTraitData { pub trait_def_id: ast::DefId, - pub nested: subst::VecPerParamSpace + pub nested: Vec } #[derive(Debug,Clone)] @@ -594,7 +594,7 @@ impl VtableDefaultTraitData { { VtableDefaultTraitData { trait_def_id: self.trait_def_id, - nested: self.nested.map(op) + nested: self.nested.iter().map(op).collect() } } @@ -604,7 +604,7 @@ impl VtableDefaultTraitData { let VtableDefaultTraitData { trait_def_id, nested } = self; VtableDefaultTraitData { trait_def_id: trait_def_id, - nested: nested.map_move(op) + nested: nested.into_iter().map(op).collect() } } } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 2a920721963..3d331e6f2fe 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1918,7 +1918,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Err(ErrorReported) => Vec::new() }; - let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new()); debug!("vtable_default_impl_data: obligations={}", obligations.repr(self.tcx())); VtableDefaultTraitData { From 7e382132a57953e09bbb4e41152107032d69a2cf Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Sat, 7 Feb 2015 11:10:19 +0100 Subject: [PATCH 11/32] Make default_trait_impls private and add accessor --- src/librustc/middle/traits/select.rs | 2 +- src/librustc/middle/ty.rs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 3d331e6f2fe..e729b678c32 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1149,7 +1149,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); } - if self.tcx().default_trait_impls.borrow().contains(&def_id) { + if ty::trait_has_default_impl(self.tcx(), def_id) { candidates.vec.push(DefaultTraitCandidate(def_id.clone())) } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 2fcee3d6213..782f0b19814 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -758,7 +758,7 @@ pub struct ctxt<'tcx> { pub trait_impls: RefCell>>>>, /// Maps a trait onto a list of *default* trait implementations - pub default_trait_impls: RefCell, + default_trait_impls: RefCell, /// Maps a DefId of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. @@ -5999,6 +5999,10 @@ pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc { || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id))) } +pub fn trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) -> bool { + tcx.default_trait_impls.borrow().contains(&trait_def_id) +} + /// Records a trait-to-implementation mapping. pub fn record_default_trait_implementation(tcx: &ctxt, trait_def_id: DefId) { From d38aab397e3295ead5869f84cd54044c1759c6d7 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Sat, 7 Feb 2015 14:24:34 +0100 Subject: [PATCH 12/32] Rename DefTrait to DefaultImpl --- src/librustc/metadata/decoder.rs | 14 ++++++------- src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/astencode.rs | 2 +- src/librustc/middle/def.rs | 4 ++-- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/reachable.rs | 2 +- src/librustc/middle/resolve_lifetime.rs | 4 ++-- src/librustc/middle/traits/mod.rs | 22 ++++++++++----------- src/librustc/middle/traits/project.rs | 2 +- src/librustc/middle/traits/select.rs | 22 ++++++++++----------- src/librustc/middle/traits/util.rs | 8 ++++---- src/librustc/middle/ty.rs | 2 +- src/librustc/middle/ty_fold.rs | 8 ++++---- src/librustc_privacy/lib.rs | 8 ++++---- src/librustc_resolve/build_reduced_graph.rs | 8 ++++---- src/librustc_resolve/lib.rs | 10 +++++----- src/librustc_trans/save/mod.rs | 2 +- src/librustc_trans/trans/callee.rs | 2 +- src/librustc_trans/trans/meth.rs | 4 ++-- src/librustc_typeck/astconv.rs | 8 ++++---- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustc_typeck/check/mod.rs | 6 +++--- src/librustc_typeck/coherence/orphan.rs | 2 +- src/librustc_typeck/collect.rs | 4 ++-- src/librustc_typeck/variance.rs | 4 ++-- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/doctree.rs | 4 ++-- src/librustdoc/visit_ast.rs | 4 ++-- src/libsyntax/ast.rs | 4 ++-- src/libsyntax/ast_map/mod.rs | 2 +- src/libsyntax/fold.rs | 4 ++-- src/libsyntax/parse/parser.rs | 4 ++-- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 2 +- 36 files changed, 93 insertions(+), 93 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 065d78879f1..b5738650ccb 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -126,7 +126,7 @@ enum Family { TupleVariant, // v StructVariant, // V Impl, // i - DefTrait, // d + DefaultImpl, // d Trait, // I Struct, // S PublicField, // g @@ -152,7 +152,7 @@ fn item_family(item: rbml::Doc) -> Family { 'v' => TupleVariant, 'V' => StructVariant, 'i' => Impl, - 'd' => DefTrait, + 'd' => DefaultImpl, 'I' => Trait, 'S' => Struct, 'g' => PublicField, @@ -357,9 +357,9 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) let enum_did = item_reqd_and_translated_parent_item(cnum, item); DlDef(def::DefVariant(enum_did, did, false)) } - Trait => DlDef(def::DefTrait(did)), + Trait => DlDef(def::DefaultImpl(did)), Enum => DlDef(def::DefTy(did, true)), - Impl | DefTrait => DlImpl(did), + Impl | DefaultImpl => DlImpl(did), PublicField | InheritedField => DlField, } } @@ -482,7 +482,7 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd, let item_doc = lookup_item(id, cdata.data()); let fam = item_family(item_doc); match fam { - Family::Impl | Family::DefTrait => { + Family::Impl | Family::DefaultImpl => { reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| { doc_trait_ref(tp, tcx, cdata) }) @@ -1358,7 +1358,7 @@ pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) let parent_item_doc = lookup_item(parent_item_id.node, cdata.data()); match item_family(parent_item_doc) { Trait => Some(item_def_id(parent_item_doc, cdata)), - Impl | DefTrait => { + Impl | DefaultImpl => { reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref) .map(|_| item_trait_ref(parent_item_doc, tcx, cdata).def_id) } @@ -1568,7 +1568,7 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool { pub fn is_default_trait<'tcx>(cdata: Cmd, id: ast::NodeId) -> bool { let item_doc = lookup_item(id, cdata.data()); match item_family(item_doc) { - Family::DefTrait => true, + Family::DefaultImpl => true, _ => false } } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index fc9d2a13834..df4a556a870 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1201,7 +1201,7 @@ fn encode_info_for_item(ecx: &EncodeContext, None => {} } } - ast::ItemDefTrait(unsafety, ref ast_trait_ref) => { + ast::ItemDefaultImpl(unsafety, ref ast_trait_ref) => { add_to_index(item, rbml_w, index); rbml_w.start_tag(tag_items_data_item); encode_def_id(rbml_w, def_id); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index ae10eb686b0..cbed978d16f 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -440,7 +440,7 @@ impl tr for def::Def { def::DefVariant(e_did, v_did, is_s) => { def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s) }, - def::DefTrait(did) => def::DefTrait(did.tr(dcx)), + def::DefaultImpl(did) => def::DefaultImpl(did.tr(dcx)), def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum), def::DefAssociatedTy(did) => def::DefAssociatedTy(did.tr(dcx)), def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did), ident) => diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index 7857bcad813..009bfaf8728 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -38,7 +38,7 @@ pub enum Def { // type `U` (indicated by the Ident). // FIXME(#20301) -- should use Name DefAssociatedPath(TyParamProvenance, ast::Ident), - DefTrait(ast::DefId), + DefaultImpl(ast::DefId), DefPrimTy(ast::PrimTy), DefTyParam(ParamSpace, u32, ast::DefId, ast::Name), DefUse(ast::DefId), @@ -135,7 +135,7 @@ impl Def { DefFn(id, _) | DefStaticMethod(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) | DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(id) | - DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) | + DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefaultImpl(id) | DefMethod(id, _, _) | DefConst(id) | DefAssociatedPath(TyParamProvenance::FromSelf(id), _) | DefAssociatedPath(TyParamProvenance::FromParam(id), _) => { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 4be7bb9c365..ab6dd927782 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -579,7 +579,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { Ok(self.cat_rvalue_node(id, span, expr_ty)) } def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) | - def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) | + def::DefaultImpl(_) | def::DefTy(..) | def::DefPrimTy(_) | def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) | def::DefLabel(_) | def::DefSelfTy(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> { diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 73a9f179fa0..58daad2176d 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -302,7 +302,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { ast::ItemMod(..) | ast::ItemForeignMod(..) | ast::ItemImpl(..) | ast::ItemTrait(..) | ast::ItemStruct(..) | ast::ItemEnum(..) | - ast::ItemDefTrait(..) => {} + ast::ItemDefaultImpl(..) => {} _ => { self.tcx.sess.span_bug(item.span, diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index ac3c85acd61..bef98f5bd02 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -115,7 +115,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { ast::ItemUse(_) | ast::ItemMod(..) | ast::ItemMac(..) | - ast::ItemDefTrait(..) | + ast::ItemDefaultImpl(..) | ast::ItemForeignMod(..) | ast::ItemStatic(..) | ast::ItemConst(..) => { @@ -169,7 +169,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { // if this path references a trait, then this will resolve to // a trait ref, which introduces a binding scope. match self.def_map.borrow().get(&id) { - Some(&def::DefTrait(..)) => { + Some(&def::DefaultImpl(..)) => { self.with(LateScope(&Vec::new(), self.scope), |_, this| { this.visit_path(path, id); }); diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index a829f35b690..c400dd5a78a 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -222,7 +222,7 @@ pub enum Vtable<'tcx, N> { VtableImpl(VtableImplData<'tcx, N>), /// Vtable for default trait implementations - VtableDefaultTrait(VtableDefaultTraitData), + VtableDefaultImpl(VtableDefaultImplData), /// Successful resolution to an obligation provided by the caller /// for some type parameter. The `Vec` represents the @@ -263,7 +263,7 @@ pub struct VtableImplData<'tcx, N> { } #[derive(Debug,Clone)] -pub struct VtableDefaultTraitData { +pub struct VtableDefaultImplData { pub trait_def_id: ast::DefId, pub nested: Vec } @@ -525,7 +525,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableParam(ref n) => n.iter(), VtableBuiltin(ref i) => i.iter_nested(), VtableObject(_) | - VtableDefaultTrait(..) | VtableFnPointer(..) | + VtableDefaultImpl(..) | VtableFnPointer(..) | VtableClosure(..) => (&[]).iter(), } } @@ -533,7 +533,7 @@ impl<'tcx, N> Vtable<'tcx, N> { pub fn map_nested(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M { match *self { VtableImpl(ref i) => VtableImpl(i.map_nested(op)), - VtableDefaultTrait(ref t) => VtableDefaultTrait(t.map_nested(op)), + VtableDefaultImpl(ref t) => VtableDefaultImpl(t.map_nested(op)), VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()), VtableClosure(d, ref s) => VtableClosure(d, s.clone()), VtableParam(ref n) => VtableParam(n.iter().map(op).collect()), @@ -549,7 +549,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableImpl(i) => VtableImpl(i.map_move_nested(op)), VtableFnPointer(sig) => VtableFnPointer(sig), VtableClosure(d, s) => VtableClosure(d, s), - VtableDefaultTrait(t) => VtableDefaultTrait(t.map_move_nested(op)), + VtableDefaultImpl(t) => VtableDefaultImpl(t.map_move_nested(op)), VtableParam(n) => VtableParam(n.into_iter().map(op).collect()), VtableObject(p) => VtableObject(p), VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)), @@ -584,25 +584,25 @@ impl<'tcx, N> VtableImplData<'tcx, N> { } } -impl VtableDefaultTraitData { +impl VtableDefaultImplData { pub fn iter_nested(&self) -> Iter { self.nested.iter() } - pub fn map_nested(&self, op: F) -> VtableDefaultTraitData where + pub fn map_nested(&self, op: F) -> VtableDefaultImplData where F: FnMut(&N) -> M, { - VtableDefaultTraitData { + VtableDefaultImplData { trait_def_id: self.trait_def_id, nested: self.nested.iter().map(op).collect() } } - pub fn map_move_nested(self, op: F) -> VtableDefaultTraitData where + pub fn map_move_nested(self, op: F) -> VtableDefaultImplData where F: FnMut(N) -> M, { - let VtableDefaultTraitData { trait_def_id, nested } = self; - VtableDefaultTraitData { + let VtableDefaultImplData { trait_def_id, nested } = self; + VtableDefaultImplData { trait_def_id: trait_def_id, nested: nested.into_iter().map(op).collect() } diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index ecfd02b69fc..7d4febb38e6 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -709,7 +709,7 @@ fn assemble_candidates_from_impls<'cx,'tcx>( // projection. And the projection where clause is handled // in `assemble_candidates_from_param_env`. } - super::VtableDefaultTrait(..) | + super::VtableDefaultImpl(..) | super::VtableBuiltin(..) => { // These traits have no associated types. selcx.tcx().sess.span_bug( diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index e729b678c32..7f1119fc344 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -26,8 +26,8 @@ use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch use super::{Selection}; use super::{SelectionResult}; use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure, - VtableFnPointer, VtableObject, VtableDefaultTrait}; -use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableDefaultTraitData}; + VtableFnPointer, VtableObject, VtableDefaultImpl}; +use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableDefaultImplData}; use super::object_safety; use super::{util}; @@ -136,7 +136,7 @@ enum SelectionCandidate<'tcx> { BuiltinCandidate(ty::BuiltinBound), ParamCandidate(ty::PolyTraitRef<'tcx>), ImplCandidate(ast::DefId), - DefaultTraitCandidate(ast::DefId), + DefaultImplCandidate(ast::DefId), /// This is a trait matching with a projected type as `Self`, and /// we found an applicable bound in the trait definition. @@ -1150,7 +1150,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if ty::trait_has_default_impl(self.tcx(), def_id) { - candidates.vec.push(DefaultTraitCandidate(def_id.clone())) + candidates.vec.push(DefaultImplCandidate(def_id.clone())) } Ok(()) @@ -1275,7 +1275,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // #18453. true } - (&DefaultTraitCandidate(_), _) => { + (&DefaultImplCandidate(_), _) => { // Prefer other candidates over default implementations. true } @@ -1728,9 +1728,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(VtableParam(obligations)) } - DefaultTraitCandidate(trait_def_id) => { + DefaultImplCandidate(trait_def_id) => { let data = try!(self.confirm_default_impl_candidate(obligation, trait_def_id)); - Ok(VtableDefaultTrait(data)) + Ok(VtableDefaultImpl(data)) } ImplCandidate(impl_def_id) => { @@ -1868,7 +1868,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_default_impl_candidate(&mut self, obligation: &TraitObligation<'tcx>, impl_def_id: ast::DefId) - -> Result>, + -> Result>, SelectionError<'tcx>> { debug!("confirm_default_impl_candidate({}, {})", @@ -1884,7 +1884,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_def_id: ast::DefId, nested: Vec>) - -> VtableDefaultTraitData> + -> VtableDefaultImplData> { let derived_cause = self.derived_cause(obligation, ImplDerivedObligation); let obligations = nested.iter().map(|&nested_ty| { @@ -1920,7 +1920,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("vtable_default_impl_data: obligations={}", obligations.repr(self.tcx())); - VtableDefaultTraitData { + VtableDefaultImplData { trait_def_id: trait_def_id, nested: obligations } @@ -2456,7 +2456,7 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> { BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b), ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)), ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)), - DefaultTraitCandidate(t) => format!("DefaultTraitCandidate({:?})", t), + DefaultImplCandidate(t) => format!("DefaultImplCandidate({:?})", t), ProjectionCandidate => format!("ProjectionCandidate"), FnPointerCandidate => format!("FnPointerCandidate"), ObjectCandidate => { diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 771c6ad3a5e..0308604aa8b 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -20,7 +20,7 @@ use util::nodemap::FnvHashSet; use util::ppaux::Repr; use super::{Obligation, ObligationCause, PredicateObligation, - VtableImpl, VtableParam, VtableImplData, VtableDefaultTraitData}; + VtableImpl, VtableParam, VtableImplData, VtableDefaultImplData}; struct PredicateSet<'a,'tcx:'a> { tcx: &'a ty::ctxt<'tcx>, @@ -469,7 +469,7 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> { super::VtableImpl(ref v) => v.repr(tcx), - super::VtableDefaultTrait(ref t) => + super::VtableDefaultImpl(ref t) => t.repr(tcx), super::VtableClosure(ref d, ref s) => @@ -511,9 +511,9 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData { } } -impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableDefaultTraitData { +impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableDefaultImplData { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { - format!("VtableDefaultTraitData(trait_def_id={}, nested={})", + format!("VtableDefaultImplData(trait_def_id={}, nested={})", self.trait_def_id.repr(tcx), self.nested.repr(tcx)) } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 782f0b19814..7b70240f695 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -5175,7 +5175,7 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) &None => None } } - ast::ItemDefTrait(_, ref ast_trait_ref) => { + ast::ItemDefaultImpl(_, ref ast_trait_ref) => { Some(ty::node_id_to_trait_ref(cx, ast_trait_ref.ref_id)) } _ => None diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 8ed6af652ce..92b0ea905ac 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -507,9 +507,9 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData< } } -impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultTraitData { - fn fold_with>(&self, folder: &mut F) -> traits::VtableDefaultTraitData { - traits::VtableDefaultTraitData { +impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultImplData { + fn fold_with>(&self, folder: &mut F) -> traits::VtableDefaultImplData { + traits::VtableDefaultImplData { trait_def_id: self.trait_def_id, nested: self.nested.fold_with(folder), } @@ -528,7 +528,7 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> fn fold_with>(&self, folder: &mut F) -> traits::Vtable<'tcx, N> { match *self { traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)), - traits::VtableDefaultTrait(ref t) => traits::VtableDefaultTrait(t.fold_with(folder)), + traits::VtableDefaultImpl(ref t) => traits::VtableDefaultImpl(t.fold_with(folder)), traits::VtableClosure(d, ref s) => { traits::VtableClosure(d, s.fold_with(folder)) } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 0f13bd30d53..ddf77a9030c 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -209,7 +209,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { match item.node { // impls/extern blocks do not break the "public chain" because they // cannot have visibility qualifiers on them anyway - ast::ItemImpl(..) | ast::ItemDefTrait(..) | ast::ItemForeignMod(..) => {} + ast::ItemImpl(..) | ast::ItemDefaultImpl(..) | ast::ItemForeignMod(..) => {} // Traits are a little special in that even if they themselves are // not public they may still be exported. @@ -802,7 +802,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { def::DefVariant(..) => ck("variant"), def::DefTy(_, false) => ck("type"), def::DefTy(_, true) => ck("enum"), - def::DefTrait(..) => ck("trait"), + def::DefaultImpl(..) => ck("trait"), def::DefStruct(..) => ck("struct"), def::DefMethod(_, Some(..), _) => ck("trait method"), def::DefMethod(..) => ck("method"), @@ -1145,7 +1145,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { } } - ast::ItemDefTrait(..) | + ast::ItemDefaultImpl(..) | ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemStruct(..) | ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) | ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemMac(..) => {} @@ -1205,7 +1205,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { } } - ast::ItemDefTrait(..) | ast::ItemExternCrate(_) | ast::ItemUse(_) | + ast::ItemDefaultImpl(..) | ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemStatic(..) | ast::ItemConst(..) | ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) | ast::ItemMac(..) => {} diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index acea3f5851e..8696db212f9 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -40,7 +40,7 @@ use syntax::ast::{Block, Crate}; use syntax::ast::{DeclItem, DefId}; use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic}; use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn}; -use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefTrait}; +use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse}; use syntax::ast::{MethodImplItem, Name, NamedField, NodeId}; use syntax::ast::{PathListIdent, PathListMod}; @@ -656,7 +656,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { parent.clone() } - ItemDefTrait(_, _) | + ItemDefaultImpl(_, _) | ItemImpl(_, _, _, Some(_), _, _) => parent.clone(), ItemTrait(_, _, _, ref items) => { @@ -736,7 +736,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { self.trait_item_map.insert((name, def_id), kind); } - name_bindings.define_type(DefTrait(def_id), sp, modifiers); + name_bindings.define_type(DefaultImpl(def_id), sp, modifiers); parent.clone() } ItemMac(..) => parent.clone() @@ -918,7 +918,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } child_name_bindings.define_value(def, DUMMY_SP, modifiers); } - DefTrait(def_id) => { + DefaultImpl(def_id) => { debug!("(building reduced graph for external \ crate) building type {}", final_ident); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 82a3cdaa8cc..ea99ad6a18a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -70,7 +70,7 @@ use syntax::ast::{ExprClosure, ExprLoop, ExprWhile, ExprMethodCall}; use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl}; use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics}; use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate}; -use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefTrait}; +use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse}; use syntax::ast::{Local, MethodImplItem, Mod, Name, NodeId}; use syntax::ast::{Pat, PatEnum, PatIdent, PatLit}; @@ -2840,7 +2840,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } - ItemDefTrait(_, ref trait_ref) => { + ItemDefaultImpl(_, ref trait_ref) => { self.resolve_trait_reference(item.id, trait_ref, TraitImplementation); } ItemImpl(_, _, @@ -3199,7 +3199,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } Some(def) => { match def { - (DefTrait(_), _) => { + (DefaultImpl(_), _) => { debug!("(resolving trait) found trait def: {:?}", def); self.record_def(trait_reference.ref_id, def); } @@ -4675,7 +4675,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => continue }; let trait_def_id = match def { - DefTrait(trait_def_id) => trait_def_id, + DefaultImpl(trait_def_id) => trait_def_id, _ => continue, }; if self.trait_item_map.contains_key(&(name, trait_def_id)) { @@ -4691,7 +4691,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(target) => target, }; let did = match target.bindings.def_for_namespace(TypeNS) { - Some(DefTrait(trait_def_id)) => trait_def_id, + Some(DefaultImpl(trait_def_id)) => trait_def_id, Some(..) | None => continue, }; if self.trait_item_map.contains_key(&(name, did)) { diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 8d2a2d51ee4..439c83e0b37 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -239,7 +239,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefTy(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..) | - def::DefTrait(_) => Some(recorder::TypeRef), + def::DefaultImpl(_) => Some(recorder::TypeRef), def::DefStatic(_, _) | def::DefConst(_) | def::DefLocal(_) | diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 3d3e35cd776..052c9b4da6b 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -207,7 +207,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) def::DefUpvar(..) => { datum_callee(bcx, ref_expr) } - def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) | + def::DefMod(..) | def::DefForeignMod(..) | def::DefaultImpl(..) | def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) | def::DefUse(..) | def::DefTyParamBinder(..) | def::DefRegion(..) | def::DefLabel(..) | def::DefTyParam(..) | diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 1f90e4ae023..16e050ce01c 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -390,7 +390,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Callee { bcx: bcx, data: Fn(llfn) } } traits::VtableBuiltin(..) | - traits::VtableDefaultTrait(..) | + traits::VtableDefaultImpl(..) | traits::VtableParam(..) => { bcx.sess().bug( &format!("resolved vtable bad vtable {} in trans", @@ -716,7 +716,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let vtable = fulfill_obligation(ccx, DUMMY_SP, trait_ref.clone()); match vtable { // Should default trait error here? - traits::VtableDefaultTrait(_) | + traits::VtableDefaultImpl(_) | traits::VtableBuiltin(_) => { Vec::new().into_iter() } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e3c1c66f78c..96c770218d9 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -617,7 +617,7 @@ pub fn instantiate_trait_ref<'tcx>( -> Rc> { match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) { - def::DefTrait(trait_def_id) => { + def::DefaultImpl(trait_def_id) => { let trait_ref = ast_path_to_trait_ref(this, rscope, trait_def_id, @@ -931,7 +931,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, match ty.node { ast::TyPath(ref path, id) => { match this.tcx().def_map.borrow().get(&id) { - Some(&def::DefTrait(trait_def_id)) => { + Some(&def::DefaultImpl(trait_def_id)) => { let mut projection_bounds = Vec::new(); let trait_ref = object_path_to_poly_trait_ref(this, rscope, @@ -1211,7 +1211,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, Some(&d) => d }; match a_def { - def::DefTrait(trait_def_id) => { + def::DefaultImpl(trait_def_id) => { // N.B. this case overlaps somewhat with // TyObjectSum, see that fn for details let mut projection_bounds = Vec::new(); @@ -1821,7 +1821,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt, match *ast_bound { ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => { match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) { - def::DefTrait(trait_did) => { + def::DefaultImpl(trait_did) => { match trait_def_ids.get(&trait_did) { // Already seen this trait. We forbid // duplicates in the list (for some diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 34c52981b79..26ba0fe8ed1 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -435,7 +435,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat, let def = tcx.def_map.borrow()[pat.id].clone(); let (enum_def_id, variant_def_id) = match def { - def::DefTrait(_) => { + def::DefaultImpl(_) => { let name = pprust::path_to_string(path); span_err!(tcx.sess, pat.span, E0168, "use of trait `{}` in a struct pattern", name); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 1639772103b..20c2fd09840 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -330,7 +330,7 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> { cstore: &cstore::CStore, dl: decoder::DefLike) { match dl { - decoder::DlDef(def::DefTrait(did)) => { + decoder::DlDef(def::DefaultImpl(did)) => { traits.push(TraitInfo::new(did)); } decoder::DlDef(def::DefMod(did)) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e443b4d0e60..aa3af257fd6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3858,7 +3858,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, variant_id, &fields[..]); enum_id } - Some(def::DefTrait(def_id)) => { + Some(def::DefaultImpl(def_id)) => { span_err!(tcx.sess, path.span, E0159, "use of trait `{}` as a struct constructor", pprust::path_to_string(path)); @@ -4630,7 +4630,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefStruct(id) | def::DefConst(id) => { (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id)) } - def::DefTrait(_) | + def::DefaultImpl(_) | def::DefTy(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..) | @@ -4734,7 +4734,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefTy(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..) | - def::DefTrait(..) | + def::DefaultImpl(..) | def::DefPrimTy(..) | def::DefTyParam(..) => { // Everything but the final segment should have no diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 9a730093c7d..08aa54b6f5f 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -96,7 +96,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { } } } - ast::ItemDefTrait(_, ref ast_trait_ref) => { + ast::ItemDefaultImpl(_, ref ast_trait_ref) => { // "Trait" impl debug!("coherence2::orphan check: default trait impl {}", item.repr(self.tcx)); let trait_ref = ty::node_id_to_trait_ref(self.tcx, ast_trait_ref.ref_id); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a20fa54f822..6988ad59aa4 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -648,7 +648,7 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { predicates, &enum_definition.variants); }, - ast::ItemDefTrait(_, ref ast_trait_ref) => { + ast::ItemDefaultImpl(_, ref ast_trait_ref) => { let trait_ref = astconv::instantiate_trait_ref(ccx, &ExplicitRscope, ast_trait_ref, None, None); @@ -1147,7 +1147,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs)); ty::TypeScheme { ty: t, generics: ty_generics } } - ast::ItemDefTrait(..) | + ast::ItemDefaultImpl(..) | ast::ItemTrait(..) | ast::ItemImpl(..) | ast::ItemMod(..) | diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index 7ba589019c5..ed5a879edb3 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -476,7 +476,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> { ast::ItemExternCrate(_) | ast::ItemUse(_) | - ast::ItemDefTrait(..) | + ast::ItemDefaultImpl(..) | ast::ItemImpl(..) | ast::ItemStatic(..) | ast::ItemConst(..) | @@ -627,7 +627,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { ast::ItemForeignMod(..) | ast::ItemTy(..) | ast::ItemImpl(..) | - ast::ItemDefTrait(..) | + ast::ItemDefaultImpl(..) | ast::ItemMac(..) => { } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d1283d6f46b..4cd6f6551d0 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -69,7 +69,7 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt, let mut ret = Vec::new(); let did = def.def_id(); let inner = match def { - def::DefTrait(did) => { + def::DefaultImpl(did) => { record_extern_fqn(cx, did, clean::TypeTrait); clean::TraitItem(build_external_trait(cx, tcx, did)) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7ef48378af1..929a5f19ad9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2431,7 +2431,7 @@ fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId { def::DefFn(i, _) => (i, TypeFunction), def::DefTy(i, false) => (i, TypeTypedef), def::DefTy(i, true) => (i, TypeEnum), - def::DefTrait(i) => (i, TypeTrait), + def::DefaultImpl(i) => (i, TypeTrait), def::DefStruct(i) => (i, TypeStruct), def::DefMod(i) => (i, TypeModule), def::DefStatic(i, _) => (i, TypeStatic), diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 555e66e3a1e..8143926982f 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -39,7 +39,7 @@ pub struct Module { pub vis: ast::Visibility, pub stab: Option, pub impls: Vec, - pub def_traits: Vec, + pub def_traits: Vec, pub foreigns: Vec, pub macros: Vec, pub is_crate: bool, @@ -198,7 +198,7 @@ pub struct Impl { pub id: ast::NodeId, } -pub struct DefaultTrait { +pub struct DefaultImpl { pub unsafety: ast::Unsafety, pub trait_: ast::TraitRef, pub id: ast::NodeId, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index e77510785e9..c64aff31e30 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -358,8 +358,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; om.impls.push(i); }, - ast::ItemDefTrait(unsafety, ref trait_ref) => { - let i = DefaultTrait { + ast::ItemDefaultImpl(unsafety, ref trait_ref) => { + let i = DefaultImpl { unsafety: unsafety, trait_: trait_ref.clone(), id: item.id diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d57b23b8b1b..effaac52716 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1644,7 +1644,7 @@ pub enum Item_ { // Default trait implementations // `impl Trait for ..` - ItemDefTrait(Unsafety, TraitRef), + ItemDefaultImpl(Unsafety, TraitRef), ItemImpl(Unsafety, ImplPolarity, Generics, @@ -1671,7 +1671,7 @@ impl Item_ { ItemTrait(..) => "trait", ItemMac(..) | ItemImpl(..) | - ItemDefTrait(..) => "item" + ItemDefaultImpl(..) => "item" } } } diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index 7903a3a1bfc..c33158193ce 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -1044,7 +1044,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { ItemStruct(..) => "struct", ItemTrait(..) => "trait", ItemImpl(..) => "impl", - ItemDefTrait(..) => "default impl", + ItemDefaultImpl(..) => "default impl", ItemMac(..) => "macro" }; format!("{} {}{}", item_str, path_str, id_str) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 31e5a876374..dae830583c4 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -999,8 +999,8 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ { let struct_def = folder.fold_struct_def(struct_def); ItemStruct(struct_def, folder.fold_generics(generics)) } - ItemDefTrait(unsafety, ref trait_ref) => { - ItemDefTrait(unsafety, folder.fold_trait_ref((*trait_ref).clone())) + ItemDefaultImpl(unsafety, ref trait_ref) => { + ItemDefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone())) } ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => { let new_impl_items = impl_items.into_iter().flat_map(|item| { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 55c4afc36a5..0a5afcb3301 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -31,7 +31,7 @@ use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst}; -use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, ItemDefTrait}; +use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, ItemDefaultImpl}; use ast::{ItemExternCrate, ItemUse}; use ast::{LifetimeDef, Lit, Lit_}; use ast::{LitBool, LitChar, LitByte, LitBinary}; @@ -4843,7 +4843,7 @@ impl<'a> Parser<'a> { self.expect(&token::OpenDelim(token::Brace)); self.expect(&token::CloseDelim(token::Brace)); (ast_util::impl_pretty_name(&opt_trait, None), - ItemDefTrait(unsafety, opt_trait.unwrap()), None) + ItemDefaultImpl(unsafety, opt_trait.unwrap()), None) } else { if opt_trait.is_some() { ty = self.parse_ty_sum(); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index d5b17b5798b..1a3e1816e9f 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -926,7 +926,7 @@ impl<'a> State<'a> { try!(self.print_struct(&**struct_def, generics, item.ident, item.span)); } - ast::ItemDefTrait(unsafety, ref trait_ref) => { + ast::ItemDefaultImpl(unsafety, ref trait_ref) => { try!(self.head("")); try!(self.print_visibility(item.vis)); try!(self.print_unsafety(unsafety)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 9654e7a005b..412bf0fa22a 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -282,7 +282,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_generics(type_parameters); walk_enum_def(visitor, enum_definition, type_parameters) } - ItemDefTrait(_, ref trait_ref) => { + ItemDefaultImpl(_, ref trait_ref) => { visitor.visit_trait_ref(trait_ref) } ItemImpl(_, _, From f0e9bd9099e729eb73b4483795d0057e963c8eac Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Sat, 7 Feb 2015 14:46:08 +0100 Subject: [PATCH 13/32] address nits --- src/librustc/middle/traits/mod.rs | 3 +++ src/librustc/middle/traits/util.rs | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index c400dd5a78a..8b836fd322e 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -222,6 +222,9 @@ pub enum Vtable<'tcx, N> { VtableImpl(VtableImplData<'tcx, N>), /// Vtable for default trait implementations + /// This carries the information and nested obligations with regards + /// to a default implementation for a trait `Trait`. The nested obligations + /// ensure the trait implementation holds for all the constituent types. VtableDefaultImpl(VtableDefaultImplData), /// Successful resolution to an obligation provided by the caller diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 0308604aa8b..9b462e6be60 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -323,8 +323,8 @@ pub fn trait_ref_for_builtin_bound<'tcx>( } } + pub fn predicate_for_trait_ref<'tcx>( - tcx: &ty::ctxt<'tcx>, cause: ObligationCause<'tcx>, trait_ref: Rc>, recursion_depth: uint) @@ -349,7 +349,7 @@ pub fn predicate_for_default_trait_impl<'tcx>( def_id: trait_def_id, substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty)) }); - predicate_for_trait_ref(tcx, cause, trait_ref, recursion_depth) + predicate_for_trait_ref(cause, trait_ref, recursion_depth) } pub fn predicate_for_builtin_bound<'tcx>( @@ -361,7 +361,7 @@ pub fn predicate_for_builtin_bound<'tcx>( -> Result, ErrorReported> { let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty)); - predicate_for_trait_ref(tcx, cause, trait_ref, recursion_depth) + predicate_for_trait_ref(cause, trait_ref, recursion_depth) } /// Cast a trait reference into a reference to one of its super From 1e3ed61d8273377544e40bdbbdf8391b51571293 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Fri, 13 Feb 2015 18:30:33 +0100 Subject: [PATCH 14/32] Coherence for default trait implementations - Don't allow multiple default trait implementations - Allow positive trait implementations just for structs and enums when there's a default implementation for such trait. --- src/librustc/middle/traits/select.rs | 13 +--- src/librustc/middle/ty.rs | 29 ++++++--- src/librustc_typeck/coherence/overlap.rs | 79 +++++++++++++++++++++--- src/librustc_typeck/collect.rs | 3 +- src/librustc_typeck/diagnostics.rs | 3 +- 5 files changed, 95 insertions(+), 32 deletions(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 7f1119fc344..666c7c91070 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1626,6 +1626,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Vec::new() } + ty::ty_trait(..) | ty::ty_projection(..) | ty::ty_param(..) | ty::ty_infer(..) => { @@ -1639,18 +1640,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { vec![referent_ty] } - - ty::ty_trait(ref data) => { - // Recursively check all supertraits to find out if any further - // bounds are required and thus we must fulfill. - let principal = - data.principal_trait_ref_with_self_ty(self.tcx(), - self.tcx().types.err); - - - util::supertraits(self.tcx(), principal).map(|tr| tr.self_ty()).collect() - } - ty::ty_open(element_ty) => {vec![element_ty]}, ty::ty_ptr(ty::mt { ty: element_ty, ..}) | diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7b70240f695..71d484866a9 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -758,7 +758,7 @@ pub struct ctxt<'tcx> { pub trait_impls: RefCell>>>>, /// Maps a trait onto a list of *default* trait implementations - default_trait_impls: RefCell, + default_trait_impls: RefCell>, /// Maps a DefId of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. @@ -2496,7 +2496,7 @@ pub fn mk_ctxt<'tcx>(s: Session, destructor_for_type: RefCell::new(DefIdMap()), destructors: RefCell::new(DefIdSet()), trait_impls: RefCell::new(DefIdMap()), - default_trait_impls: RefCell::new(DefIdSet()), + default_trait_impls: RefCell::new(DefIdMap()), inherent_impls: RefCell::new(DefIdMap()), impl_items: RefCell::new(DefIdMap()), used_unsafe: RefCell::new(NodeSet()), @@ -5999,18 +5999,26 @@ pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc { || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id))) } +pub fn trait_default_impl(tcx: &ctxt, trait_def_id: DefId) -> Option { + match tcx.default_trait_impls.borrow().get(&trait_def_id) { + Some(id) => Some(*id), + None => None + } +} + pub fn trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) -> bool { - tcx.default_trait_impls.borrow().contains(&trait_def_id) + tcx.default_trait_impls.borrow().contains_key(&trait_def_id) } /// Records a trait-to-implementation mapping. -pub fn record_default_trait_implementation(tcx: &ctxt, trait_def_id: DefId) { +pub fn record_default_trait_implementation(tcx: &ctxt, + trait_def_id: DefId, + impl_def_id: DefId) { - if tcx.default_trait_impls.borrow().contains(&trait_def_id) { - return; - } - - tcx.default_trait_impls.borrow_mut().insert(trait_def_id); + // We're using the latest implementation found as the reference one. + // Duplicated implementations are caught and reported in the coherence + // step. + tcx.default_trait_impls.borrow_mut().insert(trait_def_id, impl_def_id); } @@ -6100,7 +6108,8 @@ pub fn populate_implementations_for_trait_if_necessary( let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id); if csearch::is_default_trait(&tcx.sess.cstore, implementation_def_id) { - record_default_trait_implementation(tcx, trait_id); + record_default_trait_implementation(tcx, trait_id, + implementation_def_id); tcx.populated_external_traits.borrow_mut().insert(trait_id); // Nothing else to do for default trait implementations since diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 403dcf1e25a..4a2660fcf46 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -17,16 +17,19 @@ use middle::infer::{self, new_infer_ctxt}; use syntax::ast::{DefId}; use syntax::ast::{LOCAL_CRATE}; use syntax::ast; -use syntax::codemap::{Span}; +use syntax::ast_util; +use syntax::visit; +use syntax::codemap::Span; use util::ppaux::Repr; pub fn check(tcx: &ty::ctxt) { - let overlap = OverlapChecker { tcx: tcx }; + let mut overlap = OverlapChecker { tcx: tcx }; overlap.check_for_overlapping_impls(); + visit::walk_crate(&mut overlap, tcx.map.krate()); } struct OverlapChecker<'cx, 'tcx:'cx> { - tcx: &'cx ty::ctxt<'tcx> + tcx: &'cx ty::ctxt<'tcx>, } impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { @@ -90,17 +93,28 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { return; } - span_err!(self.tcx.sess, self.span_of_impl(impl1_def_id), E0119, + self.report_overlap_error(trait_def_id, impl1_def_id, impl2_def_id); + } + + fn report_overlap_error(&self, trait_def_id: ast::DefId, + impl1: ast::DefId, impl2: ast::DefId) { + + span_err!(self.tcx.sess, self.span_of_impl(impl1), E0119, "conflicting implementations for trait `{}`", ty::item_path_str(self.tcx, trait_def_id)); - if impl2_def_id.krate == ast::LOCAL_CRATE { - span_note!(self.tcx.sess, self.span_of_impl(impl2_def_id), + self.report_overlap_note(impl1, impl2); + } + + fn report_overlap_note(&self, impl1: ast::DefId, impl2: ast::DefId) { + + if impl2.krate == ast::LOCAL_CRATE { + span_note!(self.tcx.sess, self.span_of_impl(impl2), "note conflicting implementation here"); } else { let crate_store = &self.tcx.sess.cstore; - let cdata = crate_store.get_crate_data(impl2_def_id.krate); - span_note!(self.tcx.sess, self.span_of_impl(impl1_def_id), + let cdata = crate_store.get_crate_data(impl2.krate); + span_note!(self.tcx.sess, self.span_of_impl(impl1), "conflicting implementation in crate `{}`", cdata.name); } @@ -111,3 +125,52 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { self.tcx.map.span(impl_did.node) } } + + +impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { + fn visit_item(&mut self, item: &'v ast::Item) { + match item.node { + ast::ItemImpl(_, ast::ImplPolarity::Positive, _, Some(ref ast_trait_ref), _, _) => { + let trait_ref = ty::node_id_to_trait_ref(self.tcx, ast_trait_ref.ref_id); + match ty::trait_default_impl(self.tcx, trait_ref.def_id) { + Some(default_impl) => { + match trait_ref.self_ty().sty { + ty::ty_struct(..) | ty::ty_enum(..) => {}, + _ => { + let impl_def_id = ast_util::local_def(item.id); + span_err!(self.tcx.sess, self.span_of_impl(impl_def_id), E0317, + "implementations for traits providing default \ + implementations are only allowed on structs and enums"); + + self.report_overlap_note(impl_def_id, default_impl); + } + } + } + None => {} + } + } + ast::ItemDefaultImpl(_, _) => { + let impl_def_id = ast_util::local_def(item.id); + match ty::impl_trait_ref(self.tcx, impl_def_id) { + Some(ref trait_ref) => { + match ty::trait_default_impl(self.tcx, trait_ref.def_id) { + Some(other_impl) if other_impl != impl_def_id => { + self.report_overlap_error(trait_ref.def_id, + other_impl, + impl_def_id); + } + Some(_) => {} + None => { + self.tcx.sess.bug( + &format!("no default implementation recorded for `{:?}`", + item)[]); + } + } + } + _ => {} + } + } + _ => {} + } + } +} diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 6988ad59aa4..10fb71f1b48 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -652,7 +652,7 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { let trait_ref = astconv::instantiate_trait_ref(ccx, &ExplicitRscope, ast_trait_ref, None, None); - ty::record_default_trait_implementation(tcx, trait_ref.def_id) + ty::record_default_trait_implementation(tcx, trait_ref.def_id, local_def(it.id)) } ast::ItemImpl(_, _, ref generics, @@ -1190,6 +1190,7 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, ast::ItemStruct(_, ref generics) => { ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics) } + ast::ItemDefaultImpl(..) | ast::ItemTrait(..) | ast::ItemExternCrate(..) | ast::ItemUse(..) | diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index f610f71cd42..39ae233957a 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -172,7 +172,8 @@ register_diagnostics! { E0248, // found value name used as a type E0249, // expected constant expr for array length E0250, // expected constant expr for array length - E0316 // can't create default impls for traits outside their crates + E0316, // can't create default impls for traits outside their crates + E0317 } __build_diagnostic_array! { DIAGNOSTICS } From d215411911c2f6e5a68a12686c930352f68d2031 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Wed, 18 Feb 2015 01:49:16 +0100 Subject: [PATCH 15/32] Make Send/Sync go through the default implementation path --- src/librustc/middle/traits/select.rs | 38 ++++++++++++++++------------ src/librustc/middle/ty.rs | 5 +++- src/librustc_resolve/lib.rs | 2 +- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 666c7c91070..6462f3830a1 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -824,24 +824,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { stack, &mut candidates)); } - Some(bound @ ty::BoundSend) | - Some(bound @ ty::BoundSync) => { - // Ideally, we shouldn't sepcial case Send/Sync. This will be unified - // as soon as default trait implementations for these traits land. - try!(self.assemble_candidates_from_impls(obligation, &mut candidates)); - - // No explicit impls were declared for this type, consider the fallback rules. - if candidates.vec.is_empty() && !candidates.ambiguous { - try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates)); - } - } - Some(bound @ ty::BoundSized) => { // Sized and Copy are always automatically computed. try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates)); } - None => { + _ => { // For the time being, we ignore user-defined impls for builtin-bounds, other than // `Copy`. // (And unboxed candidates only apply to the Fn/FnMut/etc traits.) @@ -1149,8 +1137,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); } - if ty::trait_has_default_impl(self.tcx(), def_id) { - candidates.vec.push(DefaultImplCandidate(def_id.clone())) + match self_ty.sty { + ty::ty_infer(ty::TyVar(_)) | + ty::ty_trait(..) => {}, + _ => { + if ty::trait_has_default_impl(self.tcx(), def_id) { + candidates.vec.push(DefaultImplCandidate(def_id.clone())) + } + } } Ok(()) @@ -1179,6 +1173,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let poly_trait_ref = match self_ty.sty { ty::ty_trait(ref data) => { + match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { + Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => { + if data.bounds.builtin_bounds.contains(&bound) { + debug!("assemble_candidates_from_object_ty: matched builtin bound, \ + pushing candidate"); + candidates.vec.push(BuiltinCandidate(bound)); + return; + } + } + _ => {} + } + data.principal_trait_ref_with_self_ty(self.tcx(), self_ty) } ty::ty_infer(ty::TyVar(_)) => { @@ -1622,13 +1628,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_bare_fn(..) | ty::ty_str | ty::ty_err | + ty::ty_param(..) | ty::ty_char => { Vec::new() } ty::ty_trait(..) | ty::ty_projection(..) | - ty::ty_param(..) | ty::ty_infer(..) => { self.tcx().sess.bug( &format!( diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 71d484866a9..3f8e283b209 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6007,7 +6007,10 @@ pub fn trait_default_impl(tcx: &ctxt, trait_def_id: DefId) -> Option } pub fn trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) -> bool { - tcx.default_trait_impls.borrow().contains_key(&trait_def_id) + match tcx.lang_items.to_builtin_kind(trait_def_id) { + Some(BoundSend) | Some(BoundSync) => true, + _ => tcx.default_trait_impls.borrow().contains_key(&trait_def_id) + } } /// Records a trait-to-implementation mapping. diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ea99ad6a18a..bd1c8e1ba12 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2989,7 +2989,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // check for imports shadowing primitive types if let ast::ViewPathSimple(ident, _) = view_path.node { match self.def_map.borrow().get(&item.id) { - Some(&DefTy(..)) | Some(&DefStruct(..)) | Some(&DefTrait(..)) | None => { + Some(&DefTy(..)) | Some(&DefStruct(..)) | Some(&DefaultImpl(..)) | None => { self.check_if_primitive_type_name(ident.name, item.span); } _ => {} From 40fffc9e3fe1664240683a2e86f2d14827417ef5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 18 Feb 2015 11:58:44 -0500 Subject: [PATCH 16/32] Some nits and cleanup --- src/librustc/middle/traits/select.rs | 93 +++++++++++++----------- src/librustc_typeck/coherence/overlap.rs | 3 + 2 files changed, 55 insertions(+), 41 deletions(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 6462f3830a1..c5ef55154de 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -152,6 +152,8 @@ enum SelectionCandidate<'tcx> { ObjectCandidate, + BuiltinObjectCandidate, + ErrorCandidate, } @@ -818,21 +820,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("obligation self ty is {}", obligation.predicate.0.self_ty().repr(self.tcx())); + // User-defined copy impls are permitted, but only for + // structs and enums. try!(self.assemble_candidates_from_impls(obligation, &mut candidates)); + // For other types, we'll use the builtin rules. try!(self.assemble_builtin_bound_candidates(ty::BoundCopy, stack, &mut candidates)); } Some(bound @ ty::BoundSized) => { - // Sized and Copy are always automatically computed. + // Sized is never implementable by end-users, it is + // always automatically computed. try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates)); } - _ => { - // For the time being, we ignore user-defined impls for builtin-bounds, other than - // `Copy`. - // (And unboxed candidates only apply to the Fn/FnMut/etc traits.) + Some(ty::BoundSend) | + Some(ty::BoundSync) | + None => { try!(self.assemble_closure_candidates(obligation, &mut candidates)); try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates)); try!(self.assemble_candidates_from_impls(obligation, &mut candidates)); @@ -1178,7 +1183,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if data.bounds.builtin_bounds.contains(&bound) { debug!("assemble_candidates_from_object_ty: matched builtin bound, \ pushing candidate"); - candidates.vec.push(BuiltinCandidate(bound)); + candidates.vec.push(BuiltinObjectCandidate); return; } } @@ -1272,6 +1277,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (&ImplCandidate(..), &ParamCandidate(..)) | (&ClosureCandidate(..), &ParamCandidate(..)) | (&FnPointerCandidate(..), &ParamCandidate(..)) | + (&BuiltinObjectCandidate(..), &ParamCandidate(_)) | (&BuiltinCandidate(..), &ParamCandidate(..)) => { // We basically prefer always prefer to use a // where-clause over another option. Where clauses @@ -1359,7 +1365,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(If(Vec::new())) } - ty::ty_uniq(referent_ty) => { // Box + ty::ty_uniq(_) => { // Box match bound { ty::BoundCopy => { Err(Unimplemented) @@ -1369,26 +1375,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(If(Vec::new())) } - ty::BoundSync | - ty::BoundSend => { - Ok(If(vec![referent_ty])) + ty::BoundSync | ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); } } } ty::ty_ptr(..) => { // *const T, *mut T match bound { - ty::BoundCopy | - ty::BoundSized => { + ty::BoundCopy | ty::BoundSized => { Ok(If(Vec::new())) } - ty::BoundSync | - ty::BoundSend => { - self.tcx().sess.bug( - &format!( - "raw pointers should have a negative \ - impl for `Send` and `Sync`")[]); + ty::BoundSync | ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); } } } @@ -1398,7 +1398,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::BoundSized => { Err(Unimplemented) } - ty::BoundCopy | ty::BoundSync | ty::BoundSend => { + ty::BoundCopy => { if data.bounds.builtin_bounds.contains(&bound) { Ok(If(Vec::new())) } else { @@ -1417,6 +1417,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Err(Unimplemented) } } + ty::BoundSync | ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); + } } } @@ -1441,9 +1444,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(If(Vec::new())) } - ty::BoundSync | - ty::BoundSend => { - Ok(If(vec![referent_ty])) + ty::BoundSync | ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); } } } @@ -1472,9 +1474,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::BoundSync | - ty::BoundSend => { - Ok(If(vec![element_ty])) + ty::BoundSync | ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); } } } @@ -1482,13 +1483,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_str => { // Equivalent to [u8] match bound { - ty::BoundSync | - ty::BoundSend => { - Ok(If(Vec::new())) + ty::BoundSync | ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); } - ty::BoundCopy | - ty::BoundSized => { + ty::BoundCopy | ty::BoundSized => { Err(Unimplemented) } } @@ -1576,15 +1575,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // "opened" unsized/existential type (one that has // been dereferenced) match bound { - ty::BoundCopy | - ty::BoundSync | - ty::BoundSend => { + ty::BoundCopy => { Ok(If(vec!(ty))) } ty::BoundSized => { Err(Unimplemented) } + + ty::BoundSync | + ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); + } } } ty::ty_err => { @@ -1606,16 +1608,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { { // First check for markers and other nonsense. match bound { - ty::BoundCopy => { - return Ok(ParameterBuiltin) - } + // Fallback to whatever user-defined impls exist in this case. + ty::BoundCopy => Ok(ParameterBuiltin), - ty::BoundSend | - ty::BoundSync | - ty::BoundSized => { } + // Sized if all the component types are sized. + ty::BoundSized => Ok(If(types)), + + // Shouldn't be coming through here. + ty::BoundSend | ty::BoundSync => unreachable!(), } - - Ok(If(types)) } } @@ -1739,6 +1740,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(VtableClosure(closure_def_id, substs)) } + BuiltinObjectCandidate => { + // This indicates something like `(Trait+Send) : + // Send`. In this case, we know that this holds + // because that's what the object type is telling us, + // and there's really no additional obligations to + // prove and no types in particular to unify etc. + Ok(VtableParam(Vec::new())) + } + ObjectCandidate => { let data = self.confirm_object_candidate(obligation); Ok(VtableObject(data)) @@ -2449,6 +2459,7 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> { PhantomFnCandidate => format!("PhantomFnCandidate"), ErrorCandidate => format!("ErrorCandidate"), BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b), + BuiltinObjectCandidate => format!("BuiltinObjectCandidate"), ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)), ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)), DefaultImplCandidate(t) => format!("DefaultImplCandidate({:?})", t), diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 4a2660fcf46..26624c051c9 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -25,6 +25,9 @@ use util::ppaux::Repr; pub fn check(tcx: &ty::ctxt) { let mut overlap = OverlapChecker { tcx: tcx }; overlap.check_for_overlapping_impls(); + + // this secondary walk specifically checks for impls of defaulted + // traits, for which additional overlap rules exist visit::walk_crate(&mut overlap, tcx.map.krate()); } From 0be1e430cf8762095178cb8c94a17f1bab32a191 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Wed, 18 Feb 2015 10:53:52 +0100 Subject: [PATCH 17/32] Fix error codes --- src/librustc_typeck/coherence/orphan.rs | 2 +- src/librustc_typeck/coherence/overlap.rs | 2 +- src/librustc_typeck/diagnostics.rs | 4 +-- .../typeck-default-trait-impl-supertrait.rs | 29 +++++++++++++++++++ 4 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 src/test/compile-fail/typeck-default-trait-impl-supertrait.rs diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 08aa54b6f5f..d34a16a924f 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -101,7 +101,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { debug!("coherence2::orphan check: default trait impl {}", item.repr(self.tcx)); let trait_ref = ty::node_id_to_trait_ref(self.tcx, ast_trait_ref.ref_id); if trait_ref.def_id.krate != ast::LOCAL_CRATE { - span_err!(self.tcx.sess, item.span, E0316, + span_err!(self.tcx.sess, item.span, E0318, "cannot create default implementations for traits outside the \ crate they're defined in; define a new trait instead."); } diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 26624c051c9..9accfe7749e 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -141,7 +141,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { ty::ty_struct(..) | ty::ty_enum(..) => {}, _ => { let impl_def_id = ast_util::local_def(item.id); - span_err!(self.tcx.sess, self.span_of_impl(impl_def_id), E0317, + span_err!(self.tcx.sess, self.span_of_impl(impl_def_id), E0319, "implementations for traits providing default \ implementations are only allowed on structs and enums"); diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 39ae233957a..6f363faef60 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -172,8 +172,8 @@ register_diagnostics! { E0248, // found value name used as a type E0249, // expected constant expr for array length E0250, // expected constant expr for array length - E0316, // can't create default impls for traits outside their crates - E0317 + E0318, // can't create default impls for traits outside their crates + E0319 // trait impls for defaulted traits allowed just for structs/enums } __build_diagnostic_array! { DIAGNOSTICS } diff --git a/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs b/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs new file mode 100644 index 00000000000..cb3f50c8d87 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs @@ -0,0 +1,29 @@ +// Copyright 2015 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. + +// Test that when a `..` impl applies, we also check that any +// supertrait conditions are met. + +#![feature(optin_builtin_traits)] + +trait NotImplemented { } + +trait MyTrait : NotImplemented {} + +impl MyTrait for .. {} + +fn foo() { bar::() } + +fn bar() { } + +fn main() { + foo::(); //~ ERROR XXX + bar::(); //~ ERROR XXX +} From 7213ef1a8fd3cb7e479d53fdb287c6c612b9fb93 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Tue, 27 Jan 2015 01:07:31 +0100 Subject: [PATCH 18/32] Test all the things --- .../coherence-default-trait-impl.rs | 25 ++++++++++ .../syntaxt-default-trait-impls.rs | 18 +++++++ ...-default-trait-impl-constituent-types-2.rs | 30 +++++++++++ ...ck-default-trait-impl-constituent-types.rs | 36 +++++++++++++ ...typeck-default-trait-impl-negation-send.rs | 31 ++++++++++++ ...typeck-default-trait-impl-negation-sync.rs | 50 +++++++++++++++++++ .../typeck-default-trait-impl-negation.rs | 42 ++++++++++++++++ ...typeck-default-trait-impl-outside-crate.rs | 18 +++++++ src/test/pretty/default-trait-impl.rs | 19 +++++++ 9 files changed, 269 insertions(+) create mode 100644 src/test/compile-fail/coherence-default-trait-impl.rs create mode 100644 src/test/compile-fail/syntaxt-default-trait-impls.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-negation-send.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-negation.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs create mode 100644 src/test/pretty/default-trait-impl.rs diff --git a/src/test/compile-fail/coherence-default-trait-impl.rs b/src/test/compile-fail/coherence-default-trait-impl.rs new file mode 100644 index 00000000000..bcc3353ba02 --- /dev/null +++ b/src/test/compile-fail/coherence-default-trait-impl.rs @@ -0,0 +1,25 @@ +// Copyright 2015 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. + +// ignore-tidy-linelength + +#![feature(optin_builtin_traits)] + +trait MyTrait {} + +impl MyTrait for .. {} + +impl MyTrait for .. {} +//~^ ERROR conflicting implementations for trait `MyTrait` + +impl MyTrait for (i32, i32) {} +//~^ ERROR implementations for traits providing default implementations are only allowed on + +fn main() {} diff --git a/src/test/compile-fail/syntaxt-default-trait-impls.rs b/src/test/compile-fail/syntaxt-default-trait-impls.rs new file mode 100644 index 00000000000..a33cd0edca5 --- /dev/null +++ b/src/test/compile-fail/syntaxt-default-trait-impls.rs @@ -0,0 +1,18 @@ +// Copyright 2015 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. + +#![feature(optin_builtin_traits)] + +trait MyDefaultImpl {} + +impl MyDefaultImpl for .. {} +//~^ ERROR default trait implementations are not allowed to have genercis + +fn main() {} diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs new file mode 100644 index 00000000000..a27f7f7ebbe --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs @@ -0,0 +1,30 @@ +// Copyright 2015 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. + +#![feature(optin_builtin_traits)] + +trait MyTrait {} + +impl MyTrait for .. {} + +struct MyS; + +struct MyS2; + +impl !MyTrait for MyS2 {} + +fn is_mytrait() {} + +fn main() { + is_mytrait::(); + + is_mytrait::<(MyS2, MyS)>(); + //~^ ERROR the trait `MyTrait` is not implemented for the type `MyS2` +} diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs new file mode 100644 index 00000000000..556a0a1a0f3 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs @@ -0,0 +1,36 @@ +// Copyright 2015 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. + +#![feature(optin_builtin_traits)] + +trait MyTrait {} + +impl MyTrait for .. {} +impl !MyTrait for *mut T {} + +struct MyS; + +struct MyS2; + +impl !MyTrait for MyS2 {} + +struct MyS3; + +fn is_mytrait() {} + +fn main() { + is_mytrait::(); + + is_mytrait::(); + //~^ ERROR the trait `MyTrait` is not implemented for the type `MyS2` + + is_mytrait::>(); + //~^ ERROR the trait `MyTrait` is not implemented for the type `*mut MyS3` +} diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation-send.rs b/src/test/compile-fail/typeck-default-trait-impl-negation-send.rs new file mode 100644 index 00000000000..db4d1fe485b --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-negation-send.rs @@ -0,0 +1,31 @@ +// Copyright 2015 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. + +#![feature(optin_builtin_traits)] + +struct MySendable { + t: *mut u8 +} + +unsafe impl Send for MySendable {} + +struct MyNotSendable { + t: *mut u8 +} + +impl !Send for MyNotSendable {} + +fn is_send() {} + +fn main() { + is_send::(); + is_send::(); + //~^ ERROR the trait `core::marker::Send` is not implemented for the type `MyNotSendable` +} diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs b/src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs new file mode 100644 index 00000000000..d613589e7d7 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs @@ -0,0 +1,50 @@ +// Copyright 2015 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. + +// ignore-tidy-linelength + +#![feature(optin_builtin_traits)] + +use std::marker::Managed; +use std::cell::UnsafeCell; + +struct MySync { + t: *mut u8 +} + +unsafe impl Sync for MySync {} + +struct MyNotSync { + t: *mut u8 +} + +impl !Sync for MyNotSync {} + +struct MyTypeWUnsafe { + t: UnsafeCell +} + +struct MyTypeManaged { + t: Managed +} + +fn is_sync() {} + +fn main() { + is_sync::(); + is_sync::(); + //~^ ERROR the trait `core::marker::Sync` is not implemented for the type `MyNotSync` + + is_sync::(); + //~^ ERROR the trait `core::marker::Sync` is not implemented for the type `core::cell::UnsafeCell` + + is_sync::(); + //~^ ERROR the trait `core::marker::Sync` is not implemented for the type `core::marker::Managed` +} diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation.rs b/src/test/compile-fail/typeck-default-trait-impl-negation.rs new file mode 100644 index 00000000000..4b91d0b7a73 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-negation.rs @@ -0,0 +1,42 @@ +// Copyright 2015 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. + +#![feature(optin_builtin_traits)] + +trait MyTrait {} + +impl MyTrait for .. {} + +unsafe trait MyUnsafeTrait {} + +unsafe impl MyUnsafeTrait for .. {} + +struct ThisImplsTrait; + +impl !MyUnsafeTrait for ThisImplsTrait {} + + +struct ThisImplsUnsafeTrait; + +impl !MyTrait for ThisImplsUnsafeTrait {} + +fn is_my_trait() {} +fn is_my_unsafe_trait() {} + +fn main() { + is_my_trait::(); + is_my_trait::(); + //~^ ERROR the trait `MyTrait` is not implemented for the type `ThisImplsUnsafeTrait` + + is_my_unsafe_trait::(); + //~^ ERROR the trait `MyUnsafeTrait` is not implemented for the type `ThisImplsTrait` + + is_my_unsafe_trait::(); +} diff --git a/src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs b/src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs new file mode 100644 index 00000000000..10ba8c74164 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs @@ -0,0 +1,18 @@ +// Copyright 2015 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. + +// ignore-tidy-linelength + +#![feature(optin_builtin_traits)] + +impl Copy for .. {} +//~^ ERROR cannot create default implementations for traits outside the crate they're defined in; define a new trait instead. + +fn main() {} diff --git a/src/test/pretty/default-trait-impl.rs b/src/test/pretty/default-trait-impl.rs new file mode 100644 index 00000000000..a5246b9300c --- /dev/null +++ b/src/test/pretty/default-trait-impl.rs @@ -0,0 +1,19 @@ +// Copyright 2014 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. + +#![feature(optin_builtin_traits)] + +// pp-exact + +trait MyTrait { } + +impl MyTrait for .. { } + +pub fn main() { } From f7a75e0341b6192b20bc271c4a165b9a53d34ff4 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 19 Feb 2015 06:59:37 -0500 Subject: [PATCH 19/32] Add new test case showing that supertraits are not enough --- ...k-default-trait-impl-trait-where-clause.rs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs diff --git a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs new file mode 100644 index 00000000000..85bca7f248c --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs @@ -0,0 +1,38 @@ +// Copyright 2015 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. + +// Test that when a `..` impl applies, we also check that any +// supertrait conditions are met. + +#![feature(optin_builtin_traits)] + +trait NotImplemented { } + +trait MyTrait + where Option : NotImplemented +{} + +impl NotImplemented for i32 {} + +impl MyTrait for .. {} + +fn foo() { + bar::>() + //~^ ERROR not implemented for the type `Option` + // + // This should probably typecheck. This is #20671. +} + +fn bar() { } + +fn main() { + foo::(); //~ ERROR not implemented for the type `i32` + bar::>(); //~ ERROR not implemented for the type `Option` +} From 64d33d892ad3bda256e174e97e51f603896b6c66 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Wed, 18 Feb 2015 23:31:03 +0100 Subject: [PATCH 20/32] check supertraits --- src/librustc/middle/traits/select.rs | 25 ++++++++++++++++--- .../typeck-default-trait-impl-supertrait.rs | 4 +-- ...k-default-trait-impl-trait-where-clause.rs | 17 ++++++++----- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index c5ef55154de..ac782729bc3 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1423,7 +1423,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::ty_rptr(_, ty::mt { ty: referent_ty, mutbl }) => { + ty::ty_rptr(_, ty::mt { ty: _, mutbl }) => { // &mut T or &T match bound { ty::BoundCopy => { @@ -1871,8 +1871,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn confirm_default_impl_candidate(&mut self, - obligation: &TraitObligation<'tcx>, - impl_def_id: ast::DefId) + obligation: &TraitObligation<'tcx>, + impl_def_id: ast::DefId) -> Result>, SelectionError<'tcx>> { @@ -1892,6 +1892,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { -> VtableDefaultImplData> { let derived_cause = self.derived_cause(obligation, ImplDerivedObligation); + let obligations = nested.iter().map(|&nested_ty| { // the obligation might be higher-ranked, e.g. for<'a> &'a // int : Copy. In that case, we will wind up with @@ -1918,11 +1919,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } }) }).collect::>(); - let obligations = match obligations { + + let mut obligations = match obligations { Ok(o) => o, Err(ErrorReported) => Vec::new() }; + let _: Result<(),()> = self.infcx.try(|snapshot| { + let (_, skol_map) = + self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot); + + let substs = obligation.predicate.to_poly_trait_ref().substs(); + let trait_obligations = self.impl_obligations(obligation.cause.clone(), + obligation.recursion_depth + 1, + trait_def_id, + substs, + skol_map, + snapshot); + obligations.push_all(trait_obligations.as_slice()); + Ok(()) + }); + debug!("vtable_default_impl_data: obligations={}", obligations.repr(self.tcx())); VtableDefaultImplData { diff --git a/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs b/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs index cb3f50c8d87..c9bfdff6c0e 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs @@ -24,6 +24,6 @@ fn foo() { bar::() } fn bar() { } fn main() { - foo::(); //~ ERROR XXX - bar::(); //~ ERROR XXX + foo::(); //~ ERROR the trait `NotImplemented` is not implemented for the type `i32` + bar::(); //~ ERROR the trait `NotImplemented` is not implemented for the type `i64` } diff --git a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs index 85bca7f248c..06f36521157 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs @@ -25,14 +25,19 @@ impl MyTrait for .. {} fn foo() { bar::>() - //~^ ERROR not implemented for the type `Option` - // - // This should probably typecheck. This is #20671. + //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option` + // + // This should probably typecheck. This is #20671. } fn bar() { } -fn main() { - foo::(); //~ ERROR not implemented for the type `i32` - bar::>(); //~ ERROR not implemented for the type `Option` +fn test() { + bar::>(); + //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option` +} + +fn main() { + foo::(); + //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option` } From 24bdce4bbf55dd7f88492fd3a106bca2efdaa1a6 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 19 Feb 2015 10:30:45 -0500 Subject: [PATCH 21/32] some comments and nits --- src/librustc/middle/traits/select.rs | 78 ++++++++++--------- ...k-default-trait-impl-trait-where-clause.rs | 2 + 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index ac782729bc3..864d666d24f 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -17,9 +17,9 @@ use self::SelectionCandidate::*; use self::BuiltinBoundConditions::*; use self::EvaluationResult::*; -use super::{DerivedObligationCause}; -use super::{project}; -use super::project::Normalized; +use super::DerivedObligationCause; +use super::project; +use super::project::{normalize_with_depth, Normalized}; use super::{PredicateObligation, TraitObligation, ObligationCause}; use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation}; use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch}; @@ -1620,7 +1620,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn constituent_types(&self, t: Ty<'tcx>) -> Vec> { + fn constituent_ty_obligations(&self, t: Ty<'tcx>) -> Vec> { match t.sty { ty::ty_uint(_) | ty::ty_int(_) | @@ -1870,6 +1870,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { VtableBuiltinData { nested: obligations } } + /// This handles the case where a `impl Foo for ..` impl is being used. + /// The idea is that the impl applies to `X : Foo` if the following conditions are met: + /// + /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds + /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds. fn confirm_default_impl_candidate(&mut self, obligation: &TraitObligation<'tcx>, impl_def_id: ast::DefId) @@ -1881,10 +1886,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { impl_def_id.repr(self.tcx())); let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty()); - let types = self.constituent_types(self_ty); + let types = self.constituent_ty_obligations(self_ty); Ok(self.vtable_default_impl(obligation, impl_def_id, types)) } + /// See `confirm_default_impl_candidate` fn vtable_default_impl(&mut self, obligation: &TraitObligation<'tcx>, trait_def_id: ast::DefId, @@ -1930,12 +1936,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot); let substs = obligation.predicate.to_poly_trait_ref().substs(); - let trait_obligations = self.impl_obligations(obligation.cause.clone(), - obligation.recursion_depth + 1, - trait_def_id, - substs, - skol_map, - snapshot); + let trait_obligations = self.impl_or_trait_obligations(obligation.cause.clone(), + obligation.recursion_depth + 1, + trait_def_id, + substs, + skol_map, + snapshot); obligations.push_all(trait_obligations.as_slice()); Ok(()) }); @@ -1988,12 +1994,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { skol_map.repr(self.tcx())); let mut impl_obligations = - self.impl_obligations(cause, - recursion_depth, - impl_def_id, - &substs.value, - skol_map, - snapshot); + self.impl_or_trait_obligations(cause, + recursion_depth, + impl_def_id, + &substs.value, + skol_map, + snapshot); debug!("vtable_impl: impl_def_id={} impl_obligations={}", impl_def_id.repr(self.tcx()), @@ -2413,28 +2419,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Binder(trait_ref) } - fn impl_obligations(&mut self, - cause: ObligationCause<'tcx>, - recursion_depth: uint, - impl_def_id: ast::DefId, - impl_substs: &Substs<'tcx>, - skol_map: infer::SkolemizationMap, - snapshot: &infer::CombinedSnapshot) - -> VecPerParamSpace> + /// Returns the obligations that are implied by instantiating an + /// impl or trait. The obligations are substituted and fully + /// normalized. This is used when confirming an impl or default + /// impl. + fn impl_or_trait_obligations(&mut self, + cause: ObligationCause<'tcx>, + recursion_depth: uint, + def_id: ast::DefId, // of impl or trait + substs: &Substs<'tcx>, // for impl or trait + skol_map: infer::SkolemizationMap, + snapshot: &infer::CombinedSnapshot) + -> VecPerParamSpace> { - let impl_bounds = ty::lookup_predicates(self.tcx(), impl_def_id); - let bounds = impl_bounds.instantiate(self.tcx(), impl_substs); - let normalized_bounds = - project::normalize_with_depth(self, cause.clone(), recursion_depth, &bounds); - let normalized_bounds = - self.infcx().plug_leaks(skol_map, snapshot, &normalized_bounds); - let mut impl_obligations = + let predicates = ty::lookup_predicates(self.tcx(), def_id); + let predicates = predicates.instantiate(self.tcx(), substs); + let predicates = normalize_with_depth(self, cause.clone(), recursion_depth, &predicates); + let predicates = self.infcx().plug_leaks(skol_map, snapshot, &predicates); + let mut obligations = util::predicates_for_generics(self.tcx(), cause, recursion_depth, - &normalized_bounds.value); - impl_obligations.extend(TypeSpace, normalized_bounds.obligations.into_iter()); - impl_obligations + &predicates.value); + obligations.extend(TypeSpace, predicates.obligations.into_iter()); + obligations } #[allow(unused_comparisons)] diff --git a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs index 06f36521157..4f572e87639 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + // Test that when a `..` impl applies, we also check that any // supertrait conditions are met. From e8df95d77f65a3a1456f7e10d9d1dd209acf2879 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 19 Feb 2015 11:28:01 -0500 Subject: [PATCH 22/32] mark candidate set ambig for defaulted traits where self-type is not yet known --- src/librustc/middle/traits/select.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 864d666d24f..6fcf5ef6ad8 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1143,8 +1143,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } match self_ty.sty { - ty::ty_infer(ty::TyVar(_)) | ty::ty_trait(..) => {}, + ty::ty_infer(ty::TyVar(_)) => { + // the defaulted impl might apply, we don't know + if ty::trait_has_default_impl(self.tcx(), def_id) { + candidates.ambiguous = true; + } + } _ => { if ty::trait_has_default_impl(self.tcx(), def_id) { candidates.vec.push(DefaultImplCandidate(def_id.clone())) From 38ef5ee48f7a2994a7fd8e6a1a818d378d51d40e Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Thu, 19 Feb 2015 21:13:55 +0100 Subject: [PATCH 23/32] Check constituent types are known --- src/librustc/middle/traits/select.rs | 56 ++++++++++++++++++---------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 6fcf5ef6ad8..c86f0004de9 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1152,7 +1152,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } _ => { if ty::trait_has_default_impl(self.tcx(), def_id) { - candidates.vec.push(DefaultImplCandidate(def_id.clone())) + match self.constituent_types_for_ty(self_ty) { + Some(_) => { + candidates.vec.push(DefaultImplCandidate(def_id.clone())) + } + None => { + candidates.ambiguous = true; + } + } } } } @@ -1625,7 +1632,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn constituent_ty_obligations(&self, t: Ty<'tcx>) -> Vec> { + fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Option>> { match t.sty { ty::ty_uint(_) | ty::ty_int(_) | @@ -1636,7 +1643,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_err | ty::ty_param(..) | ty::ty_char => { - Vec::new() + Some(Vec::new()) } ty::ty_trait(..) | @@ -1649,23 +1656,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::ty_uniq(referent_ty) => { // Box - vec![referent_ty] + Some(vec![referent_ty]) } - ty::ty_open(element_ty) => {vec![element_ty]}, + ty::ty_open(element_ty) => {Some(vec![element_ty])}, ty::ty_ptr(ty::mt { ty: element_ty, ..}) | ty::ty_rptr(_, ty::mt { ty: element_ty, ..}) => { - vec![element_ty] + Some(vec![element_ty]) }, ty::ty_vec(element_ty, _) => { - vec![element_ty] + Some(vec![element_ty]) } ty::ty_tup(ref tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet - tys.clone() + Some(tys.clone()) } ty::ty_closure(def_id, _, substs) => { @@ -1673,26 +1680,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.closure_typer.closure_upvars(def_id, substs) { Some(upvars) => { - upvars.iter().map(|c| c.ty).collect() + Some(upvars.iter().map(|c| c.ty).collect()) } None => { - Vec::new() + None } } } ty::ty_struct(def_id, substs) => { - ty::struct_fields(self.tcx(), def_id, substs).iter() - .map(|f| f.mt.ty) - .collect() + Some(ty::struct_fields(self.tcx(), def_id, substs).iter() + .map(|f| f.mt.ty) + .collect()) } ty::ty_enum(def_id, substs) => { - ty::substd_enum_variants(self.tcx(), def_id, substs) - .iter() - .flat_map(|variant| variant.args.iter()) - .map(|&ty| ty) - .collect() + Some(ty::substd_enum_variants(self.tcx(), def_id, substs) + .iter() + .flat_map(|variant| variant.args.iter()) + .map(|&ty| ty) + .collect()) } } } @@ -1891,8 +1898,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { impl_def_id.repr(self.tcx())); let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty()); - let types = self.constituent_ty_obligations(self_ty); - Ok(self.vtable_default_impl(obligation, impl_def_id, types)) + match self.constituent_types_for_ty(self_ty) { + Some(types) => { + Ok(self.vtable_default_impl(obligation, impl_def_id, types)) + } + None => { + self.tcx().sess.bug( + &format!( + "asked to confirm default implementation for ambiguous type: {}", + self_ty.repr(self.tcx()))[]); + } + } } /// See `confirm_default_impl_candidate` From 1cc5a87c08fb1e9c6214e3370c78e3c217a0bae4 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Fri, 20 Feb 2015 11:17:08 +0100 Subject: [PATCH 24/32] Don't report bug for IntVar and FloatVar --- src/librustc/middle/traits/select.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index c86f0004de9..04c555632e1 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1642,13 +1642,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_str | ty::ty_err | ty::ty_param(..) | + ty::ty_infer(ty::IntVar(_)) | + ty::ty_infer(ty::FloatVar(_)) | ty::ty_char => { Some(Vec::new()) } ty::ty_trait(..) | ty::ty_projection(..) | - ty::ty_infer(..) => { + ty::ty_infer(_) => { self.tcx().sess.bug( &format!( "asked to assemble constituent types of unexpected type: {}", From 640000a7c0d49e03b22c635e98679d5cffb18f1a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 20 Feb 2015 05:16:59 -0500 Subject: [PATCH 25/32] fix treatment of parameters and associated types --- src/librustc/middle/traits/select.rs | 67 ++++++++++++++----- .../typeck-default-trait-impl-assoc-type.rs | 25 +++++++ .../typeck-default-trait-impl-send-param.rs | 21 ++++++ 3 files changed, 96 insertions(+), 17 deletions(-) create mode 100644 src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-send-param.rs diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 04c555632e1..f824ec50dc4 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1142,23 +1142,45 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); } - match self_ty.sty { - ty::ty_trait(..) => {}, - ty::ty_infer(ty::TyVar(_)) => { - // the defaulted impl might apply, we don't know - if ty::trait_has_default_impl(self.tcx(), def_id) { + if ty::trait_has_default_impl(self.tcx(), def_id) { + match self_ty.sty { + ty::ty_trait(..) | + ty::ty_param(..) | + ty::ty_projection(..) => { + // In these cases, we don't know what the actual + // type is. Therefore, we cannot break it down + // into its constituent types. So we don't + // consider the `..` impl but instead just add no + // candidates: this means that typeck will only + // succeed if there is another reason to believe + // that this obligation holds. That could be a + // where-clause or, in the case of an object type, + // it could be that the object type lists the + // trait (e.g. `Foo+Send : Send`). See + // `compile-fail/typeck-default-trait-impl-send-param.rs` + // for an example of a test case that exercises + // this path. + } + ty::ty_infer(ty::TyVar(_)) => { + // the defaulted impl might apply, we don't know candidates.ambiguous = true; } - } - _ => { - if ty::trait_has_default_impl(self.tcx(), def_id) { - match self.constituent_types_for_ty(self_ty) { - Some(_) => { - candidates.vec.push(DefaultImplCandidate(def_id.clone())) - } - None => { - candidates.ambiguous = true; - } + _ => { + if self.constituent_types_for_ty(self_ty).is_some() { + candidates.vec.push(DefaultImplCandidate(def_id.clone())) + } else { + // We don't yet know what the constituent + // types are. So call it ambiguous for now, + // though this is a bit stronger than + // necessary: that is, we know that the + // defaulted impl applies, but we can't + // process the confirmation step without + // knowing the constituent types. (Anyway, in + // the particular case of defaulted impls, it + // doesn't really matter much either way, + // since we won't be aiding inference by + // processing the confirmation step.) + candidates.ambiguous = true; } } } @@ -1632,6 +1654,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + /// For default impls, we need to break apart a type into its + /// "constituent types" -- meaning, the types that it contains. + /// + /// Here are some (simple) examples: + /// + /// ``` + /// (i32, u32) -> [i32, u32] + /// Foo where struct Foo { x: i32, y: u32 } -> [i32, u32] + /// Bar where struct Bar { x: T, y: u32 } -> [i32, u32] + /// Zed where enum Zed { A(T), B(u32) } -> [i32, u32] + /// ``` fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Option>> { match t.sty { ty::ty_uint(_) | @@ -1641,7 +1674,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_bare_fn(..) | ty::ty_str | ty::ty_err | - ty::ty_param(..) | ty::ty_infer(ty::IntVar(_)) | ty::ty_infer(ty::FloatVar(_)) | ty::ty_char => { @@ -1649,8 +1681,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::ty_trait(..) | + ty::ty_param(..) | ty::ty_projection(..) | - ty::ty_infer(_) => { + ty::ty_infer(ty::TyVar(_)) => { self.tcx().sess.bug( &format!( "asked to assemble constituent types of unexpected type: {}", diff --git a/src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs b/src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs new file mode 100644 index 00000000000..8a9d53731c5 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs @@ -0,0 +1,25 @@ +// Copyright 2015 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. + +// Test that we do not consider associated types to be sendable without +// some applicable trait bound (and we don't ICE). + +trait Trait { + type AssocType; + fn dummy(&self) { } +} +fn bar() { + is_send::(); //~ ERROR not implemented +} + +fn is_send() { +} + +fn main() { } diff --git a/src/test/compile-fail/typeck-default-trait-impl-send-param.rs b/src/test/compile-fail/typeck-default-trait-impl-send-param.rs new file mode 100644 index 00000000000..185e9dcb3bd --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-send-param.rs @@ -0,0 +1,21 @@ +// Copyright 2015 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. + +// Test that we do not consider parameter types to be sendable without +// an explicit trait bound. + +fn foo() { + is_send::() //~ ERROR not implemented +} + +fn is_send() { +} + +fn main() { } From 3ebc2abc6affd826c564630c036f4aa24c4fbe53 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 20 Feb 2015 05:47:09 -0500 Subject: [PATCH 26/32] tweak exhaustive matching of ty_infer --- src/librustc/middle/traits/select.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index f824ec50dc4..1eb1c650e7c 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1683,7 +1683,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_trait(..) | ty::ty_param(..) | ty::ty_projection(..) | - ty::ty_infer(ty::TyVar(_)) => { + ty::ty_infer(ty::TyVar(_)) | + ty::ty_infer(ty::FreshTy(_)) | + ty::ty_infer(ty::FreshIntTy(_)) => { self.tcx().sess.bug( &format!( "asked to assemble constituent types of unexpected type: {}", From 6d1844c8065c5c680b0a86c83152902b47bc856c Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Fri, 20 Feb 2015 15:46:50 +0100 Subject: [PATCH 27/32] Record default implementations in a separate step --- src/librustc/middle/traits/select.rs | 23 ++++++++++++++++++- src/libtest/stats.rs | 1 + .../coherence-default-trait-impl.rs | 4 +++- ...-default-trait-impl-constituent-types-2.rs | 4 +++- ...ck-default-trait-impl-constituent-types.rs | 7 +++--- .../typeck-default-trait-impl-negation.rs | 6 +++-- .../typeck-default-trait-impl-supertrait.rs | 4 +++- ...k-default-trait-impl-trait-where-clause.rs | 6 +++-- 8 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 1eb1c650e7c..a328c5c2d75 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -847,6 +847,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.assemble_candidates_from_projected_tys(obligation, &mut candidates); try!(self.assemble_candidates_from_caller_bounds(stack, &mut candidates)); + // Default implementations have lower priority, so we only + // consider triggering a default if there is no other impl that can apply. + if candidates.vec.len() == 0 { + try!(self.assemble_candidates_from_default_impls(obligation, &mut candidates)); + } debug!("candidate list size: {}", candidates.vec.len()); Ok(candidates) } @@ -1142,6 +1147,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); } + Ok(()) + } + + fn assemble_candidates_from_default_impls(&mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>) + -> Result<(), SelectionError<'tcx>> + { + + let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); + debug!("assemble_candidates_from_default_impls(self_ty={})", self_ty.repr(self.tcx())); + + let def_id = obligation.predicate.def_id(); + if ty::trait_has_default_impl(self.tcx(), def_id) { match self_ty.sty { ty::ty_trait(..) | @@ -1323,7 +1342,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } (&DefaultImplCandidate(_), _) => { // Prefer other candidates over default implementations. - true + self.tcx().sess.bug( + "default implementations shouldn't be recorded \ + when there are other valid candidates"); } (&ProjectionCandidate, &ParamCandidate(_)) => { // FIXME(#20297) -- this gives where clauses precedent diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 4e94be59ade..7cc07e926b2 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -332,6 +332,7 @@ pub fn winsorize(samples: &mut [T], pct: T) { /// Returns a HashMap with the number of occurrences of every element in the /// sequence that the iterator exposes. +#[cfg(not(stage0))] pub fn freq_count(iter: T) -> hash_map::HashMap where T: Iterator, U: Eq + Clone + Hash { diff --git a/src/test/compile-fail/coherence-default-trait-impl.rs b/src/test/compile-fail/coherence-default-trait-impl.rs index bcc3353ba02..ab653b3a554 100644 --- a/src/test/compile-fail/coherence-default-trait-impl.rs +++ b/src/test/compile-fail/coherence-default-trait-impl.rs @@ -12,7 +12,9 @@ #![feature(optin_builtin_traits)] -trait MyTrait {} +use std::marker::MarkerTrait; + +trait MyTrait: MarkerTrait {} impl MyTrait for .. {} diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs index a27f7f7ebbe..0f3453da431 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs @@ -10,7 +10,9 @@ #![feature(optin_builtin_traits)] -trait MyTrait {} +use std::marker::MarkerTrait; + +trait MyTrait: MarkerTrait {} impl MyTrait for .. {} diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs index 556a0a1a0f3..524f467e017 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs @@ -10,7 +10,9 @@ #![feature(optin_builtin_traits)] -trait MyTrait {} +use std::marker::MarkerTrait; + +trait MyTrait: MarkerTrait {} impl MyTrait for .. {} impl !MyTrait for *mut T {} @@ -30,7 +32,4 @@ fn main() { is_mytrait::(); //~^ ERROR the trait `MyTrait` is not implemented for the type `MyS2` - - is_mytrait::>(); - //~^ ERROR the trait `MyTrait` is not implemented for the type `*mut MyS3` } diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation.rs b/src/test/compile-fail/typeck-default-trait-impl-negation.rs index 4b91d0b7a73..a1ca0e3e0fa 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-negation.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-negation.rs @@ -10,11 +10,13 @@ #![feature(optin_builtin_traits)] -trait MyTrait {} +use std::marker::MarkerTrait; + +trait MyTrait: MarkerTrait {} impl MyTrait for .. {} -unsafe trait MyUnsafeTrait {} +unsafe trait MyUnsafeTrait: MarkerTrait {} unsafe impl MyUnsafeTrait for .. {} diff --git a/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs b/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs index c9bfdff6c0e..7f24058e475 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs @@ -13,7 +13,9 @@ #![feature(optin_builtin_traits)] -trait NotImplemented { } +use std::marker::MarkerTrait; + +trait NotImplemented: MarkerTrait { } trait MyTrait : NotImplemented {} diff --git a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs index 4f572e87639..c970aaaf5d4 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs @@ -15,9 +15,11 @@ #![feature(optin_builtin_traits)] -trait NotImplemented { } +use std::marker::MarkerTrait; -trait MyTrait +trait NotImplemented: MarkerTrait { } + +trait MyTrait: MarkerTrait where Option : NotImplemented {} From 3343e9c16976aabef9836e61213e64a0552ec051 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 20 Feb 2015 13:34:13 -0500 Subject: [PATCH 28/32] Add new test for impl precedence and remove unnecessary coherence rules that prevent the test from compiling. --- src/librustc_typeck/coherence/overlap.rs | 57 +------------------ .../typeck-default-trait-impl-precedence.rs | 32 +++++++++++ 2 files changed, 33 insertions(+), 56 deletions(-) create mode 100644 src/test/compile-fail/typeck-default-trait-impl-precedence.rs diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 9accfe7749e..14ca867a56c 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -17,18 +17,12 @@ use middle::infer::{self, new_infer_ctxt}; use syntax::ast::{DefId}; use syntax::ast::{LOCAL_CRATE}; use syntax::ast; -use syntax::ast_util; -use syntax::visit; use syntax::codemap::Span; use util::ppaux::Repr; pub fn check(tcx: &ty::ctxt) { - let mut overlap = OverlapChecker { tcx: tcx }; + let overlap = OverlapChecker { tcx: tcx }; overlap.check_for_overlapping_impls(); - - // this secondary walk specifically checks for impls of defaulted - // traits, for which additional overlap rules exist - visit::walk_crate(&mut overlap, tcx.map.krate()); } struct OverlapChecker<'cx, 'tcx:'cx> { @@ -128,52 +122,3 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { self.tcx.map.span(impl_did.node) } } - - -impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { - fn visit_item(&mut self, item: &'v ast::Item) { - match item.node { - ast::ItemImpl(_, ast::ImplPolarity::Positive, _, Some(ref ast_trait_ref), _, _) => { - let trait_ref = ty::node_id_to_trait_ref(self.tcx, ast_trait_ref.ref_id); - match ty::trait_default_impl(self.tcx, trait_ref.def_id) { - Some(default_impl) => { - match trait_ref.self_ty().sty { - ty::ty_struct(..) | ty::ty_enum(..) => {}, - _ => { - let impl_def_id = ast_util::local_def(item.id); - span_err!(self.tcx.sess, self.span_of_impl(impl_def_id), E0319, - "implementations for traits providing default \ - implementations are only allowed on structs and enums"); - - self.report_overlap_note(impl_def_id, default_impl); - } - } - } - None => {} - } - } - ast::ItemDefaultImpl(_, _) => { - let impl_def_id = ast_util::local_def(item.id); - match ty::impl_trait_ref(self.tcx, impl_def_id) { - Some(ref trait_ref) => { - match ty::trait_default_impl(self.tcx, trait_ref.def_id) { - Some(other_impl) if other_impl != impl_def_id => { - self.report_overlap_error(trait_ref.def_id, - other_impl, - impl_def_id); - } - Some(_) => {} - None => { - self.tcx.sess.bug( - &format!("no default implementation recorded for `{:?}`", - item)[]); - } - } - } - _ => {} - } - } - _ => {} - } - } -} diff --git a/src/test/compile-fail/typeck-default-trait-impl-precedence.rs b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs new file mode 100644 index 00000000000..e519c3f2c2f --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs @@ -0,0 +1,32 @@ +// Copyright 2015 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. + +// Test that declaring that `&T` is `Defaulted` if `T:Signed` implies +// that other `&T` is NOT `Defaulted` if `T:Signed` does not hold. In +// other words, the `..` impl only applies if there are no existing +// impls whose types unify. + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +trait Defaulted : MarkerTrait { } +impl Defaulted for .. { } +impl<'a,T:Signed> Defaulted for &'a T { } +impl<'a,T:Signed> Defaulted for &'a mut T { } +fn is_defaulted() { } + +trait Signed : MarkerTrait { } +impl Signed for i32 { } + +fn main() { + is_defaulted::<&'static i32>(); + is_defaulted::<&'static u32>(); +} From d021c55fb9a18b854cd70a3d67a260d4d71a14c3 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Fri, 20 Feb 2015 23:42:53 +0100 Subject: [PATCH 29/32] Restore the coherence visitor and fix fallouts --- src/librustc_typeck/coherence/overlap.rs | 38 ++++++++++++++++++- .../coherence-default-trait-impl.rs | 3 -- .../compile-fail/coherence-impls-builtin.rs | 1 + src/test/compile-fail/recursion_limit.rs | 3 ++ .../typeck-default-trait-impl-precedence.rs | 1 + 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 14ca867a56c..366e934b4dd 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -17,12 +17,18 @@ use middle::infer::{self, new_infer_ctxt}; use syntax::ast::{DefId}; use syntax::ast::{LOCAL_CRATE}; use syntax::ast; +use syntax::ast_util; +use syntax::visit; use syntax::codemap::Span; use util::ppaux::Repr; pub fn check(tcx: &ty::ctxt) { - let overlap = OverlapChecker { tcx: tcx }; + let mut overlap = OverlapChecker { tcx: tcx }; overlap.check_for_overlapping_impls(); + + // this secondary walk specifically checks for impls of defaulted + // traits, for which additional overlap rules exist + visit::walk_crate(&mut overlap, tcx.map.krate()); } struct OverlapChecker<'cx, 'tcx:'cx> { @@ -122,3 +128,33 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { self.tcx.map.span(impl_did.node) } } + + +impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { + fn visit_item(&mut self, item: &'v ast::Item) { + match item.node { + ast::ItemDefaultImpl(_, _) => { + let impl_def_id = ast_util::local_def(item.id); + match ty::impl_trait_ref(self.tcx, impl_def_id) { + Some(ref trait_ref) => { + match ty::trait_default_impl(self.tcx, trait_ref.def_id) { + Some(other_impl) if other_impl != impl_def_id => { + self.report_overlap_error(trait_ref.def_id, + other_impl, + impl_def_id); + } + Some(_) => {} + None => { + self.tcx.sess.bug( + &format!("no default implementation recorded for `{:?}`", + item)[]); + } + } + } + _ => {} + } + } + _ => {} + } + } +} diff --git a/src/test/compile-fail/coherence-default-trait-impl.rs b/src/test/compile-fail/coherence-default-trait-impl.rs index ab653b3a554..6bcbefb904d 100644 --- a/src/test/compile-fail/coherence-default-trait-impl.rs +++ b/src/test/compile-fail/coherence-default-trait-impl.rs @@ -21,7 +21,4 @@ impl MyTrait for .. {} impl MyTrait for .. {} //~^ ERROR conflicting implementations for trait `MyTrait` -impl MyTrait for (i32, i32) {} -//~^ ERROR implementations for traits providing default implementations are only allowed on - fn main() {} diff --git a/src/test/compile-fail/coherence-impls-builtin.rs b/src/test/compile-fail/coherence-impls-builtin.rs index 38730d241f6..3e132dcb11f 100644 --- a/src/test/compile-fail/coherence-impls-builtin.rs +++ b/src/test/compile-fail/coherence-impls-builtin.rs @@ -34,6 +34,7 @@ unsafe impl Send for [MyType] {} unsafe impl Send for &'static [NotSync] {} //~^ ERROR builtin traits can only be implemented on structs or enums +//~^^ ERROR conflicting implementations for trait `core::marker::Send` fn is_send() {} diff --git a/src/test/compile-fail/recursion_limit.rs b/src/test/compile-fail/recursion_limit.rs index 6cd984c071a..e8bc11317f2 100644 --- a/src/test/compile-fail/recursion_limit.rs +++ b/src/test/compile-fail/recursion_limit.rs @@ -47,4 +47,7 @@ fn main() { //~^^^^ ERROR overflow evaluating //~^^^^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate //~^^^^^^ NOTE required by `is_send` + //~^^^^^^^ ERROR overflow evaluating + //~^^^^^^^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate + //~^^^^^^^^^ NOTE required by `is_send` } diff --git a/src/test/compile-fail/typeck-default-trait-impl-precedence.rs b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs index e519c3f2c2f..4006eb2e83e 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-precedence.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs @@ -29,4 +29,5 @@ impl Signed for i32 { } fn main() { is_defaulted::<&'static i32>(); is_defaulted::<&'static u32>(); + //~^ ERROR the trait `Signed` is not implemented for the type `u32` } From 753db889149db712598ff2a1ee34885d7b9680cc Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Sat, 21 Feb 2015 01:01:48 +0100 Subject: [PATCH 30/32] allow negative impls for traits that have a default impl --- src/librustc_typeck/check/wf.rs | 9 ++++++--- src/test/compile-fail/typeck-negative-impls-builtin.rs | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 2601c4d2752..c6fafb7a77a 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -83,12 +83,15 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { } ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(ref tref), _, _) => { let trait_ref = ty::node_id_to_trait_ref(ccx.tcx, tref.ref_id); + ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id); match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) { Some(ty::BoundSend) | Some(ty::BoundSync) => {} Some(_) | None => { - span_err!(ccx.tcx.sess, item.span, E0192, - "negative impls are currently \ - allowed just for `Send` and `Sync`") + if !ty::trait_has_default_impl(ccx.tcx, trait_ref.def_id) { + span_err!(ccx.tcx.sess, item.span, E0192, + "negative impls are only allowed for traits with \ + default impls (e.g., `Send` and `Sync`)") + } } } } diff --git a/src/test/compile-fail/typeck-negative-impls-builtin.rs b/src/test/compile-fail/typeck-negative-impls-builtin.rs index 557fb2f4f88..57a394dc7f1 100644 --- a/src/test/compile-fail/typeck-negative-impls-builtin.rs +++ b/src/test/compile-fail/typeck-negative-impls-builtin.rs @@ -17,6 +17,6 @@ trait TestTrait { } impl !TestTrait for TestType {} -//~^ ERROR negative impls are currently allowed just for `Send` and `Sync` +//~^ ERROR negative impls are only allowed for traits with default impls (e.g., `Send` and `Sync`) fn main() {} From 038d7e69e8861bd038e3dbd91adf078f72b6c887 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Sat, 21 Feb 2015 11:49:15 +0100 Subject: [PATCH 31/32] Fix test fallouts --- src/librustc_driver/test.rs | 2 +- src/test/parse-fail/empty-impl-semicolon.rs | 2 +- src/test/parse-fail/multitrait.rs | 2 +- src/test/parse-fail/trait-bounds-not-on-impl.rs | 4 +++- src/test/pretty/default-trait-impl.rs | 4 +++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index fbbd72e2c76..cdcc9850e42 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -206,7 +206,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { ast::ItemEnum(..) | ast::ItemStruct(..) | ast::ItemTrait(..) | ast::ItemImpl(..) | - ast::ItemMac(..) => { + ast::ItemMac(..) | ast::ItemDefaultImpl(..) => { None } diff --git a/src/test/parse-fail/empty-impl-semicolon.rs b/src/test/parse-fail/empty-impl-semicolon.rs index 70c7d42feb5..a2e780d49b8 100644 --- a/src/test/parse-fail/empty-impl-semicolon.rs +++ b/src/test/parse-fail/empty-impl-semicolon.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -impl Foo; //~ ERROR expected one of `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;` +impl Foo; //~ ERROR expected one of `(`, `+`, `..`, `::`, `<`, `for`, `where`, or `{`, found `;` diff --git a/src/test/parse-fail/multitrait.rs b/src/test/parse-fail/multitrait.rs index f182eb8fa5b..a8b2fa4e115 100644 --- a/src/test/parse-fail/multitrait.rs +++ b/src/test/parse-fail/multitrait.rs @@ -13,7 +13,7 @@ struct S { } impl Cmp, ToString for S { -//~^ ERROR: expected one of `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `,` +//~^ ERROR: expected one of `(`, `+`, `..`, `::`, `<`, `for`, `where`, or `{`, found `,` fn eq(&&other: S) { false } fn to_string(&self) -> String { "hi".to_string() } } diff --git a/src/test/parse-fail/trait-bounds-not-on-impl.rs b/src/test/parse-fail/trait-bounds-not-on-impl.rs index a034352c4a6..51447b22576 100644 --- a/src/test/parse-fail/trait-bounds-not-on-impl.rs +++ b/src/test/parse-fail/trait-bounds-not-on-impl.rs @@ -13,7 +13,9 @@ trait Foo { struct Bar; -impl Foo + Owned for Bar { //~ ERROR not a trait +impl Foo + Owned for Bar { +//~^ ERROR not a trait +//~^^ ERROR expected one of `..`, `where`, or `{`, found `Bar` } fn main() { } diff --git a/src/test/pretty/default-trait-impl.rs b/src/test/pretty/default-trait-impl.rs index a5246b9300c..d148bb15e99 100644 --- a/src/test/pretty/default-trait-impl.rs +++ b/src/test/pretty/default-trait-impl.rs @@ -12,7 +12,9 @@ // pp-exact -trait MyTrait { } +use std::marker::MarkerTrait; + +trait MyTrait: MarkerTrait { } impl MyTrait for .. { } From 3dcc631dee7b2f4be3443b4bbc1dd916436d60ca Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 22 Feb 2015 07:14:53 -0500 Subject: [PATCH 32/32] Add additional test case for superregion --- .../typeck-default-trait-impl-superregion.rs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/test/compile-fail/typeck-default-trait-impl-superregion.rs diff --git a/src/test/compile-fail/typeck-default-trait-impl-superregion.rs b/src/test/compile-fail/typeck-default-trait-impl-superregion.rs new file mode 100644 index 00000000000..4a6a77ac7b4 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-superregion.rs @@ -0,0 +1,29 @@ +// Copyright 2015 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. + +// Test that when a `..` impl applies, we also check that any +// supertrait conditions are met. + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +trait MyTrait : 'static {} + +impl MyTrait for .. {} + +fn foo() { } + +fn bar<'a>() { + foo::<&'a ()>(); //~ ERROR does not fulfill the required lifetime +} + +fn main() { +}