Skip to content

Commit 2237f83

Browse files
committed
Fix a number of bugs that interfered with cross-crate usage of associated consts.
1 parent 699db6c commit 2237f83

File tree

8 files changed

+167
-24
lines changed

8 files changed

+167
-24
lines changed

src/librustc/metadata/decoder.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,21 +1003,23 @@ pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
10031003
let item = lookup_item(id, data);
10041004
let mut result = Vec::new();
10051005

1006-
reader::tagged_docs(item, tag_item_trait_item, |ac_id| {
1007-
let did = item_def_id(ac_id, cdata);
1008-
let ac_doc = lookup_item(did.node, data);
1009-
1010-
if item_sort(ac_doc) == Some('C') {
1011-
let trait_item = get_impl_or_trait_item(intr.clone(),
1012-
cdata,
1013-
did.node,
1014-
tcx);
1015-
if let ty::ConstTraitItem(ref ac) = trait_item {
1016-
result.push((*ac).clone())
1006+
for &tag in &[tag_item_trait_item, tag_item_impl_item] {
1007+
reader::tagged_docs(item, tag, |ac_id| {
1008+
let did = item_def_id(ac_id, cdata);
1009+
let ac_doc = lookup_item(did.node, data);
1010+
1011+
if item_sort(ac_doc) == Some('C') {
1012+
let trait_item = get_impl_or_trait_item(intr.clone(),
1013+
cdata,
1014+
did.node,
1015+
tcx);
1016+
if let ty::ConstTraitItem(ref ac) = trait_item {
1017+
result.push((*ac).clone())
1018+
}
10171019
}
1018-
}
1019-
true
1020-
});
1020+
true
1021+
});
1022+
}
10211023

10221024
return result;
10231025
}

