]> git.lizzy.rs Git - rust.git/commitdiff
rustc_typeck: rework coherence to be almost completely on-demand.
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Sun, 19 Feb 2017 12:46:29 +0000 (14:46 +0200)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Sat, 25 Feb 2017 16:35:26 +0000 (18:35 +0200)
53 files changed:
src/librustc/dep_graph/dep_node.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/infer/mod.rs
src/librustc/middle/cstore.rs
src/librustc/traits/mod.rs
src/librustc/traits/project.rs
src/librustc/traits/specialize/mod.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/ty/contents.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/trait_def.rs
src/librustc/ty/util.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
src/librustc_borrowck/borrowck/gather_loans/move_error.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_borrowck/borrowck/mir/gather_moves.rs
src/librustc_borrowck/borrowck/mir/mod.rs
src/librustc_const_eval/check_match.rs
src/librustc_const_eval/eval.rs
src/librustc_driver/test.rs
src/librustc_incremental/calculate_svh/svh_visitor.rs
src/librustc_lint/builtin.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_mir/mir_map.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/type_check.rs
src/librustc_passes/consts.rs
src/librustc_passes/rvalues.rs
src/librustc_trans/collector.rs
src/librustc_trans/glue.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/coherence/builtin.rs
src/librustc_typeck/coherence/inherent.rs [new file with mode: 0644]
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/coherence/unsafety.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/inline.rs
src/test/compile-fail/E0117.rs
src/test/compile-fail/coherence-cross-crate-conflict.rs
src/test/compile-fail/coherence-default-trait-impl.rs
src/test/compile-fail/coherence-impls-sized.rs
src/test/ui/span/E0204.stderr

index 769c08a81efa62cea6c3e761a526d033fc064d32..e0233d6f8b98cd1bf818a8766f58da2781a6919c 100644 (file)
@@ -70,6 +70,7 @@ pub enum DepNode<D: Clone + Debug> {
     Resolve,
     EntryPoint,
     CheckEntryFn,
+    CoherenceCheckTrait(D),
     CoherenceCheckImpl(D),
     CoherenceOverlapCheck(D),
     CoherenceOverlapCheckSpecial(D),
@@ -241,6 +242,7 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             MetaData(ref d) => op(d).map(MetaData),
             CollectItem(ref d) => op(d).map(CollectItem),
             CollectItemSig(ref d) => op(d).map(CollectItemSig),
+            CoherenceCheckTrait(ref d) => op(d).map(CoherenceCheckTrait),
             CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
             CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),
             CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial),
index bfcaf1e00f06eca5d4428137b6fac46eacc522dd..468421a68b54cb5f88168056a7d67ddf07f77761 100644 (file)
@@ -80,6 +80,9 @@ pub struct LoweringContext<'a> {
     impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
     bodies: FxHashMap<hir::BodyId, hir::Body>,
 
+    trait_impls: BTreeMap<DefId, Vec<NodeId>>,
+    trait_default_impl: BTreeMap<DefId, NodeId>,
+
     loop_scopes: Vec<NodeId>,
     is_in_loop_condition: bool,
 
@@ -116,6 +119,8 @@ pub fn lower_crate(sess: &Session,
         trait_items: BTreeMap::new(),
         impl_items: BTreeMap::new(),
         bodies: FxHashMap(),
+        trait_impls: BTreeMap::new(),
+        trait_default_impl: BTreeMap::new(),
         loop_scopes: Vec::new(),
         is_in_loop_condition: false,
         type_def_lifetime_params: DefIdMap(),
@@ -201,6 +206,8 @@ fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
             trait_items: self.trait_items,
             impl_items: self.impl_items,
             bodies: self.bodies,
+            trait_impls: self.trait_impls,
+            trait_default_impl: self.trait_default_impl,
         }
     }
 
@@ -1089,14 +1096,27 @@ fn lower_item_kind(&mut self,
                 hir::ItemUnion(vdata, self.lower_generics(generics))
             }
             ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
+                let trait_ref = self.lower_trait_ref(trait_ref);
+
+                if let Def::Trait(def_id) = trait_ref.path.def {
+                    self.trait_default_impl.insert(def_id, id);
+                }
+
                 hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
-                                     self.lower_trait_ref(trait_ref))
+                                     trait_ref)
             }
             ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
                 let new_impl_items = impl_items.iter()
                                                .map(|item| self.lower_impl_item_ref(item))
                                                .collect();
                 let ifce = ifce.as_ref().map(|trait_ref| self.lower_trait_ref(trait_ref));
+
+                if let Some(ref trait_ref) = ifce {
+                    if let Def::Trait(def_id) = trait_ref.path.def {
+                        self.trait_impls.entry(def_id).or_insert(vec![]).push(id);
+                    }
+                }
+
                 hir::ItemImpl(self.lower_unsafety(unsafety),
                               self.lower_impl_polarity(polarity),
                               self.lower_generics(generics),
index 13b786541c50275bac835cdd36661cb90e1e0cb7..20b4d8d8a8f031b71be26fe141630fef933d1fdd 100644 (file)
@@ -461,6 +461,26 @@ pub fn ty_param_name(&self, id: NodeId) -> Name {
         }
     }
 
+    pub fn trait_impls(&self, trait_did: DefId) -> &'hir [NodeId] {
+        self.dep_graph.read(DepNode::TraitImpls(trait_did));
+
+        // NB: intentionally bypass `self.forest.krate()` so that we
+        // do not trigger a read of the whole krate here
+        self.forest.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..])
+    }
+
+    pub fn trait_default_impl(&self, trait_did: DefId) -> Option<NodeId> {
+        self.dep_graph.read(DepNode::TraitImpls(trait_did));
+
+        // NB: intentionally bypass `self.forest.krate()` so that we
+        // do not trigger a read of the whole krate here
+        self.forest.krate.trait_default_impl.get(&trait_did).cloned()
+    }
+
+    pub fn trait_is_auto(&self, trait_did: DefId) -> bool {
+        self.trait_default_impl(trait_did).is_some()
+    }
+
     /// Get the attributes on the krate. This is preferable to
     /// invoking `krate.attrs` because it registers a tighter
     /// dep-graph access.
index e8c5f2447cd6f5a15ffd9e62b4a267f2b798e16a..8b6c75886baa8121ff62903a2c773202766531f3 100644 (file)
@@ -410,6 +410,9 @@ pub struct Crate {
     pub trait_items: BTreeMap<TraitItemId, TraitItem>,
     pub impl_items: BTreeMap<ImplItemId, ImplItem>,
     pub bodies: FxHashMap<BodyId, Body>,
+
+    pub trait_impls: BTreeMap<DefId, Vec<NodeId>>,
+    pub trait_default_impl: BTreeMap<DefId, NodeId>,
 }
 
 impl Crate {
index d7f254df7538a6b878e0e9faf2f4850d40a278e8..a929060cf98904e53d626677c179b43d20fce79a 100644 (file)
@@ -505,7 +505,7 @@ pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId)
             evaluation_cache: traits::EvaluationCache::new(),
             projection_cache: RefCell::new(traits::ProjectionCache::new()),
             reported_trait_errors: RefCell::new(FxHashSet()),
-            projection_mode: Reveal::NotSpecializable,
+            projection_mode: Reveal::UserFacing,
             tainted_by_errors_flag: Cell::new(false),
             err_count_on_creation: self.sess.err_count(),
             obligations_in_snapshot: Cell::new(false),
