about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/metadata/decoder.rs30
-rw-r--r--src/librustc/middle/const_eval.rs28
-rw-r--r--src/librustc/middle/ty.rs3
-rw-r--r--src/librustc_trans/trans/inline.rs8
-rw-r--r--src/test/auxiliary/associated-const-cc-lib.rs46
-rw-r--r--src/test/run-pass/associated-const-cross-crate-defaults.rs30
-rw-r--r--src/test/run-pass/associated-const-cross-crate.rs25
-rw-r--r--src/test/run-pass/associated-const-in-global-const.rs21
8 files changed, 167 insertions, 24 deletions
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 00a7fe68f2f..f03a2d342d7 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -1002,21 +1002,23 @@ pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
     let item = lookup_item(id, data);
     let mut result = Vec::new();
 
-    reader::tagged_docs(item, tag_item_trait_item, |ac_id| {
-        let did = item_def_id(ac_id, cdata);
-        let ac_doc = lookup_item(did.node, data);
-
-        if item_sort(ac_doc) == Some('C') {
-            let trait_item = get_impl_or_trait_item(intr.clone(),
-                                                    cdata,
-                                                    did.node,
-                                                    tcx);
-            if let ty::ConstTraitItem(ref ac) = trait_item {
-                result.push((*ac).clone())
+    for &tag in &[tag_item_trait_item, tag_item_impl_item] {
+        reader::tagged_docs(item, tag, |ac_id| {
+            let did = item_def_id(ac_id, cdata);
+            let ac_doc = lookup_item(did.node, data);
+
+            if item_sort(ac_doc) == Some('C') {
+                let trait_item = get_impl_or_trait_item(intr.clone(),
+                                                        cdata,
+                                                        did.node,
+                                                        tcx);
+                if let ty::ConstTraitItem(ref ac) = trait_item {
+                    result.push((*ac).clone())
+                }
             }
-        }
-        true
-    });
+            true
+        });
+    }
 
     return result;
 }
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index b5a173a569f..916874f1c51 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -117,15 +117,25 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                 _ => None
             },
             Some(ast_map::NodeTraitItem(ti)) => match ti.node {
-                ast::ConstTraitItem(_, ref default) => {
+                ast::ConstTraitItem(_, _) => {
                     match maybe_ref_id {
+                        // If we have a trait item, and we know the expression
+                        // that's the source of the obligation to resolve it,
+                        // `resolve_trait_associated_const` will select an impl
+                        // or the default.
                         Some(ref_id) => {
                             let trait_id = ty::trait_of_item(tcx, def_id)
                                               .unwrap();
                             resolve_trait_associated_const(tcx, ti, trait_id,
                                                            ref_id)
                         }
-                        None => default.as_ref().map(|expr| &**expr),
+                        // Technically, without knowing anything about the
+                        // expression that generates the obligation, we could
+                        // still return the default if there is one. However,
+                        // it's safer to return `None` than to return some value
+                        // that may differ from what you would get from
+                        // correctly selecting an impl.
+                        None => None
                     }
                 }
                 _ => None
@@ -153,17 +163,19 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                 ast::ItemConst(_, ref const_expr) => Some(const_expr.id),
                 _ => None
             },
-            csearch::FoundAst::Found(&ast::IITraitItem(_, ref ti)) => match ti.node {
-                ast::ConstTraitItem(_, ref default) => {
+            csearch::FoundAst::Found(&ast::IITraitItem(trait_id, ref ti)) => match ti.node {
+                ast::ConstTraitItem(_, _) => {
                     used_ref_id = true;
                     match maybe_ref_id {
+                        // As mentioned in the comments above for in-crate
+                        // constants, we only try to find the expression for
+                        // a trait-associated const if the caller gives us
+                        // the expression that refers to it.
                         Some(ref_id) => {
-                            let trait_id = ty::trait_of_item(tcx, def_id)
-                                              .unwrap();
                             resolve_trait_associated_const(tcx, ti, trait_id,
                                                            ref_id).map(|e| e.id)
                         }
-                        None => default.as_ref().map(|expr| expr.id),
+                        None => None
                     }
                 }
                 _ => None
@@ -177,7 +189,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
         // If we used the reference expression, particularly to choose an impl
         // of a trait-associated const, don't cache that, because the next
         // lookup with the same def_id may yield a different result.
-        if used_ref_id {
+        if !used_ref_id {
             tcx.extern_const_statics
                .borrow_mut().insert(def_id,
                                     expr_id.unwrap_or(ast::DUMMY_NODE_ID));
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 1b5e31f61d8..41745c6384b 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -5167,8 +5167,7 @@ pub fn associated_consts<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
             }
         }
     } else {
-        let acs = csearch::get_associated_consts(cx, id);
-        acs.iter().map(|ac| (*ac).clone()).collect()
+        csearch::get_associated_consts(cx, id)
     }
 }
 
diff --git a/src/librustc_trans/trans/inline.rs b/src/librustc_trans/trans/inline.rs
index 2034c6223c1..3f44bc40f35 100644
--- a/src/librustc_trans/trans/inline.rs
+++ b/src/librustc_trans/trans/inline.rs
@@ -134,6 +134,14 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
 
             ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
 
+            // Associated consts already have to be evaluated in `typeck`, so
+            // the logic to do that already exists in `middle`. In order to
+            // reuse that code, it needs to be able to look up the traits for
+            // inlined items.
+            let ty_trait_item = ty::impl_or_trait_item(ccx.tcx(), fn_id).clone();
+            ccx.tcx().impl_or_trait_items.borrow_mut()
+                     .insert(local_def(trait_item.id), ty_trait_item);
+
             // If this is a default method, we can't look up the
             // impl type. But we aren't going to translate anyways, so
             // don't.
diff --git a/src/test/auxiliary/associated-const-cc-lib.rs b/src/test/auxiliary/associated-const-cc-lib.rs
new file mode 100644
index 00000000000..9735c6cb54d
--- /dev/null
+++ b/src/test/auxiliary/associated-const-cc-lib.rs
@@ -0,0 +1,46 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+#![crate_type="lib"]
+
+use std::marker::MarkerTrait;
+
+// These items are for testing that associated consts work cross-crate.
+pub trait Foo: MarkerTrait {
+    const BAR: usize;
+}
+
+pub struct FooNoDefault;
+
+impl Foo for FooNoDefault {
+    const BAR: usize = 0;
+}
+
+// These test that defaults and default resolution work cross-crate.
+pub trait FooDefault: MarkerTrait {
+    const BAR: usize = 1;
+}
+
+pub struct FooOverwriteDefault;
+
+impl FooDefault for FooOverwriteDefault {
+    const BAR: usize = 2;
+}
+
+pub struct FooUseDefault;
+
+impl FooDefault for FooUseDefault {}
+
+// Test inherent impls.
+pub struct InherentBar;
+
+impl InherentBar {
+    pub const BAR: usize = 3;
+}
diff --git a/src/test/run-pass/associated-const-cross-crate-defaults.rs b/src/test/run-pass/associated-const-cross-crate-defaults.rs
new file mode 100644
index 00000000000..944466f359d
--- /dev/null
+++ b/src/test/run-pass/associated-const-cross-crate-defaults.rs
@@ -0,0 +1,30 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// aux-build:associated-const-cc-lib.rs
+
+extern crate associated_const_cc_lib as foolib;
+
+pub struct LocalFooUseDefault;
+
+impl foolib::FooDefault for LocalFooUseDefault {}
+
+pub struct LocalFooOverwriteDefault;
+
+impl foolib::FooDefault for LocalFooOverwriteDefault {
+    const BAR: usize = 4;
+}
+
+fn main() {
+    assert_eq!(1, <foolib::FooUseDefault as foolib::FooDefault>::BAR);
+    assert_eq!(2, <foolib::FooOverwriteDefault as foolib::FooDefault>::BAR);
+    assert_eq!(1, <LocalFooUseDefault as foolib::FooDefault>::BAR);
+    assert_eq!(4, <LocalFooOverwriteDefault as foolib::FooDefault>::BAR);
+}
diff --git a/src/test/run-pass/associated-const-cross-crate.rs b/src/test/run-pass/associated-const-cross-crate.rs
new file mode 100644
index 00000000000..c18cda018d8
--- /dev/null
+++ b/src/test/run-pass/associated-const-cross-crate.rs
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// aux-build:associated-const-cc-lib.rs
+
+extern crate associated_const_cc_lib as foolib;
+
+pub struct LocalFoo;
+
+impl foolib::Foo for LocalFoo {
+    const BAR: usize = 1;
+}
+
+fn main() {
+    assert_eq!(0, <foolib::FooNoDefault as foolib::Foo>::BAR);
+    assert_eq!(1, <LocalFoo as foolib::Foo>::BAR);
+    assert_eq!(3, foolib::InherentBar::BAR);
+}
diff --git a/src/test/run-pass/associated-const-in-global-const.rs b/src/test/run-pass/associated-const-in-global-const.rs
new file mode 100644
index 00000000000..b9fb067d4fa
--- /dev/null
+++ b/src/test/run-pass/associated-const-in-global-const.rs
@@ -0,0 +1,21 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+struct Foo;
+
+impl Foo {
+    const BAR: f32 = 1.5;
+}
+
+const FOOBAR: f32 = <Foo>::BAR;
+
+fn main() {
+    assert_eq!(1.5f32, FOOBAR);
+}