src/librustc/middle/const_eval.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,25 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
117117
_ => None
118118
},
119119
Some(ast_map::NodeTraitItem(ti)) => match ti.node {
120-
ast::ConstTraitItem(_, ref default) => {
120+
ast::ConstTraitItem(_, _) => {
121121
match maybe_ref_id {
122+
// If we have a trait item, and we know the expression
123+
// that's the source of the obligation to resolve it,
124+
// `resolve_trait_associated_const` will select an impl
125+
// or the default.
122126
Some(ref_id) => {
123127
let trait_id = ty::trait_of_item(tcx, def_id)
124128
.unwrap();
125129
resolve_trait_associated_const(tcx, ti, trait_id,
126130
ref_id)
127131
}
128-
None => default.as_ref().map(|expr| &**expr),
132+
// Technically, without knowing anything about the
133+
// expression that generates the obligation, we could
134+
// still return the default if there is one. However,
135+
// it's safer to return `None` than to return some value
136+
// that may differ from what you would get from
137+
// correctly selecting an impl.
138+
None => None
129139
}
130140
}
131141
_ => None
@@ -153,17 +163,19 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
153163
ast::ItemConst(_, ref const_expr) => Some(const_expr.id),
154164
_ => None
155165
},
156-
csearch::FoundAst::Found(&ast::IITraitItem(_, ref ti)) => match ti.node {
157-
ast::ConstTraitItem(_, ref default) => {
166+
csearch::FoundAst::Found(&ast::IITraitItem(trait_id, ref ti)) => match ti.node {
167+
ast::ConstTraitItem(_, _) => {
158168
used_ref_id = true;
159169
match maybe_ref_id {
170+
// As mentioned in the comments above for in-crate
171+
// constants, we only try to find the expression for
172+
// a trait-associated const if the caller gives us
173+
// the expression that refers to it.
160174
Some(ref_id) => {
161-
let trait_id = ty::trait_of_item(tcx, def_id)
162-
.unwrap();
163175
resolve_trait_associated_const(tcx, ti, trait_id,
164176
ref_id).map(|e| e.id)
165177
}
166-
None => default.as_ref().map(|expr| expr.id),
178+
None => None
167179
}
168180
}
169181
_ => None
@@ -177,7 +189,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
177189
// If we used the reference expression, particularly to choose an impl
178190
// of a trait-associated const, don't cache that, because the next
179191
// lookup with the same def_id may yield a different result.
180-
if used_ref_id {
192+
if !used_ref_id {
181193
tcx.extern_const_statics
182194
.borrow_mut().insert(def_id,
183195
expr_id.unwrap_or(ast::DUMMY_NODE_ID));

src/librustc/middle/ty.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5157,8 +5157,7 @@ pub fn associated_consts<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
51575157
}
51585158
}
51595159
} else {
5160-
let acs = csearch::get_associated_consts(cx, id);
5161-
acs.iter().map(|ac| (*ac).clone()).collect()
5160+
csearch::get_associated_consts(cx, id)
51625161
}
51635162
}
51645163

src/librustc_trans/trans/inline.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
134134

135135
ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
136136

137+
// Associated consts already have to be evaluated in `typeck`, so
138+
// the logic to do that already exists in `middle`. In order to
139+
// reuse that code, it needs to be able to look up the traits for
140+
// inlined items.
141+
let ty_trait_item = ty::impl_or_trait_item(ccx.tcx(), fn_id).clone();
142+
ccx.tcx().impl_or_trait_items.borrow_mut()
143+
.insert(local_def(trait_item.id), ty_trait_item);
144+
137145
// If this is a default method, we can't look up the
138146
// impl type. But we aren't going to translate anyways, so
139147
// don't.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_type="lib"]
12+
13+
use std::marker::MarkerTrait;
14+
15+
// These items are for testing that associated consts work cross-crate.
16+
pub trait Foo: MarkerTrait {
17+
const BAR: usize;
18+
}
19+
20+
pub struct FooNoDefault;
21+
22+
impl Foo for FooNoDefault {
23+
const BAR: usize = 0;
24+
}
25+
26+
// These test that defaults and default resolution work cross-crate.
27+
pub trait FooDefault: MarkerTrait {
28+
const BAR: usize = 1;
29+
}
30+
31+
pub struct FooOverwriteDefault;
32+
33+
impl FooDefault for FooOverwriteDefault {
34+
const BAR: usize = 2;
35+
}
36+
37+
pub struct FooUseDefault;
38+
39+
impl FooDefault for FooUseDefault {}
40+
41+
// Test inherent impls.
42+
pub struct InherentBar;
43+
44+
impl InherentBar {
45+
pub const BAR: usize = 3;
46+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:associated-const-cc-lib.rs
12+
13+
extern crate associated_const_cc_lib as foolib;
14+
15+
pub struct LocalFooUseDefault;
16+
17+
impl foolib::FooDefault for LocalFooUseDefault {}
18+
19+
pub struct LocalFooOverwriteDefault;
20+
21+
impl foolib::FooDefault for LocalFooOverwriteDefault {
22+
const BAR: usize = 4;
23+
}
24+
25+
fn main() {
26+
assert_eq!(1, <foolib::FooUseDefault as foolib::FooDefault>::BAR);
27+
assert_eq!(2, <foolib::FooOverwriteDefault as foolib::FooDefault>::BAR);
28+
assert_eq!(1, <LocalFooUseDefault as foolib::FooDefault>::BAR);
29+
assert_eq!(4, <LocalFooOverwriteDefault as foolib::FooDefault>::BAR);
30+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:associated-const-cc-lib.rs
12+
13+
extern crate associated_const_cc_lib as foolib;
14+
15+
pub struct LocalFoo;
16+
17+
impl foolib::Foo for LocalFoo {
18+
const BAR: usize = 1;
19+
}
20+
21+
fn main() {
22+
assert_eq!(0, <foolib::FooNoDefault as foolib::Foo>::BAR);
23+
assert_eq!(1, <LocalFoo as foolib::Foo>::BAR);
24+
assert_eq!(3, foolib::InherentBar::BAR);
25+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct Foo;
12+
13+
impl Foo {
14+
const BAR: f32 = 1.5;
15+
}
16+
17+
const FOOBAR: f32 = <Foo>::BAR;
18+
19+
fn main() {
20+
assert_eq!(1.5f32, FOOBAR);
21+
}

0 commit comments

Comments
 (0)