index cb5ced57bd8b915e83f98d70055e3f555511f0d6..4a7027b8997a5854befdef64121af1d4b96a373e 100644 (file)
@@ -191,7 +191,6 @@ pub trait CrateStore {
 
     // flags
     fn is_const_fn(&self, did: DefId) -> bool;
-    fn is_defaulted_trait(&self, did: DefId) -> bool;
     fn is_default_impl(&self, impl_did: DefId) -> bool;
     fn is_foreign_item(&self, did: DefId) -> bool;
     fn is_dllimport_foreign_item(&self, def: DefId) -> bool;
@@ -327,7 +326,6 @@ fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem
 
     // flags
     fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") }
-    fn is_defaulted_trait(&self, did: DefId) -> bool { bug!("is_defaulted_trait") }
     fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") }
     fn is_foreign_item(&self, did: DefId) -> bool { bug!("is_foreign_item") }
     fn is_dllimport_foreign_item(&self, id: DefId) -> bool { false }
index 117e16da26c3f3371c040a3b1819379dc3fdd96d..7e7d06e4b814e681e025a1b33e5966582c7043c0 100644 (file)
@@ -473,7 +473,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
 
-    tcx.infer_ctxt(elaborated_env, Reveal::NotSpecializable).enter(|infcx| {
+    tcx.infer_ctxt(elaborated_env, Reveal::UserFacing).enter(|infcx| {
         let predicates = match fully_normalize(&infcx, cause,
                                                &infcx.parameter_environment.caller_bounds) {
             Ok(predicates) => predicates,
index 448a3166bd8609ec1db82482a6f75ba31edd0451..3d8f9e41c675b877e8fba6edf51f4155ceba7aed 100644 (file)
 /// more or less conservative.
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub enum Reveal {
-    /// FIXME (#32205)
-    /// At coherence-checking time, we're still constructing the
-    /// specialization graph, and thus we only project
-    /// non-`default` associated types that are defined directly in
-    /// the applicable impl. (This behavior should be improved over
-    /// time, to allow for successful projections modulo cycles
-    /// between different impls).
-    ///
-    /// Here's an example that will fail due to the restriction:
-    ///
-    /// ```
-    /// trait Assoc {
-    ///     type Output;
-    /// }
-    ///
-    /// impl<T> Assoc for T {
-    ///     type Output = bool;
-    /// }
-    ///
-    /// impl Assoc for u8 {} // <- inherits the non-default type from above
-    ///
-    /// trait Foo {}
-    /// impl Foo for u32 {}
-    /// impl Foo for <u8 as Assoc>::Output {}  // <- this projection will fail
-    /// ```
-    ///
-    /// The projection would succeed if `Output` had been defined
-    /// directly in the impl for `u8`.
-    ExactMatch,
-
     /// At type-checking time, we refuse to project any associated
     /// type that is marked `default`. Non-`default` ("final") types
     /// are always projected. This is necessary in general for
@@ -90,7 +60,7 @@ pub enum Reveal {
     /// fn main() {
     ///     let <() as Assoc>::Output = true;
     /// }
-    NotSpecializable,
+    UserFacing,
 
     /// At trans time, all monomorphic projections will succeed.
     /// Also, `impl Trait` is normalized to the concrete type,
@@ -1347,8 +1317,9 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>(
     -> Option<specialization_graph::NodeItem<ty::AssociatedItem>>
 {
     let trait_def_id = selcx.tcx().impl_trait_ref(impl_def_id).unwrap().def_id;
+    let trait_def = selcx.tcx().lookup_trait_def(trait_def_id);
 
-    if selcx.projection_mode() == Reveal::ExactMatch {
+    if !trait_def.is_complete(selcx.tcx()) {
         let impl_node = specialization_graph::Node::Impl(impl_def_id);
         for item in impl_node.items(selcx.tcx()) {
             if item.kind == ty::AssociatedKind::Type && item.name == assoc_ty_name {
@@ -1360,7 +1331,7 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>(
         }
         None
     } else {
-        selcx.tcx().lookup_trait_def(trait_def_id)
+        trait_def
             .ancestors(impl_def_id)
             .defs(selcx.tcx(), assoc_ty_name, ty::AssociatedKind::Type)
             .next()
index 0fe054b30ba3174a1c1bfa3cbe6b6fbc0d1bc51f..79df7de04f540a9c955a0a942660c5336d3d41da 100644 (file)
@@ -189,7 +189,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              .subst(tcx, &penv.free_substs);
 
     // Create a infcx, taking the predicates of impl1 as assumptions:
-    let result = tcx.infer_ctxt(penv, Reveal::ExactMatch).enter(|infcx| {
+    let result = tcx.infer_ctxt(penv, Reveal::UserFacing).enter(|infcx| {
         // Normalize the trait reference. The WF rules ought to ensure
         // that this always succeeds.
         let impl1_trait_ref =
index 368b1fb4bcbd38ca4d61e0356fa993a2a19b860c..40eb69395678f2bd63d39a03d35b980e9d0524e9 100644 (file)
@@ -108,7 +108,7 @@ fn insert(&mut self,
             let possible_sibling = *slot;
 
             let tcx = tcx.global_tcx();
-            let (le, ge) = tcx.infer_ctxt((), Reveal::ExactMatch).enter(|infcx| {
+            let (le, ge) = tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
                 let overlap = traits::overlapping_impls(&infcx,
                                                         possible_sibling,
                                                         impl_def_id);
index 56621c57eb8f7bed86f3b7c10f99b6fbd565acc1..e14295982916f44ad0578777db464581b6a4554d 100644 (file)
@@ -219,7 +219,7 @@ fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         res = res - TC::OwnsDtor;
                     }
 
-                    if def.has_dtor() {
+                    if def.has_dtor(tcx) {
                         res = res | TC::OwnsDtor;
                     }
 
index 26c92e3e7ecf72dee18d354a5d7f09d56a083be3..358d69ff8dba99d529a6982d51a328db990436cb 100644 (file)
@@ -24,6 +24,15 @@ trait Key {
     fn default_span(&self, tcx: TyCtxt) -> Span;
 }
 
+impl Key for CrateNum {
+    fn map_crate(&self) -> CrateNum {
+        *self
+    }
+    fn default_span(&self, _: TyCtxt) -> Span {
+        DUMMY_SP
+    }
+}
+
 impl Key for DefId {
     fn map_crate(&self) -> CrateNum {
         self.krate
@@ -42,6 +51,15 @@ fn default_span(&self, tcx: TyCtxt) -> Span {
     }
 }
 
+impl Key for (CrateNum, DefId) {
+    fn map_crate(&self) -> CrateNum {
+        self.0
+    }
+    fn default_span(&self, tcx: TyCtxt) -> Span {
+        self.1.default_span(tcx)
+    }
+}
+
 trait Value<'tcx>: Sized {
     fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
 }
@@ -141,6 +159,19 @@ fn describe(tcx: TyCtxt, (_, def_id): (DefId, DefId)) -> String {
     }
 }
 
+impl<'tcx> QueryDescription for queries::coherent_trait<'tcx> {
+    fn describe(tcx: TyCtxt, (_, def_id): (CrateNum, DefId)) -> String {
+        format!("coherence checking all impls of trait `{}`",
+                tcx.item_path_str(def_id))
+    }
+}
+
+impl<'tcx> QueryDescription for queries::coherent_inherent_impls<'tcx> {
+    fn describe(_: TyCtxt, _: CrateNum) -> String {
+        format!("coherence checking all inherent impls")
+    }
+}
+
 macro_rules! define_maps {
     (<$tcx:tt>
      $($(#[$attr:meta])*
@@ -238,6 +269,12 @@ pub fn get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) -> $V {
             }
 
             pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) {
+                // FIXME(eddyb) Move away from using `DepTrackingMap`
+                // so we don't have to explicitly ignore a false edge:
+                // we can't observe a value dependency, only side-effects,
+                // through `force`, and once everything has been updated,
+                // perhaps only diagnostics, if those, will remain.
+                let _ignore = tcx.dep_graph.in_ignore();
                 match Self::try_get_with(tcx, span, key, |_| ()) {
                     Ok(()) => {}
                     Err(e) => tcx.report_cycle(e)
@@ -338,7 +375,19 @@ fn default() -> Self {
 
     pub typeck_tables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,
 
+    pub coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
+
+    pub coherent_inherent_impls: coherent_inherent_impls_dep_node(CrateNum) -> (),
+
     /// Results of evaluating monomorphic constants embedded in
     /// other items, such as enum variant explicit discriminants.
     pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result<ConstVal, ()>
 }
+
+fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
+    DepNode::CoherenceCheckTrait(def_id)
+}
+
+fn coherent_inherent_impls_dep_node(_: CrateNum) -> DepNode<DefId> {
+    DepNode::Coherence
+}
index 5ab0c9e5655190847955e2fffd1194e0cc51a610..55b6f61148d7715b947e7665d25942536f4b82f0 100644 (file)
@@ -1301,6 +1301,7 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
         const IS_FUNDAMENTAL      = 1 << 4,
         const IS_UNION            = 1 << 5,
         const IS_BOX              = 1 << 6,
+        const IS_DTOR_VALID       = 1 << 7,
     }
 }
 
@@ -1522,8 +1523,8 @@ pub fn is_box(&self) -> bool {
     }
 
     /// Returns whether this type has a destructor.
-    pub fn has_dtor(&self) -> bool {
-        self.destructor.get().is_some()
+    pub fn has_dtor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
+        self.destructor(tcx).is_some()
     }
 
     /// Asserts this is a struct and returns the struct's unique
@@ -1578,12 +1579,36 @@ pub fn variant_of_def(&self, def: Def) -> &VariantDef {
         }
     }
 
-    pub fn destructor(&self) -> Option<DefId> {
-        self.destructor.get()
+    pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<DefId> {
+        if self.flags.get().intersects(AdtFlags::IS_DTOR_VALID) {
+            return self.destructor.get();
+        }
+
+        let dtor = self.destructor_uncached(tcx);
+        self.destructor.set(dtor);
+        self.flags.set(self.flags.get() | AdtFlags::IS_DTOR_VALID);
+
+        dtor
     }
 
-    pub fn set_destructor(&self, dtor: DefId) {
-        self.destructor.set(Some(dtor));
+    fn destructor_uncached(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<DefId> {
+        let drop_trait = if let Some(def_id) = tcx.lang_items.drop_trait() {
+            def_id
+        } else {
+            return None;
+        };
+
+        queries::coherent_trait::get(tcx, DUMMY_SP, (LOCAL_CRATE, drop_trait));
+
+        let mut dtor = None;
+        let ty = tcx.item_type(self.did);
+        tcx.lookup_trait_def(drop_trait).for_each_relevant_impl(tcx, ty, |def_id| {
+            if let Some(item) = tcx.associated_items(def_id).next() {
+                dtor = Some(item.def_id);
+            }
+        });
+
+        dtor
     }
 
     pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
@@ -2367,23 +2392,18 @@ pub fn item_variances(self, item_id: DefId) -> Rc<Vec<ty::Variance>> {
     }
 
     pub fn trait_has_default_impl(self, trait_def_id: DefId) -> bool {
-        self.populate_implementations_for_trait_if_necessary(trait_def_id);
-
         let def = self.lookup_trait_def(trait_def_id);
         def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL)
     }
 
-    /// Records a trait-to-implementation mapping.
-    pub fn record_trait_has_default_impl(self, trait_def_id: DefId) {
-        let def = self.lookup_trait_def(trait_def_id);
-        def.flags.set(def.flags.get() | TraitFlags::HAS_DEFAULT_IMPL)
-    }
-
     /// Populates the type context with all the inherent implementations for
     /// the given type if necessary.
     pub fn populate_inherent_implementations_for_type_if_necessary(self,
+                                                                   span: Span,
                                                                    type_id: DefId) {
         if type_id.is_local() {
+            // Make sure coherence of inherent impls ran already.
+            ty::queries::coherent_inherent_impls::force(self, span, LOCAL_CRATE);
             return
         }
 
@@ -2416,16 +2436,12 @@ pub fn populate_implementations_for_trait_if_necessary(self, trait_id: DefId) {
         let _ignore = self.dep_graph.in_ignore();
 
         let def = self.lookup_trait_def(trait_id);
-        if def.flags.get().intersects(TraitFlags::IMPLS_VALID) {
+        if def.flags.get().intersects(TraitFlags::HAS_REMOTE_IMPLS) {
             return;
         }
 
         debug!("populate_implementations_for_trait_if_necessary: searching for {:?}", def);
 
-        if self.sess.cstore.is_defaulted_trait(trait_id) {
-            self.record_trait_has_default_impl(trait_id);
-        }
-
         for impl_def_id in self.sess.cstore.implementations_of_trait(Some(trait_id)) {
             let trait_ref = self.impl_trait_ref(impl_def_id).unwrap();
 
@@ -2434,7 +2450,7 @@ pub fn populate_implementations_for_trait_if_necessary(self, trait_id: DefId) {
             def.record_remote_impl(self, impl_def_id, trait_ref, parent);
         }
 
-        def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID);
+        def.flags.set(def.flags.get() | TraitFlags::HAS_REMOTE_IMPLS);
     }
 
     pub fn closure_kind(self, def_id: DefId) -> ty::ClosureKind {
index 1dc494ca277b309e3ef0bb81f2f19688a9da2609..097b596c5ebb6b6c9e08219168643855605b265a 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use dep_graph::DepNode;
-use hir::def_id::DefId;
+use hir::def_id::{DefId, LOCAL_CRATE};
 use traits::{self, specialization_graph};
 use ty;
 use ty::fast_reject;
@@ -18,6 +18,9 @@
 use hir;
 use util::nodemap::FxHashMap;
 
+use syntax::ast;
+use syntax_pos::DUMMY_SP;
+
 /// A trait's definition with type information.
 pub struct TraitDef {
     pub def_id: DefId,
@@ -60,6 +63,11 @@ pub struct TraitDef {
     /// Various flags
     pub flags: Cell<TraitFlags>,
 
+    /// The number of impls we've added from the local crate.
+    /// When this number matches up the list in the HIR map,
+    /// we're done, and the specialization graph is correct.
+    local_impl_count: Cell<usize>,
+
     /// The ICH of this trait's DefPath, cached here so it doesn't have to be
     /// recomputed all the time.
     pub def_path_hash: u64,
@@ -78,6 +86,7 @@ pub fn new(def_id: DefId,
             nonblanket_impls: RefCell::new(FxHashMap()),
             blanket_impls: RefCell::new(vec![]),
             flags: Cell::new(ty::TraitFlags::NO_TRAIT_FLAGS),
+            local_impl_count: Cell::new(0),
             specialization_graph: RefCell::new(traits::specialization_graph::Graph::new()),
             def_path_hash: def_path_hash,
         }
@@ -155,6 +164,13 @@ pub fn record_local_impl(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
         assert!(impl_def_id.is_local());
         let was_new = self.record_impl(tcx, impl_def_id, impl_trait_ref);
         assert!(was_new);
+
+        self.local_impl_count.set(self.local_impl_count.get() + 1);
+    }
+
+    /// Records a trait-to-implementation mapping.
+    pub fn record_has_default_impl(&self) {
+        self.flags.set(self.flags.get() | TraitFlags::HAS_DEFAULT_IMPL);
     }
 
     /// Records a trait-to-implementation mapping for a non-local impl.
@@ -194,10 +210,51 @@ pub fn ancestors(&'a self, of_impl: DefId) -> specialization_graph::Ancestors<'a
         specialization_graph::ancestors(self, of_impl)
     }
 
+    /// Whether the impl set and specialization graphs are complete.
+    pub fn is_complete(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
+        tcx.populate_implementations_for_trait_if_necessary(self.def_id);
+        ty::queries::coherent_trait::try_get(tcx, DUMMY_SP, (LOCAL_CRATE, self.def_id)).is_ok()
+    }
+
+    /// If any local impls haven't been added yet, returns
+    /// Some(list of local impls for this trait).
+    fn missing_local_impls(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
+                           -> Option<&'gcx [ast::NodeId]> {
+        if self.flags.get().intersects(TraitFlags::HAS_LOCAL_IMPLS) {
+            return None;
+        }
+
+        if self.is_complete(tcx) {
+            self.flags.set(self.flags.get() | TraitFlags::HAS_LOCAL_IMPLS);
+            return None;
+        }
+
+        let impls = tcx.hir.trait_impls(self.def_id);
+        assert!(self.local_impl_count.get() <= impls.len());
+        if self.local_impl_count.get() == impls.len() {
+            self.flags.set(self.flags.get() | TraitFlags::HAS_LOCAL_IMPLS);
+            return None;
+        }
+
+        Some(impls)
+    }
+
     pub fn for_each_impl<F: FnMut(DefId)>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, mut f: F) {
         self.read_trait_impls(tcx);
         tcx.populate_implementations_for_trait_if_necessary(self.def_id);
 
+        let local_impls = self.missing_local_impls(tcx);
+        if let Some(impls) = local_impls {
+            for &id in impls {
+                f(tcx.hir.local_def_id(id));
+            }
+        }
+        let mut f = |def_id: DefId| {
+            if !(local_impls.is_some() && def_id.is_local()) {
+                f(def_id);
+            }
+        };
+
         for &impl_def_id in self.blanket_impls.borrow().iter() {
             f(impl_def_id);
         }
@@ -217,9 +274,20 @@ pub fn for_each_relevant_impl<F: FnMut(DefId)>(&self,
                                                    mut f: F)
     {
         self.read_trait_impls(tcx);
-
         tcx.populate_implementations_for_trait_if_necessary(self.def_id);
 
+        let local_impls = self.missing_local_impls(tcx);
+        if let Some(impls) = local_impls {
+            for &id in impls {
+                f(tcx.hir.local_def_id(id));
+            }
+        }
+        let mut f = |def_id: DefId| {
+            if !(local_impls.is_some() && def_id.is_local()) {
+                f(def_id);
+            }
+        };
+
         for &impl_def_id in self.blanket_impls.borrow().iter() {
             f(impl_def_id);
         }
@@ -258,6 +326,7 @@ pub fn for_each_relevant_impl<F: FnMut(DefId)>(&self,
         const HAS_DEFAULT_IMPL      = 1 << 0,
         const IS_OBJECT_SAFE        = 1 << 1,
         const OBJECT_SAFETY_VALID   = 1 << 2,
-        const IMPLS_VALID           = 1 << 3,
+        const HAS_REMOTE_IMPLS      = 1 << 3,
+        const HAS_LOCAL_IMPLS       = 1 << 4,
     }
 }
index d1c22651a9e008d791dcc02bb65f223c07166209..64480e510229ea66bb8e22775cc05a50b8f1e662 100644 (file)
@@ -149,7 +149,7 @@ pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        self_type: Ty<'tcx>, span: Span)
                                        -> Result<(), CopyImplementationError> {
         // FIXME: (@jroesch) float this code up
-        tcx.infer_ctxt(self.clone(), Reveal::NotSpecializable).enter(|infcx| {
+        tcx.infer_ctxt(self.clone(), Reveal::UserFacing).enter(|infcx| {
             let (adt, substs) = match self_type.sty {
                 ty::TyAdt(adt, substs) => (adt, substs),
                 _ => return Err(CopyImplementationError::NotAnAdt)
@@ -171,7 +171,7 @@ pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 }
             }
 
-            if adt.has_dtor() {
+            if adt.has_dtor(tcx) {
                 return Err(CopyImplementationError::HasDestructor);
             }
 
@@ -353,7 +353,7 @@ pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
     /// (This allows programs to make cyclic structures without
     /// resorting to unasfe means; see RFCs 769 and 1238).
     pub fn is_adt_dtorck(self, adt: &ty::AdtDef) -> bool {
-        let dtor_method = match adt.destructor() {
+        let dtor_method = match adt.destructor(self) {
             Some(dtor) => dtor,
             None => return false
         };
@@ -524,7 +524,7 @@ fn impls_bound(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
         }
         let result =
-            tcx.infer_ctxt(param_env.clone(), Reveal::ExactMatch)
+            tcx.infer_ctxt(param_env.clone(), Reveal::UserFacing)
             .enter(|infcx| {
                 traits::type_known_to_meet_bound(&infcx, self, def_id, span)
             });
index e3dec97472a481af97aa6b6e87b4ffe1495e16d2..3ce31882b86c4583ec1c4f5a7d5a5f05dad26aa8 100644 (file)
@@ -783,7 +783,7 @@ fn check_if_assigned_path_is_moved(&self,
             }
             LpExtend(ref lp_base, _, LpInterior(_, InteriorField(_))) => {
                 match lp_base.to_type().sty {
-                    ty::TyAdt(def, _) if def.has_dtor() => {
+                    ty::TyAdt(def, _) if def.has_dtor(self.tcx()) => {
                         // In the case where the owner implements drop, then
                         // the path must be initialized to prevent a case of
                         // partial reinitialization
index c33ced52e2bd6aee181faebf9e37f6acd99fa0a9..0577ba7f45a938883d3767c8b697acd94913dca3 100644 (file)
@@ -177,7 +177,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         Categorization::Interior(ref b, mc::InteriorElement(Kind::Pattern, _)) => {
             match b.ty.sty {
                 ty::TyAdt(def, _) => {
-                    if def.has_dtor() {
+                    if def.has_dtor(bccx.tcx) {
                         Some(cmt.clone())
                     } else {
                         check_and_get_illegal_move_origin(bccx, b)
index 47f8d978704f4710145305f1c40d9b74b4ea8b8b..3678c2e55c1fdb17d0d175796e282f167f98f861 100644 (file)
@@ -150,7 +150,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         Categorization::Downcast(ref b, _) |
         Categorization::Interior(ref b, mc::InteriorField(_)) => {
             match b.ty.sty {
-                ty::TyAdt(def, _) if def.has_dtor() => {
+                ty::TyAdt(def, _) if def.has_dtor(bccx.tcx) => {
                     let mut err = struct_span_err!(bccx, move_from.span, E0509,
                                                    "cannot move out of type `{}`, \
                                                    which implements the `Drop` trait",
index f8c0044774a010eb2cadd0e604802105b12fd64f..13f898219bc12dfba9c9d456cb34c7d15a5b51e5 100644 (file)
@@ -898,7 +898,7 @@ fn must_complete_drop<'a>(&self, c: &DropCtxt<'a, 'tcx>) -> bool {
 
         match ty.sty {
             ty::TyAdt(def, _) => {
-                if def.has_dtor() && !def.is_box() {
+                if def.has_dtor(self.tcx) && !def.is_box() {
                     self.tcx.sess.span_warn(
                         c.source_info.span,
                         &format!("dataflow bug??? moving out of type with dtor {:?}",
index 35ace6628cfed4d7f244443a4feda936e20555c3..8d866676dbd1875dc3838da2e0491e4db397ae00 100644 (file)
@@ -289,7 +289,7 @@ fn move_path_for_projection(&mut self,
             // error: can't move out of borrowed content
             ty::TyRef(..) | ty::TyRawPtr(..) => return Err(MovePathError::IllegalMove),
             // error: can't move out of struct with destructor
-            ty::TyAdt(adt, _) if adt.has_dtor() && !adt.is_box() =>
+            ty::TyAdt(adt, _) if adt.has_dtor(self.tcx) && !adt.is_box() =>
                 return Err(MovePathError::IllegalMove),
             // move out of union - always move the entire union
             ty::TyAdt(adt, _) if adt.is_union() =>
index d9283e7037f50f2dc851af5ec9cb53737709f837..1c9ee335699ae13439d689cbb1af77e826b72b69 100644 (file)
@@ -248,7 +248,7 @@ fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
                    lv, ty);
             true
         }
-        ty::TyAdt(def, _) if (def.has_dtor() && !def.is_box()) || def.is_union() => {
+        ty::TyAdt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
             debug!("lvalue_contents_drop_state_cannot_differ lv: {:?} ty: {:?} Drop => true",
                    lv, ty);
             true
index 9b30946c0bebbc1d834cd9cdd045352dbd76be28..db5df72267df7919622723fb89e2c9f946d0fe9d 100644 (file)
@@ -516,7 +516,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
 ///
 /// FIXME: this should be done by borrowck.
 fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
-    cx.tcx.infer_ctxt((cx.tables, cx.param_env.clone()), Reveal::NotSpecializable).enter(|infcx| {
+    cx.tcx.infer_ctxt((cx.tables, cx.param_env.clone()), Reveal::UserFacing).enter(|infcx| {
         let mut checker = MutationChecker {
             cx: cx,
         };
index eadb49a0731a4832ffbd7b87978425c067ab8f58..0ab2255aab0ff8b2d66a7f1fc305796339f681b9 100644 (file)
@@ -922,7 +922,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(
            trait_ref);
 
     tcx.populate_implementations_for_trait_if_necessary(trait_id);
-    tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| {
+    tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
         let mut selcx = traits::SelectionContext::new(&infcx);
         let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
                                                  trait_ref.to_poly_trait_predicate());
index 36ba1e7f95bd8f8679245dbee54b2608766bf744..9568cc3d6de0e35c8cc00fce917dc91b73e344c0 100644 (file)
@@ -151,7 +151,7 @@ fn test_env<F>(source_string: &str,
                              index,
                              "test_crate",
                              |tcx| {
-        tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| {
+        tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
 
             body(Env { infcx: &infcx });
             let free_regions = FreeRegionMap::new();
index 486900fc2fed5a21adb731d9e416f1294c4d5d00..150a2c39db7a827e9796d5dca3edb992b88e39d5 100644 (file)
@@ -1167,6 +1167,9 @@ pub fn hash_crate_root_module(&mut self, krate: &'tcx Crate) {
             trait_items: _,
             impl_items: _,
             bodies: _,
+
+            trait_impls: _,
+            trait_default_impl: _,
         } = *krate;
 
         visit::Visitor::visit_mod(self, module, span, ast::CRATE_NODE_ID);
index 75269f58ed62df7460dbe336e8c6395c7e78b098..b3f09c28277ada98725c0c6729d148ee23499fdf 100644 (file)
@@ -523,7 +523,7 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
             }
             _ => return,
         };
-        if def.has_dtor() {
+        if def.has_dtor(cx.tcx) {
             return;
         }
         let parameter_environment = cx.tcx.empty_parameter_environment();
@@ -882,7 +882,7 @@ fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     let node_id = tcx.hir.as_local_node_id(method.def_id).unwrap();
 
                     let param_env = ty::ParameterEnvironment::for_item(tcx, node_id);
-                    tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| {
+                    tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
                         let mut selcx = traits::SelectionContext::new(&infcx);
                         match selcx.select(&obligation) {
                             // The method comes from a `T: Trait` bound.
index 1b19e79d489d6697106e1afb2a2e77f8ed40224e..443e75e63d3ddc9b514ea64009a394544fcccb64 100644 (file)
@@ -203,12 +203,6 @@ fn is_const_fn(&self, did: DefId) -> bool
         self.get_crate_data(did.krate).is_const_fn(did.index)
     }
 
-    fn is_defaulted_trait(&self, trait_def_id: DefId) -> bool
-    {
-        self.dep_graph.read(DepNode::MetaData(trait_def_id));
-        self.get_crate_data(trait_def_id.krate).is_defaulted_trait(trait_def_id.index)
-    }
-
     fn is_default_impl(&self, impl_did: DefId) -> bool {
         self.dep_graph.read(DepNode::MetaData(impl_did));
         self.get_crate_data(impl_did.krate).is_default_impl(impl_did.index)
index e81d752fde047a47fddf6c52a1ed6709ae625382..1627b22cd5fa18a5eb68e37ac67bdbec96fef3d1 100644 (file)
@@ -501,10 +501,16 @@ pub fn get_trait_def(&self,
             _ => bug!(),
         };
 
-        ty::TraitDef::new(self.local_def_id(item_id),
-                          data.unsafety,
-                          data.paren_sugar,
-                          self.def_path(item_id).deterministic_hash(tcx))
+        let def = ty::TraitDef::new(self.local_def_id(item_id),
+                                    data.unsafety,
+                                    data.paren_sugar,
+                                    self.def_path(item_id).deterministic_hash(tcx));
+
+        if data.has_default_impl {
+            def.record_has_default_impl();
+        }
+
+        def
     }
 
     fn get_variant(&self,
@@ -1027,13 +1033,6 @@ pub fn is_dllimport_foreign_item(&self, id: DefIndex) -> bool {
         self.dllimport_foreign_items.contains(&id)
     }
 
-    pub fn is_defaulted_trait(&self, trait_id: DefIndex) -> bool {
-        match self.entry(trait_id).kind {
-            EntryKind::Trait(data) => data.decode(self).has_default_impl,
-            _ => bug!(),
-        }
-    }
-
     pub fn is_default_impl(&self, impl_id: DefIndex) -> bool {
         match self.entry(impl_id).kind {
             EntryKind::DefaultImpl(_) => true,
index 34b701a3a9dd5acb79be37f3be3a75076b17c3d4..0d7be189f883aa57f5f2cf30883aece26f9adfe4 100644 (file)
@@ -96,7 +96,7 @@ fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
     };
 
     let src = MirSource::from_node(tcx, id);
-    tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| {
+    tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
         let cx = Cx::new(&infcx, src);
         let mut mir = if let MirSource::Fn(id) = src {
             // fetch the fully liberated fn signature (that is, all bound
index 4f80e21af64e44bb8db0f841cd9454206a421c23..9f38564d1e2f34489bfc4479952c0581c9a42529 100644 (file)
@@ -758,7 +758,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
 
             Rvalue::Aggregate(ref kind, _) => {
                 if let AggregateKind::Adt(def, ..) = *kind {
-                    if def.has_dtor() {
+                    if def.has_dtor(self.tcx) {
                         self.add(Qualif::NEEDS_DROP);
                         self.deny_drop();
                     }
@@ -1042,7 +1042,7 @@ fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Statics must be Sync.
         if mode == Mode::Static {
             let ty = mir.return_ty;
-            tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| {
+            tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
                 let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic);
                 let mut fulfillment_cx = traits::FulfillmentContext::new();
                 fulfillment_cx.register_bound(&infcx, ty,
index 40485e4b66d773cfbe98a1d75057cb04a35f1bc4..af4a4a53905eb05ffb265d9ee4fc1e8676b90098 100644 (file)
@@ -699,7 +699,7 @@ fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             return;
         }
         let param_env = ty::ParameterEnvironment::for_item(tcx, src.item_id());
-        tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| {
+        tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
             let mut checker = TypeChecker::new(&infcx, src.item_id());
             {
                 let mut verifier = TypeVerifier::new(&mut checker, mir);
index e3772a09968ec467bb0b7f38ecd4ea112a9f50a2..e3a77a9359980cdd18f6cb0e6e1fbf6b18850c4a 100644 (file)
@@ -138,7 +138,7 @@ fn visit_nested_body(&mut self, body_id: hir::BodyId) {
             self.check_const_eval(&body.value);
         }
 
-        let outer_penv = self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| {
+        let outer_penv = self.tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
             let param_env = infcx.parameter_environment.clone();
             let outer_penv = mem::replace(&mut self.param_env, param_env);
             euv::ExprUseVisitor::new(self, &infcx).consume_body(body);
@@ -274,7 +274,7 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
 /// instead of producing errors.
 fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node_ty: Ty<'tcx>) {
     match node_ty.sty {
-        ty::TyAdt(def, _) if def.has_dtor() => {
+        ty::TyAdt(def, _) if def.has_dtor(v.tcx) => {
             v.promotable = false;
         }
         _ => {}
index 9de5ff541a52c98d6bfb799493644aacfca67028..c367e71fcd24619417dd41e20e2077739503b535 100644 (file)
@@ -38,7 +38,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
 
     fn visit_nested_body(&mut self, body_id: hir::BodyId) {
         let body = self.tcx.hir.body(body_id);
-        self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| {
+        self.tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
             let mut delegate = RvalueContextDelegate {
                 tcx: infcx.tcx,
                 param_env: &infcx.parameter_environment
index 14ef48a9027030b209f6630f6351366604d1428e..b12c1220b2b4de797a9c9f4be568a02839fd35eb 100644 (file)
@@ -754,7 +754,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
     // If the type implements Drop, also add a translation item for the
     // monomorphized Drop::drop() implementation.
     let destructor_did = match ty.sty {
-        ty::TyAdt(def, _) => def.destructor(),
+        ty::TyAdt(def, _) => def.destructor(scx.tcx()),
         _ => None
     };
 
index 58e0a9e589f3369b70be642435d2088f85237195..32fc3d5af24451f21d97a2a39d6c176329f1dd26 100644 (file)
@@ -237,7 +237,7 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
             bcx.call(dtor, &[ptr.llval], None);
             bcx
         }
-        ty::TyAdt(def, ..) if def.has_dtor() && !skip_dtor => {
+        ty::TyAdt(def, ..) if def.has_dtor(bcx.tcx()) && !skip_dtor => {
             let shallow_drop = def.is_union();
             let tcx = bcx.tcx();
 
@@ -265,7 +265,7 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
                 traits::VtableImpl(data) => data,
                 _ => bug!("dtor for {:?} is not an impl???", t)
             };
-            let dtor_did = def.destructor().unwrap();
+            let dtor_did = def.destructor(tcx).unwrap();
             let callee = Callee::def(bcx.ccx, dtor_did, vtbl.substs);
             let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
             let llret;
index 06cf653e29368f021cd77d3f4e02e9c347444e9c..0e9abaf1cf955e86c272e91acc882fcccbfcedb6 100644 (file)
@@ -224,7 +224,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                                trait_param_env,
                                                                normalize_cause.clone());
 
-    tcx.infer_ctxt(trait_param_env, Reveal::NotSpecializable).enter(|infcx| {
+    tcx.infer_ctxt(trait_param_env, Reveal::UserFacing).enter(|infcx| {
         let inh = Inherited::new(infcx);
         let infcx = &inh.infcx;
         let fulfillment_cx = &inh.fulfillment_cx;
@@ -730,7 +730,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                     impl_trait_ref: ty::TraitRef<'tcx>) {
     debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
 
-    tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| {
+    tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
         let mut fulfillment_cx = traits::FulfillmentContext::new();
 
         // The below is for the most part highly similar to the procedure
index 385ea7d52e1cef51ab839b3e6ff855368e507795..07cc35ed67bbb76ab86bf82bd3e446544cd0f7e1 100644 (file)
@@ -80,7 +80,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
     // check that the impl type can be made to match the trait type.
 
     let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id);
-    tcx.infer_ctxt(impl_param_env, Reveal::NotSpecializable).enter(|infcx| {
+    tcx.infer_ctxt(impl_param_env, Reveal::UserFacing).enter(|infcx| {
         let tcx = infcx.tcx;
         let mut fulfillment_cx = traits::FulfillmentContext::new();
 
@@ -554,7 +554,7 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 
             // Find the `impl<..> Drop for _` to inspect any
             // attributes attached to the impl's generics.
-            let dtor_method = adt_def.destructor()
+            let dtor_method = adt_def.destructor(tcx)
                 .expect("dtorck type without destructor impossible");
             let method = tcx.associated_item(dtor_method);
             let impl_def_id = method.container.id();
index b6071d01ff1cf682090f1f8e934cea5bd1e6b8af..dfa7ababca0bbd8b97f143cbc9efcdca24d44ec6 100644 (file)
@@ -481,7 +481,7 @@ fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option<DefId>) {
     fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
         // Read the inherent implementation candidates for this type from the
         // metadata if necessary.
-        self.tcx.populate_inherent_implementations_for_type_if_necessary(def_id);
+        self.tcx.populate_inherent_implementations_for_type_if_necessary(self.span, def_id);
 
         if let Some(impl_infos) = self.tcx.maps.inherent_impls.borrow().get(&def_id) {
             for &impl_def_id in impl_infos.iter() {
index 68d8280d397d7aadb706759fa86cf30ae583206b..aa1fc0f8579daecfe02b523db9160ceea5bcaf51 100644 (file)
@@ -477,7 +477,7 @@ pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId)
         let tables = ty::TypeckTables::empty();
         let param_env = ParameterEnvironment::for_item(tcx, id);
         InheritedBuilder {
-            infcx: tcx.infer_ctxt((tables, param_env), Reveal::NotSpecializable)
+            infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing)
         }
     }
 }
index bfe8abb201caea401f9618d7280071cfcde8e083..3cdf9fc93ae600617a4c84aa935dfdb1adcaec07 100644 (file)
 use rustc::hir::map as hir_map;
 use rustc::hir::{self, ItemImpl};
 
-pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    check_trait(tcx, tcx.lang_items.drop_trait(), visit_implementation_of_drop);
-    check_trait(tcx, tcx.lang_items.copy_trait(), visit_implementation_of_copy);
-    check_trait(
-        tcx,
-        tcx.lang_items.coerce_unsized_trait(),
-        visit_implementation_of_coerce_unsized);
+pub fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId) {
+    Checker { tcx, trait_def_id }
+        .check(tcx.lang_items.drop_trait(), visit_implementation_of_drop)
+        .check(tcx.lang_items.copy_trait(), visit_implementation_of_copy)
+        .check(tcx.lang_items.coerce_unsized_trait(),
+               visit_implementation_of_coerce_unsized);
 }
 
-fn check_trait<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                            trait_def_id: Option<DefId>,
-                            mut f: F)
-    where F: FnMut(TyCtxt<'a, 'tcx, 'tcx>, DefId, DefId)
-{
-    if let Some(trait_def_id) = trait_def_id {
-        let mut impls = vec![];
-        tcx.lookup_trait_def(trait_def_id).for_each_impl(tcx, |did| {
-            impls.push(did);
-        });
-        impls.sort();
-        for impl_def_id in impls {
-            f(tcx, trait_def_id, impl_def_id);
+struct Checker<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    trait_def_id: DefId
+}
+
+impl<'a, 'tcx> Checker<'a, 'tcx> {
+    fn check<F>(&self, trait_def_id: Option<DefId>, mut f: F) -> &Self
+        where F: FnMut(TyCtxt<'a, 'tcx, 'tcx>, DefId, DefId)
+    {
+        if Some(self.trait_def_id) == trait_def_id {
+            for &impl_id in self.tcx.hir.trait_impls(self.trait_def_id) {
+                let impl_def_id = self.tcx.hir.local_def_id(impl_id);
+                f(self.tcx, self.trait_def_id, impl_def_id);
+            }
         }
+        self
     }
 }
 
 fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                           _drop_did: DefId,
                                           impl_did: DefId) {
-    let items = tcx.associated_item_def_ids(impl_did);
-    if items.is_empty() {
-        // We'll error out later. For now, just don't ICE.
-        return;
-    }
-    let method_def_id = items[0];
-
-    let self_type = tcx.item_type(impl_did);
-    match self_type.sty {
-        ty::TyAdt(type_def, _) => {
-            type_def.set_destructor(method_def_id);
-        }
+    match tcx.item_type(impl_did).sty {
+        ty::TyAdt(..) => {}
         _ => {
             // Destructors only work on nominal types.
             if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_did) {
@@ -205,7 +196,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            source,
            target);
 
-    tcx.infer_ctxt(param_env, Reveal::ExactMatch).enter(|infcx| {
+    tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
         let cause = ObligationCause::misc(span, impl_node_id);
         let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
                            mt_b: ty::TypeAndMut<'tcx>,
diff --git a/src/librustc_typeck/coherence/inherent.rs b/src/librustc_typeck/coherence/inherent.rs
new file mode 100644 (file)
index 0000000..e3b4ba9
--- /dev/null
@@ -0,0 +1,356 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::dep_graph::DepNode;
+use rustc::hir::def_id::DefId;
+use rustc::hir;
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::lint;
+use rustc::traits::{self, Reveal};
+use rustc::ty::{self, TyCtxt};
+
+use syntax::ast;
+use syntax_pos::Span;
+
+struct InherentCollect<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>
+}
+
+impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
+    fn visit_item(&mut self, item: &hir::Item) {
+        let (unsafety, ty) = match item.node {
+            hir::ItemImpl(unsafety, .., None, ref ty, _) => (unsafety, ty),
+            _ => return
+        };
+
+        match unsafety {
+            hir::Unsafety::Normal => {
+                // OK
+            }
+            hir::Unsafety::Unsafe => {
+                span_err!(self.tcx.sess,
+                          item.span,
+                          E0197,
+                          "inherent impls cannot be declared as unsafe");
+            }
+        }
+
+        let def_id = self.tcx.hir.local_def_id(item.id);
+        let self_ty = self.tcx.item_type(def_id);
+        match self_ty.sty {
+            ty::TyAdt(def, _) => {
+                self.check_def_id(item, def.did);
+            }
+            ty::TyDynamic(ref data, ..) if data.principal().is_some() => {
+                self.check_def_id(item, data.principal().unwrap().def_id());
+            }
+            ty::TyChar => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.char_impl(),
+                                          "char",
+                                          "char",
+                                          item.span);
+            }
+            ty::TyStr => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.str_impl(),
+                                          "str",
+                                          "str",
+                                          item.span);
+            }
+            ty::TySlice(_) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.slice_impl(),
+                                          "slice",
+                                          "[T]",
+                                          item.span);
+            }
+            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.const_ptr_impl(),
+                                          "const_ptr",
+                                          "*const T",
+                                          item.span);
+            }
+            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.mut_ptr_impl(),
+                                          "mut_ptr",
+                                          "*mut T",
+                                          item.span);
+            }
+            ty::TyInt(ast::IntTy::I8) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.i8_impl(),
+                                          "i8",
+                                          "i8",
+                                          item.span);
+            }
+            ty::TyInt(ast::IntTy::I16) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.i16_impl(),
+                                          "i16",
+                                          "i16",
+                                          item.span);
+            }
+            ty::TyInt(ast::IntTy::I32) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.i32_impl(),
+                                          "i32",
+                                          "i32",
+                                          item.span);
+            }
+            ty::TyInt(ast::IntTy::I64) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.i64_impl(),
+                                          "i64",
+                                          "i64",
+                                          item.span);
+            }
+            ty::TyInt(ast::IntTy::I128) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.i128_impl(),
+                                          "i128",
+                                          "i128",
+                                          item.span);
+            }
+            ty::TyInt(ast::IntTy::Is) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.isize_impl(),
+                                          "isize",
+                                          "isize",
+                                          item.span);
+            }
+            ty::TyUint(ast::UintTy::U8) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.u8_impl(),
+                                          "u8",
+                                          "u8",
+                                          item.span);
+            }
+            ty::TyUint(ast::UintTy::U16) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.u16_impl(),
+                                          "u16",
+                                          "u16",
+                                          item.span);
+            }
+            ty::TyUint(ast::UintTy::U32) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.u32_impl(),
+                                          "u32",
+                                          "u32",
+                                          item.span);
+            }
+            ty::TyUint(ast::UintTy::U64) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.u64_impl(),
+                                          "u64",
+                                          "u64",
+                                          item.span);
+            }
+            ty::TyUint(ast::UintTy::U128) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.u128_impl(),
+                                          "u128",
+                                          "u128",
+                                          item.span);
+            }
+            ty::TyUint(ast::UintTy::Us) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.usize_impl(),
+                                          "usize",
+                                          "usize",
+                                          item.span);
+            }
+            ty::TyFloat(ast::FloatTy::F32) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.f32_impl(),
+                                          "f32",
+                                          "f32",
+                                          item.span);
+            }
+            ty::TyFloat(ast::FloatTy::F64) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.f64_impl(),
+                                          "f64",
+                                          "f64",
+                                          item.span);
+            }
+            ty::TyError => {
+                return;
+            }
+            _ => {
+                struct_span_err!(self.tcx.sess,
+                                 ty.span,
+                                 E0118,
+                                 "no base type found for inherent implementation")
+                    .span_label(ty.span, &format!("impl requires a base type"))
+                    .note(&format!("either implement a trait on it or create a newtype \
+                                    to wrap it instead"))
+                    .emit();
+                return;
+            }
+        }
+    }
+
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    }
+}
+
+impl<'a, 'tcx> InherentCollect<'a, 'tcx> {
+    fn check_def_id(&self, item: &hir::Item, def_id: DefId) {
+        if def_id.is_local() {
+            // Add the implementation to the mapping from implementation to base
+            // type def ID, if there is a base type for this implementation and
+            // the implementation does not have any associated traits.
+            let impl_def_id = self.tcx.hir.local_def_id(item.id);
+
+            // Subtle: it'd be better to collect these into a local map
+            // and then write the vector only once all items are known,
+            // but that leads to degenerate dep-graphs. The problem is
+            // that the write of that big vector winds up having reads
+            // from *all* impls in the krate, since we've lost the
+            // precision basically.  This would be ok in the firewall
+            // model so once we've made progess towards that we can modify
+            // the strategy here. In the meantime, using `push` is ok
+            // because we are doing this as a pre-pass before anyone
+            // actually reads from `inherent_impls` -- and we know this is
+            // true beacuse we hold the refcell lock.
+            self.tcx.maps.inherent_impls.borrow_mut().push(def_id, impl_def_id);
+        } else {
+            struct_span_err!(self.tcx.sess,
+                             item.span,
+                             E0116,
+                             "cannot define inherent `impl` for a type outside of the crate \
+                              where the type is defined")
+                .span_label(item.span,
+                            &format!("impl for type defined outside of crate."))
+                .note("define and implement a trait or new type instead")
+                .emit();
+        }
+    }
+
+    fn check_primitive_impl(&self,
+                            impl_def_id: DefId,
+                            lang_def_id: Option<DefId>,
+                            lang: &str,
+                            ty: &str,
+                            span: Span) {
+        match lang_def_id {
+            Some(lang_def_id) if lang_def_id == impl_def_id => {
+                // OK
+            }
+            _ => {
+                struct_span_err!(self.tcx.sess,
+                                 span,
+                                 E0390,
+                                 "only a single inherent implementation marked with `#[lang = \
+                                  \"{}\"]` is allowed for the `{}` primitive",
+                                 lang,
+                                 ty)
+                    .span_help(span, "consider using a trait to implement these methods")
+                    .emit();
+            }
+        }
+    }
+}
+
+struct InherentOverlapChecker<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>
+}
+
+impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
+    fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId) {
+        #[derive(Copy, Clone, PartialEq)]
+        enum Namespace {
+            Type,
+            Value,
+        }
+
+        let name_and_namespace = |def_id| {
+            let item = self.tcx.associated_item(def_id);
+            (item.name, match item.kind {
+                ty::AssociatedKind::Type => Namespace::Type,
+                ty::AssociatedKind::Const |
+                ty::AssociatedKind::Method => Namespace::Value,
+            })
+        };
+
+        let impl_items1 = self.tcx.associated_item_def_ids(impl1);
+        let impl_items2 = self.tcx.associated_item_def_ids(impl2);
+
+        for &item1 in &impl_items1[..] {
+            let (name, namespace) = name_and_namespace(item1);
+
+            for &item2 in &impl_items2[..] {
+                if (name, namespace) == name_and_namespace(item2) {
+                    let msg = format!("duplicate definitions with name `{}`", name);
+                    let node_id = self.tcx.hir.as_local_node_id(item1).unwrap();
+                    self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS,
+                                           node_id,
+                                           self.tcx.span_of_impl(item1).unwrap(),
+                                           msg);
+                }
+            }
+        }
+    }
+
+    fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
+        let _task = self.tcx.dep_graph.in_task(DepNode::CoherenceOverlapInherentCheck(ty_def_id));
+
+        let inherent_impls = self.tcx.maps.inherent_impls.borrow();
+        let impls = match inherent_impls.get(&ty_def_id) {
+            Some(impls) => impls,
+            None => return,
+        };
+
+        for (i, &impl1_def_id) in impls.iter().enumerate() {
+            for &impl2_def_id in &impls[(i + 1)..] {
+                self.tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
+                    if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() {
+                        self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id)
+                    }
+                });
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentOverlapChecker<'a, 'tcx> {
+    fn visit_item(&mut self, item: &'v hir::Item) {
+        match item.node {
+            hir::ItemEnum(..) |
+            hir::ItemStruct(..) |
+            hir::ItemTrait(..) |
+            hir::ItemUnion(..) => {
+                let type_def_id = self.tcx.hir.local_def_id(item.id);
+                self.check_for_overlapping_inherent_impls(type_def_id);
+            }
+            _ => {}
+        }
+    }
+
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    }
+}
+
+pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl,
+                                      &mut InherentCollect { tcx });
+    tcx.visit_all_item_likes_in_krate(DepNode::CoherenceOverlapCheckSpecial,
+                                      &mut InherentOverlapChecker { tcx });
+}
index ed5ca79a706619ab0dd8f8f6c76fd9a12d85087a..9ecf42daeaae52021fd7f60f0a4dfd91de90f3d7 100644 (file)
 // done by the orphan and overlap modules. Then we build up various
 // mappings. That mapping code resides here.
 
-use dep_graph::DepTrackingMap;
-use hir::def_id::DefId;
-use rustc::ty::{self, maps, TyCtxt, TypeFoldable};
-use rustc::ty::{Ty, TyBool, TyChar, TyError};
-use rustc::ty::{TyParam, TyRawPtr};
-use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple};
-use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
-use rustc::ty::{TyUint, TyClosure, TyFnDef, TyFnPtr};
-use rustc::ty::{TyProjection, TyAnon};
-use syntax_pos::Span;
+use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc::ty::{self, TyCtxt, TypeFoldable};
+use rustc::ty::maps::Providers;
 use rustc::dep_graph::DepNode;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::{Item, ItemImpl};
-use rustc::hir;
-use std::cell::RefMut;
+
+use syntax::ast;
+use syntax_pos::DUMMY_SP;
 
 mod builtin;
+mod inherent;
 mod orphan;
 mod overlap;
 mod unsafety;
 
-struct CoherenceCollect<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    inherent_impls: RefMut<'a, DepTrackingMap<maps::queries::inherent_impls<'tcx>>>,
-}
-
-impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCollect<'a, 'tcx> {
-    fn visit_item(&mut self, item: &Item) {
-        if let ItemImpl(..) = item.node {
-            self.check_implementation(item)
-        }
-    }
-
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
-    }
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
-    }
-}
-
-impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> {
-    fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-        let inherent_impls = tcx.maps.inherent_impls.borrow_mut();
-        let mut this = &mut CoherenceCollect { tcx, inherent_impls };
-
-        // Check implementations and traits. This populates the tables
-        // containing the inherent methods and extension methods. It also
-        // builds up the trait inheritance table.
-        tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl, this);
-    }
+fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
+    let impl_def_id = tcx.hir.local_def_id(node_id);
 
-    // Returns the def ID of the base type, if there is one.
-    fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
-        match ty.sty {
-            TyAdt(def, _) => Some(def.did),
+    // If there are no traits, then this implementation must have a
+    // base type.
 
-            TyDynamic(ref t, ..) => t.principal().map(|p| p.def_id()),
+    if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) {
+        debug!("(checking implementation) adding impl for trait '{:?}', item '{}'",
+                trait_ref,
+                tcx.item_path_str(impl_def_id));
 
-            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyStr | TyArray(..) |
-            TySlice(..) | TyFnDef(..) | TyFnPtr(_) | TyTuple(..) | TyParam(..) | TyError |
-            TyNever | TyRawPtr(_) | TyRef(..) | TyProjection(..) => None,
-
-            TyInfer(..) | TyClosure(..) | TyAnon(..) => {
-                // `ty` comes from a user declaration so we should only expect types
-                // that the user can type
-                span_bug!(span,
-                          "coherence encountered unexpected type searching for base type: {}",
-                          ty);
-            }
+        // Skip impls where one of the self type is an error type.
+        // This occurs with e.g. resolve failures (#30589).
+        if trait_ref.references_error() {
+            return;
         }
-    }
 
-    fn check_implementation(&mut self, item: &Item) {
-        let tcx = self.tcx;
-        let impl_did = tcx.hir.local_def_id(item.id);
-        let self_type = tcx.item_type(impl_did);
-
-        // If there are no traits, then this implementation must have a
-        // base type.
-
-        if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
-            debug!("(checking implementation) adding impl for trait '{:?}', item '{}'",
-                   trait_ref,
-                   item.name);
-
-            // Skip impls where one of the self type is an error type.
-            // This occurs with e.g. resolve failures (#30589).
-            if trait_ref.references_error() {
-                return;
-            }
-
-            enforce_trait_manually_implementable(self.tcx, item.span, trait_ref.def_id);
-            self.add_trait_impl(trait_ref, impl_did);
-        } else {
-            // Skip inherent impls where the self type is an error
-            // type. This occurs with e.g. resolve failures (#30589).
-            if self_type.references_error() {
-                return;
-            }
-
-            // Add the implementation to the mapping from implementation to base
-            // type def ID, if there is a base type for this implementation and
-            // the implementation does not have any associated traits.
-            if let Some(base_def_id) = self.get_base_type_def_id(item.span, self_type) {
-                self.add_inherent_impl(base_def_id, impl_did);
-            }
-        }
+        enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id);
+        let trait_def = tcx.lookup_trait_def(trait_ref.def_id);
+        trait_def.record_local_impl(tcx, impl_def_id, trait_ref);
     }
+}
+
+fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_def_id: DefId) {
+    let did = Some(trait_def_id);
+    let li = &tcx.lang_items;
 
-    fn add_inherent_impl(&mut self, base_def_id: DefId, impl_def_id: DefId) {
-        // Subtle: it'd be better to collect these into a local map
-        // and then write the vector only once all items are known,
-        // but that leads to degenerate dep-graphs. The problem is
-        // that the write of that big vector winds up having reads
-        // from *all* impls in the krate, since we've lost the
-        // precision basically.  This would be ok in the firewall
-        // model so once we've made progess towards that we can modify
-        // the strategy here. In the meantime, using `push` is ok
-        // because we are doing this as a pre-pass before anyone
-        // actually reads from `inherent_impls` -- and we know this is
-        // true beacuse we hold the refcell lock.
-        self.inherent_impls.push(base_def_id, impl_def_id);
+    // Disallow *all* explicit impls of `Sized` and `Unsize` for now.
+    if did == li.sized_trait() {
+        let span = tcx.span_of_impl(impl_def_id).unwrap();
+        struct_span_err!(tcx.sess,
+                         span,
+                         E0322,
+                         "explicit impls for the `Sized` trait are not permitted")
+            .span_label(span, &format!("impl of 'Sized' not allowed"))
+            .emit();
+        return;
     }
 
-    fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) {
-        debug!("add_trait_impl: impl_trait_ref={:?} impl_def_id={:?}",
-               impl_trait_ref,
-               impl_def_id);
-        let trait_def = self.tcx.lookup_trait_def(impl_trait_ref.def_id);
-        trait_def.record_local_impl(self.tcx, impl_def_id, impl_trait_ref);
+    if did == li.unsize_trait() {
+        let span = tcx.span_of_impl(impl_def_id).unwrap();
+        span_err!(tcx.sess,
+                  span,
+                  E0328,
+                  "explicit impls for the `Unsize` trait are not permitted");
+        return;
     }
-}
 
-fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: DefId) {
     if tcx.sess.features.borrow().unboxed_closures {
-        // the feature gate allows all of them
+        // the feature gate allows all Fn traits
         return;
     }
-    let did = Some(trait_def_id);
-    let li = &tcx.lang_items;
 
     let trait_name = if did == li.fn_trait() {
         "Fn"
@@ -166,7 +92,7 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def
         return; // everything OK
     };
     let mut err = struct_span_err!(tcx.sess,
-                                   sp,
+                                   tcx.span_of_impl(impl_def_id).unwrap(),
                                    E0183,
                                    "manual implementations of `{}` are experimental",
                                    trait_name);
@@ -175,12 +101,41 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def
     err.emit();
 }
 
-pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    CoherenceCollect::check(tcx);
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
+        coherent_trait,
+        coherent_inherent_impls,
+        ..*providers
+    };
+}
 
+fn coherent_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            (_, def_id): (CrateNum, DefId)) {
+    tcx.populate_implementations_for_trait_if_necessary(def_id);
+
+    let impls = tcx.hir.trait_impls(def_id);
+    for &impl_id in impls {
+        check_impl(tcx, impl_id);
+    }
+    for &impl_id in impls {
+        overlap::check_impl(tcx, impl_id);
+    }
+    builtin::check_trait(tcx, def_id);
+}
+
+fn coherent_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _: CrateNum) {
+    inherent::check(tcx);
+}
+
+pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let _task = tcx.dep_graph.in_task(DepNode::Coherence);
+    for &trait_def_id in tcx.hir.krate().trait_impls.keys() {
+        ty::queries::coherent_trait::get(tcx, DUMMY_SP, (LOCAL_CRATE, trait_def_id));
+    }
+
     unsafety::check(tcx);
     orphan::check(tcx);
-    overlap::check(tcx);
-    builtin::check(tcx);
+    overlap::check_default_impls(tcx);
+
+    ty::queries::coherent_inherent_impls::get(tcx, DUMMY_SP, LOCAL_CRATE);
 }
index 9ef231499df5145c1fc0036624c60f769e9c4f4a..ee361ab6073d4e5c4df5b2029cef9ad10a430da0 100644 (file)
 //! Orphan checker: every impl either implements a trait defined in this
 //! crate or pertains to a type defined in this crate.
 
-use hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::traits;
 use rustc::ty::{self, TyCtxt};
-use syntax::ast;
-use syntax_pos::Span;
 use rustc::dep_graph::DepNode;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir;
@@ -29,46 +26,6 @@ struct OrphanChecker<'cx, 'tcx: 'cx> {
     tcx: TyCtxt<'cx, 'tcx, 'tcx>,
 }
 
-impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
-    fn check_def_id(&self, item: &hir::Item, def_id: DefId) {
-        if def_id.krate != LOCAL_CRATE {
-            struct_span_err!(self.tcx.sess,
-                             item.span,
-                             E0116,
-                             "cannot define inherent `impl` for a type outside of the crate \
-                              where the type is defined")
-                .span_label(item.span,
-                            &format!("impl for type defined outside of crate."))
-                .note("define and implement a trait or new type instead")
-                .emit();
-        }
-    }
-
-    fn check_primitive_impl(&self,
-                            impl_def_id: DefId,
-                            lang_def_id: Option<DefId>,
-                            lang: &str,
-                            ty: &str,
-                            span: Span) {
-        match lang_def_id {
-            Some(lang_def_id) if lang_def_id == impl_def_id => {
-                // OK
-            }
-            _ => {
-                struct_span_err!(self.tcx.sess,
-                                 span,
-                                 E0390,
-                                 "only a single inherent implementation marked with `#[lang = \
-                                  \"{}\"]` is allowed for the `{}` primitive",
-                                 lang,
-                                 ty)
-                    .span_help(span, "consider using a trait to implement these methods")
-                    .emit();
-            }
-        }
-    }
-}
-
 impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
     /// Checks exactly one impl for orphan rules and other such
     /// restrictions.  In this fn, it can happen that multiple errors
@@ -78,168 +35,6 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item) {
         let def_id = self.tcx.hir.local_def_id(item.id);
         match item.node {
-            hir::ItemImpl(.., None, ref ty, _) => {
-                // For inherent impls, self type must be a nominal type
-                // defined in this crate.
-                debug!("coherence2::orphan check: inherent impl {}",
-                       self.tcx.hir.node_to_string(item.id));
-                let self_ty = self.tcx.item_type(def_id);
-                match self_ty.sty {
-                    ty::TyAdt(def, _) => {
-                        self.check_def_id(item, def.did);
-                    }
-                    ty::TyDynamic(ref data, ..) if data.principal().is_some() => {
-                        self.check_def_id(item, data.principal().unwrap().def_id());
-                    }
-                    ty::TyChar => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.char_impl(),
-                                                  "char",
-                                                  "char",
-                                                  item.span);
-                    }
-                    ty::TyStr => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.str_impl(),
-                                                  "str",
-                                                  "str",
-                                                  item.span);
-                    }
-                    ty::TySlice(_) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.slice_impl(),
-                                                  "slice",
-                                                  "[T]",
-                                                  item.span);
-                    }
-                    ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.const_ptr_impl(),
-                                                  "const_ptr",
-                                                  "*const T",
-                                                  item.span);
-                    }
-                    ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.mut_ptr_impl(),
-                                                  "mut_ptr",
-                                                  "*mut T",
-                                                  item.span);
-                    }
-                    ty::TyInt(ast::IntTy::I8) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.i8_impl(),
-                                                  "i8",
-                                                  "i8",
-                                                  item.span);
-                    }
-                    ty::TyInt(ast::IntTy::I16) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.i16_impl(),
-                                                  "i16",
-                                                  "i16",
-                                                  item.span);
-                    }
-                    ty::TyInt(ast::IntTy::I32) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.i32_impl(),
-                                                  "i32",
-                                                  "i32",
-                                                  item.span);
-                    }
-                    ty::TyInt(ast::IntTy::I64) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.i64_impl(),
-                                                  "i64",
-                                                  "i64",
-                                                  item.span);
-                    }
-                    ty::TyInt(ast::IntTy::I128) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.i128_impl(),
-                                                  "i128",
-                                                  "i128",
-                                                  item.span);
-                    }
-                    ty::TyInt(ast::IntTy::Is) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.isize_impl(),
-                                                  "isize",
-                                                  "isize",
-                                                  item.span);
-                    }
-                    ty::TyUint(ast::UintTy::U8) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.u8_impl(),
-                                                  "u8",
-                                                  "u8",
-                                                  item.span);
-                    }
-                    ty::TyUint(ast::UintTy::U16) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.u16_impl(),
-                                                  "u16",
-                                                  "u16",
-                                                  item.span);
-                    }
-                    ty::TyUint(ast::UintTy::U32) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.u32_impl(),
-                                                  "u32",
-                                                  "u32",
-                                                  item.span);
-                    }
-                    ty::TyUint(ast::UintTy::U64) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.u64_impl(),
-                                                  "u64",
-                                                  "u64",
-                                                  item.span);
-                    }
-                    ty::TyUint(ast::UintTy::U128) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.u128_impl(),
-                                                  "u128",
-                                                  "u128",
-                                                  item.span);
-                    }
-                    ty::TyUint(ast::UintTy::Us) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.usize_impl(),
-                                                  "usize",
-                                                  "usize",
-                                                  item.span);
-                    }
-                    ty::TyFloat(ast::FloatTy::F32) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.f32_impl(),
-                                                  "f32",
-                                                  "f32",
-                                                  item.span);
-                    }
-                    ty::TyFloat(ast::FloatTy::F64) => {
-                        self.check_primitive_impl(def_id,
-                                                  self.tcx.lang_items.f64_impl(),
-                                                  "f64",
-                                                  "f64",
-                                                  item.span);
-                    }
-                    ty::TyError => {
-                        return;
-                    }
-                    _ => {
-                        struct_span_err!(self.tcx.sess,
-                                         ty.span,
-                                         E0118,
-                                         "no base type found for inherent implementation")
-                            .span_label(ty.span, &format!("impl requires a base type"))
-                            .note(&format!("either implement a trait on it or create a newtype \
-                                            to wrap it instead"))
-                            .emit();
-                        return;
-                    }
-                }
-            }
             hir::ItemImpl(.., Some(_), _, _) => {
                 // "Trait" impl
                 debug!("coherence2::orphan check: trait impl {}",
@@ -311,7 +106,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                        trait_def_id,
                        self.tcx.trait_has_default_impl(trait_def_id));
                 if self.tcx.trait_has_default_impl(trait_def_id) &&
-                   trait_def_id.krate != LOCAL_CRATE {
+                   !trait_def_id.is_local() {
                     let self_ty = trait_ref.self_ty();
                     let opt_self_def_id = match self_ty.sty {
                         ty::TyAdt(self_def, _) => Some(self_def.did),
@@ -346,31 +141,13 @@ fn visit_item(&mut self, item: &hir::Item) {
                         return;
                     }
                 }
-
-                // Disallow *all* explicit impls of `Sized` and `Unsize` for now.
-                if Some(trait_def_id) == self.tcx.lang_items.sized_trait() {
-                    struct_span_err!(self.tcx.sess,
-                                     item.span,
-                                     E0322,
-                                     "explicit impls for the `Sized` trait are not permitted")
-                        .span_label(item.span, &format!("impl of 'Sized' not allowed"))
-                        .emit();
-                    return;
-                }
-                if Some(trait_def_id) == self.tcx.lang_items.unsize_trait() {
-                    span_err!(self.tcx.sess,
-                              item.span,
-                              E0328,
-                              "explicit impls for the `Unsize` trait are not permitted");
-                    return;
-                }
             }
             hir::ItemDefaultImpl(_, ref item_trait_ref) => {
                 // "Trait" impl
                 debug!("coherence2::orphan check: default trait impl {}",
                        self.tcx.hir.node_to_string(item.id));
                 let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
-                if trait_ref.def_id.krate != LOCAL_CRATE {
+                if !trait_ref.def_id.is_local() {
                     struct_span_err!(self.tcx.sess,
                                      item_trait_ref.path.span,
                                      E0318,
index 45493d40eb802e3375e9cda0b9bb253a81928b41..d334d0c4338f9bc843887410dd1945f061f7c1be 100644 (file)
 //! same type. Likewise, no two inherent impls for a given type
 //! constructor provide a method with the same name.
 
-use hir::def_id::DefId;
-use rustc::traits::{self, Reveal};
+use rustc::traits;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
 use syntax::ast;
 use rustc::dep_graph::DepNode;
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use util::nodemap::DefIdMap;
-use lint;
 
-pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let mut overlap = OverlapChecker {
-        tcx: tcx,
-        default_impls: DefIdMap(),
-    };
+pub fn check_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    let mut overlap = OverlapChecker { tcx };
 
     // this secondary walk specifically checks for some other cases,
     // like defaulted traits, for which additional overlap rules exist
     tcx.visit_all_item_likes_in_krate(DepNode::CoherenceOverlapCheckSpecial, &mut overlap);
 }
 
-struct OverlapChecker<'cx, 'tcx: 'cx> {
-    tcx: TyCtxt<'cx, 'tcx, 'tcx>,
-
-    // maps from a trait def-id to an impl id
-    default_impls: DefIdMap<ast::NodeId>,
-}
+pub fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
+    let impl_def_id = tcx.hir.local_def_id(node_id);
+    let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
+    let trait_def_id = trait_ref.def_id;
 
-impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
-    fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId) {
-        #[derive(Copy, Clone, PartialEq)]
-        enum Namespace {
-            Type,
-            Value,
-        }
+    if trait_ref.references_error() {
+        debug!("coherence: skipping impl {:?} with error {:?}",
+               impl_def_id, trait_ref);
+        return
+    }
 
-        let name_and_namespace = |def_id| {
-            let item = self.tcx.associated_item(def_id);
-            (item.name, match item.kind {
-                ty::AssociatedKind::Type => Namespace::Type,
-                ty::AssociatedKind::Const |
-                ty::AssociatedKind::Method => Namespace::Value,
-            })
-        };
-
-        let impl_items1 = self.tcx.associated_item_def_ids(impl1);
-        let impl_items2 = self.tcx.associated_item_def_ids(impl2);
-
-        for &item1 in &impl_items1[..] {
-            let (name, namespace) = name_and_namespace(item1);
-
-            for &item2 in &impl_items2[..] {
-                if (name, namespace) == name_and_namespace(item2) {
-                    let msg = format!("duplicate definitions with name `{}`", name);
-                    let node_id = self.tcx.hir.as_local_node_id(item1).unwrap();
-                    self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS,
-                                           node_id,
-                                           self.tcx.span_of_impl(item1).unwrap(),
-                                           msg);
-                }
+    let _task =
+        tcx.dep_graph.in_task(DepNode::CoherenceOverlapCheck(trait_def_id));
+
+    let def = tcx.lookup_trait_def(trait_def_id);
+
+    // attempt to insert into the specialization graph
+    let insert_result = def.add_impl_for_specialization(tcx, impl_def_id);
+
+    // insertion failed due to overlap
+    if let Err(overlap) = insert_result {
+        let mut err = struct_span_err!(tcx.sess,
+                                       tcx.span_of_impl(impl_def_id).unwrap(),
+                                       E0119,
+                                       "conflicting implementations of trait `{}`{}:",
+                                       overlap.trait_desc,
+                                       overlap.self_desc.clone().map_or(String::new(),
+                                                                        |ty| {
+            format!(" for type `{}`", ty)
+        }));
+
+        match tcx.span_of_impl(overlap.with_impl) {
+            Ok(span) => {
+                err.span_label(span, &format!("first implementation here"));
+                err.span_label(tcx.span_of_impl(impl_def_id).unwrap(),
+                               &format!("conflicting implementation{}",
+                                        overlap.self_desc
+                                            .map_or(String::new(),
+                                                    |ty| format!(" for `{}`", ty))));
+            }
+            Err(cname) => {
+                err.note(&format!("conflicting implementation in crate `{}`", cname));
             }
         }
+
+        err.emit();
     }
 
-    fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
-        let _task = self.tcx.dep_graph.in_task(DepNode::CoherenceOverlapInherentCheck(ty_def_id));
-
-        let inherent_impls = self.tcx.maps.inherent_impls.borrow();
-        let impls = match inherent_impls.get(&ty_def_id) {
-            Some(impls) => impls,
-            None => return,
-        };
-
-        for (i, &impl1_def_id) in impls.iter().enumerate() {
-            for &impl2_def_id in &impls[(i + 1)..] {
-                self.tcx.infer_ctxt((), Reveal::ExactMatch).enter(|infcx| {
-                    if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() {
-                        self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id)
-                    }
-                });
+    // check for overlap with the automatic `impl Trait for Trait`
+    if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
+        // This is something like impl Trait1 for Trait2. Illegal
+        // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
+
+        if data.principal().map_or(true, |p| !tcx.is_object_safe(p.def_id())) {
+            // This is an error, but it will be reported by wfcheck.  Ignore it here.
+            // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
+        } else {
+            let mut supertrait_def_ids =
+                traits::supertrait_def_ids(tcx,
+                                           data.principal().unwrap().def_id());
+            if supertrait_def_ids.any(|d| d == trait_def_id) {
+                span_err!(tcx.sess,
+                          tcx.span_of_impl(impl_def_id).unwrap(),
+                          E0371,
+                          "the object type `{}` automatically \
+                           implements the trait `{}`",
+                          trait_ref.self_ty(),
+                          tcx.item_path_str(trait_def_id));
             }
         }
     }
 }
 
+struct OverlapChecker<'cx, 'tcx: 'cx> {
+    tcx: TyCtxt<'cx, 'tcx, 'tcx>,
+}
+
 impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v hir::Item) {
         match item.node {
-            hir::ItemEnum(..) |
-            hir::ItemStruct(..) |
-            hir::ItemTrait(..) |
-            hir::ItemUnion(..) => {
-                let type_def_id = self.tcx.hir.local_def_id(item.id);
-                self.check_for_overlapping_inherent_impls(type_def_id);
-            }
-
             hir::ItemDefaultImpl(..) => {
                 // look for another default impl; note that due to the
                 // general orphan/coherence rules, it must always be
@@ -115,8 +114,8 @@ fn visit_item(&mut self, item: &'v hir::Item) {
                 let impl_def_id = self.tcx.hir.local_def_id(item.id);
                 let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
 
-                let prev_default_impl = self.default_impls.insert(trait_ref.def_id, item.id);
-                if let Some(prev_id) = prev_default_impl {
+                let prev_id = self.tcx.hir.trait_default_impl(trait_ref.def_id).unwrap();
+                if prev_id != item.id {
                     let mut err = struct_span_err!(self.tcx.sess,
                                                    self.tcx.span_of_impl(impl_def_id).unwrap(),
                                                    E0521,
@@ -131,76 +130,6 @@ fn visit_item(&mut self, item: &'v hir::Item) {
                 }
             }
             hir::ItemImpl(.., Some(_), _, _) => {
-                let impl_def_id = self.tcx.hir.local_def_id(item.id);
-                let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
-                let trait_def_id = trait_ref.def_id;
-
-                if trait_ref.references_error() {
-                    debug!("coherence: skipping impl {:?} with error {:?}",
-                           impl_def_id, trait_ref);
-                    return
-                }
-
-                let _task =
-                    self.tcx.dep_graph.in_task(DepNode::CoherenceOverlapCheck(trait_def_id));
-
-                let def = self.tcx.lookup_trait_def(trait_def_id);
-
-                // attempt to insert into the specialization graph
-                let insert_result = def.add_impl_for_specialization(self.tcx, impl_def_id);
-
-                // insertion failed due to overlap
-                if let Err(overlap) = insert_result {
-                    let mut err = struct_span_err!(self.tcx.sess,
-                                                   self.tcx.span_of_impl(impl_def_id).unwrap(),
-                                                   E0119,
-                                                   "conflicting implementations of trait `{}`{}:",
-                                                   overlap.trait_desc,
-                                                   overlap.self_desc.clone().map_or(String::new(),
-                                                                                    |ty| {
-                        format!(" for type `{}`", ty)
-                    }));
-
-                    match self.tcx.span_of_impl(overlap.with_impl) {
-                        Ok(span) => {
-                            err.span_label(span, &format!("first implementation here"));
-                            err.span_label(self.tcx.span_of_impl(impl_def_id).unwrap(),
-                                           &format!("conflicting implementation{}",
-                                                    overlap.self_desc
-                                                        .map_or(String::new(),
-                                                                |ty| format!(" for `{}`", ty))));
-                        }
-                        Err(cname) => {
-                            err.note(&format!("conflicting implementation in crate `{}`", cname));
-                        }
-                    }
-
-                    err.emit();
-                }
-
-                // check for overlap with the automatic `impl Trait for Trait`
-                if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
-                    // This is something like impl Trait1 for Trait2. Illegal
-                    // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
-
-                    if data.principal().map_or(true, |p| !self.tcx.is_object_safe(p.def_id())) {
-                        // This is an error, but it will be reported by wfcheck.  Ignore it here.
-                        // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
-                    } else {
-                        let mut supertrait_def_ids =
-                            traits::supertrait_def_ids(self.tcx,
-                                                       data.principal().unwrap().def_id());
-                        if supertrait_def_ids.any(|d| d == trait_def_id) {
-                            span_err!(self.tcx.sess,
-                                      item.span,
-                                      E0371,
-                                      "the object type `{}` automatically \
-                                       implements the trait `{}`",
-                                      trait_ref.self_ty(),
-                                      self.tcx.item_path_str(trait_def_id));
-                        }
-                    }
-                }
             }
             _ => {}
         }
index 8c98e2952ebe9ce155696b2779fe49535486c3bb..22247d2531aec32e821417765016ae4de0e0017f 100644 (file)
@@ -31,20 +31,7 @@ fn check_unsafety_coherence(&mut self,
                                 unsafety: hir::Unsafety,
                                 polarity: hir::ImplPolarity) {
         match self.tcx.impl_trait_ref(self.tcx.hir.local_def_id(item.id)) {
-            None => {
-                // Inherent impl.
-                match unsafety {
-                    hir::Unsafety::Normal => {
-                        // OK
-                    }
-                    hir::Unsafety::Unsafe => {
-                        span_err!(self.tcx.sess,
-                                  item.span,
-                                  E0197,
-                                  "inherent impls cannot be declared as unsafe");
-                    }
-                }
-            }
+            None => {}
 
             Some(trait_ref) => {
                 let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id);
@@ -100,7 +87,7 @@ fn visit_item(&mut self, item: &'v hir::Item) {
             hir::ItemDefaultImpl(unsafety, _) => {
                 self.check_unsafety_coherence(item, None, unsafety, hir::ImplPolarity::Positive);
             }
-            hir::ItemImpl(unsafety, polarity, ref generics, ..) => {
+            hir::ItemImpl(unsafety, polarity, ref generics, Some(_), _, _) => {
                 self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
             }
             _ => {}
index 83adbdaf0307d3d9eefc93b99cce208b61554d69..ecdbf170702aabef6cdd94d762c6d8e40a00698d 100644 (file)
@@ -519,9 +519,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) {
             convert_enum_variant_types(tcx, def_id, &enum_definition.variants);
         },
         hir::ItemDefaultImpl(..) => {
-            if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
-                tcx.record_trait_has_default_impl(trait_ref.def_id);
-            }
+            tcx.impl_trait_ref(def_id);
         }
         hir::ItemImpl(..) => {
             tcx.item_generics(def_id);
@@ -869,7 +867,13 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     let def_path_hash = tcx.def_path(def_id).deterministic_hash(tcx);
-    tcx.alloc_trait_def(ty::TraitDef::new(def_id, unsafety, paren_sugar, def_path_hash))
+    let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, def_path_hash);
+
+    if tcx.hir.trait_is_auto(def_id) {
+        def.record_has_default_impl();
+    }
+
+    tcx.alloc_trait_def(def)
 }
 
 fn generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
index 0f425baec10bbaf7b7df3bccc61cd9514f64da3f..2c325d46c0bc060ff3e8b1aa4c6ca90a4bfad11e 100644 (file)
@@ -155,7 +155,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 expected: Ty<'tcx>,
                                 actual: Ty<'tcx>)
                                 -> bool {
-    tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| {
+    tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
         match infcx.eq_types(false, &cause, expected, actual) {
             Ok(InferOk { obligations, .. }) => {
                 // FIXME(#32730) propagate obligations
@@ -287,6 +287,7 @@ fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
 pub fn provide(providers: &mut Providers) {
     collect::provide(providers);
+    coherence::provide(providers);
     check::provide(providers);
 }
 
index 61c2a3c9e9512bab0c001e13f6f1e3f7b5b33eeb..c4476483186c7a35ed1de6bb20e9de0e52ff179f 100644 (file)
@@ -15,6 +15,7 @@
 use std::iter::once;
 
 use syntax::ast;
+use syntax_pos::DUMMY_SP;
 use rustc::hir;
 
 use rustc::hir::def::{Def, CtorKind};
@@ -231,7 +232,7 @@ fn build_type_alias(cx: &DocContext, did: DefId) -> clean::Typedef {
 
 pub fn build_impls(cx: &DocContext, did: DefId) -> Vec<clean::Item> {
     let tcx = cx.tcx;
-    tcx.populate_inherent_implementations_for_type_if_necessary(did);
+    tcx.populate_inherent_implementations_for_type_if_necessary(DUMMY_SP, did);
     let mut impls = Vec::new();
 
     if let Some(i) = tcx.maps.inherent_impls.borrow().get(&did) {
index 4ba9c3382f35d4792219ac0f5b54f559eefcaf6d..3da00da205fec27e1d827b0a08d613a9ee59fbd4 100644 (file)
@@ -12,6 +12,8 @@ impl Drop for u32 {} //~ ERROR E0117
 //~^ NOTE impl doesn't use types inside crate
 //~| NOTE the impl does not reference any types defined in this crate
 //~| NOTE define and implement a trait or new type instead
+//~| ERROR the Drop trait may only be implemented on structures
+//~| implementing Drop requires a struct
 
 fn main() {
 }
index 9f74afbb2b3b5493ba7b30472b627a51e7685f18..aac870293fd5500ae27a04fbf764f2b016d1a026 100644 (file)
@@ -17,6 +17,7 @@
 
 impl<A> Foo for A {
     //~^ ERROR type parameter `A` must be used as the type parameter for some local type
+    //~| ERROR conflicting implementations of trait `trait_impl_conflict::Foo` for type `isize`
 }
 
 fn main() {
index 3d109de76ccd1c21908c0ff5a46dbef64fd0a072..15a80c64f8b0621fcd07d054ba4580a01e914377 100644 (file)
@@ -13,9 +13,9 @@
 trait MyTrait {}
 
 impl MyTrait for .. {}
+//~^ ERROR redundant default implementations of trait `MyTrait`
 
 impl MyTrait for .. {}
-//~^ ERROR redundant default implementations of trait `MyTrait`
 
 trait MySafeTrait {}
 
index 79767e5157b14b34e65a7d341de5c87fa068fb7d..60b5d14d1587a9f9706defd1eb3a56c2b4c169d6 100644 (file)
@@ -27,14 +27,20 @@ impl Sized for TestE {} //~ ERROR E0322
 impl Sized for MyType {} //~ ERROR E0322
 //~^ impl of 'Sized' not allowed
 
-impl Sized for (MyType, MyType) {} //~ ERROR E0117
+impl Sized for (MyType, MyType) {} //~ ERROR E0322
+//~^ impl of 'Sized' not allowed
+//~| ERROR E0117
 
 impl Sized for &'static NotSync {} //~ ERROR E0322
 //~^ impl of 'Sized' not allowed
 
-impl Sized for [MyType] {} //~ ERROR E0117
+impl Sized for [MyType] {} //~ ERROR E0322
+//~^ impl of 'Sized' not allowed
+//~| ERROR E0117
 
-impl Sized for &'static [NotSync] {} //~ ERROR E0117
+impl Sized for &'static [NotSync] {} //~ ERROR E0322
+//~^ impl of 'Sized' not allowed
+//~| ERROR E0117
 
 fn main() {
 }
index 81a60a9dd3099ad0aedfb3d4014788f8f77fc49f..4fe6afaca8ec658a4eae9fdba79b35dc37cacb29 100644 (file)
@@ -7,15 +7,6 @@ error[E0204]: the trait `Copy` may not be implemented for this type
 15 | impl Copy for Foo { }
    |      ^^^^
 
-error[E0204]: the trait `Copy` may not be implemented for this type
-  --> $DIR/E0204.rs:27:6
-   |
-23 |     Bar { x: Vec<u32> },
-   |           ----------- this field does not implement `Copy`
-...
-27 | impl Copy for EFoo { }
-   |      ^^^^
-
 error[E0204]: the trait `Copy` may not be implemented for this type
   --> $DIR/E0204.rs:17:10
    |
@@ -25,6 +16,15 @@ error[E0204]: the trait `Copy` may not be implemented for this type
 19 |     ty: &'a mut bool,
    |     ---------------- this field does not implement `Copy`
 
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/E0204.rs:27:6
+   |
+23 |     Bar { x: Vec<u32> },
+   |           ----------- this field does not implement `Copy`
+...
+27 | impl Copy for EFoo { }
+   |      ^^^^
+
 error[E0204]: the trait `Copy` may not be implemented for this type
   --> $DIR/E0204.rs:29:10
    |