about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPietro Albini <pietro@pietroalbini.org>2018-12-06 07:48:56 +0100
committerGitHub <noreply@github.com>2018-12-06 07:48:56 +0100
commit50148a95668c3587a544ab08dda8abb270a59f54 (patch)
tree221a0d31f34596b7e206c108075e8e4d9740482c
parent0be8537e236f811a0eb722a8fa097313808f26f0 (diff)
parent59e9a1e75aaa971b1910fd9db98d9fce55534558 (diff)
downloadrust-50148a95668c3587a544ab08dda8abb270a59f54.tar.gz
rust-50148a95668c3587a544ab08dda8abb270a59f54.zip
Rollup merge of #56446 - arielb1:special-env-implications, r=nikomatsakis
pass the parameter environment to `traits::find_associated_item`

dropping the param-env on the floor is obviously the wrong thing to do.

The ICE was probably exposed by #54490 adding the problem-exposing use of
`traits::find_associated_item`.

Fixes #55380.

r? @nikomatsakis
-rw-r--r--src/librustc/traits/specialize/mod.rs12
-rw-r--r--src/librustc/traits/structural_impls.rs4
-rw-r--r--src/librustc/ty/instance.rs5
-rw-r--r--src/test/run-pass/issue-55380.rs38
4 files changed, 54 insertions, 5 deletions
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 19ef3171b13..cb17246b15f 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -85,6 +85,8 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                         source_substs: &'tcx Substs<'tcx>,
                                         target_node: specialization_graph::Node)
                                         -> &'tcx Substs<'tcx> {
+    debug!("translate_substs({:?}, {:?}, {:?}, {:?})",
+           param_env, source_impl, source_substs, target_node);
     let source_trait_ref = infcx.tcx
                                 .impl_trait_ref(source_impl)
                                 .unwrap()
@@ -119,10 +121,13 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
 /// whichever applies.
 pub fn find_associated_item<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     item: &ty::AssociatedItem,
     substs: &'tcx Substs<'tcx>,
     impl_data: &super::VtableImplData<'tcx, ()>,
 ) -> (DefId, &'tcx Substs<'tcx>) {
+    debug!("find_associated_item({:?}, {:?}, {:?}, {:?})",
+           param_env, item, substs, impl_data);
     assert!(!substs.needs_infer());
 
     let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
@@ -132,7 +137,7 @@ pub fn find_associated_item<'a, 'tcx>(
     match ancestors.defs(tcx, item.ident, item.kind, trait_def_id).next() {
         Some(node_item) => {
             let substs = tcx.infer_ctxt().enter(|infcx| {
-                let param_env = ty::ParamEnv::reveal_all();
+                let param_env = param_env.with_reveal_all();
                 let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
                 let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id,
                                               substs, node_item.node);
@@ -219,12 +224,17 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                        source_trait_ref: ty::TraitRef<'tcx>,
                                        target_impl: DefId)
                                        -> Result<&'tcx Substs<'tcx>, ()> {
+    debug!("fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)",
+           param_env, source_trait_ref, target_impl);
+
     let selcx = &mut SelectionContext::new(&infcx);
     let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
     let (target_trait_ref, mut obligations) = impl_trait_ref_and_oblig(selcx,
                                                                        param_env,
                                                                        target_impl,
                                                                        target_substs);
+    debug!("fulfill_implication: target_trait_ref={:?}, obligations={:?}",
+           target_trait_ref, obligations);
 
     // do the impls unify? If not, no specialization.
     match infcx.at(&ObligationCause::dummy(), param_env)
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 36538ac0889..36e93cc7740 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -33,8 +33,8 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for traits::Obligation<'tcx, O> {
         if ty::tls::with(|tcx| tcx.sess.verbose()) {
             write!(
                 f,
-                "Obligation(predicate={:?},cause={:?},depth={})",
-                self.predicate, self.cause, self.recursion_depth
+                "Obligation(predicate={:?},cause={:?},param_env={:?},depth={})",
+                self.predicate, self.cause, self.param_env, self.recursion_depth
             )
         } else {
             write!(
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 411a6e7e623..a24920da158 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -347,9 +347,10 @@ fn resolve_associated_item<'a, 'tcx>(
 ) -> Option<Instance<'tcx>> {
     let def_id = trait_item.def_id;
     debug!("resolve_associated_item(trait_item={:?}, \
+            param_env={:?}, \
             trait_id={:?}, \
             rcvr_substs={:?})",
-           def_id, trait_id, rcvr_substs);
+            def_id, param_env, trait_id, rcvr_substs);
 
     let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
     let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)));
@@ -359,7 +360,7 @@ fn resolve_associated_item<'a, 'tcx>(
     match vtbl {
         traits::VtableImpl(impl_data) => {
             let (def_id, substs) = traits::find_associated_item(
-                tcx, trait_item, rcvr_substs, &impl_data);
+                tcx, param_env, trait_item, rcvr_substs, &impl_data);
             let substs = tcx.erase_regions(&substs);
             Some(ty::Instance::new(def_id, substs))
         }
diff --git a/src/test/run-pass/issue-55380.rs b/src/test/run-pass/issue-55380.rs
new file mode 100644
index 00000000000..29392fba8b4
--- /dev/null
+++ b/src/test/run-pass/issue-55380.rs
@@ -0,0 +1,38 @@
+// Copyright 2018 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.
+
+// run-pass
+
+#![feature(specialization)]
+
+pub trait Foo {
+    fn abc() -> u32;
+    fn def() -> u32;
+}
+
+pub trait Marker {}
+
+impl Marker for () {}
+
+impl<T> Foo for T {
+    default fn abc() -> u32 { 16 }
+    default fn def() -> u32 { 42 }
+}
+
+impl<T: Marker> Foo for T {
+    fn def() -> u32 {
+        Self::abc()
+    }
+}
+
+fn main() {
+   assert_eq!(<()>::def(), 16);
+   assert_eq!(<i32>::def(), 42);
+}