Skip to content

Commit 39c68b0

Browse files
committed
Fix a number of bugs that interfered with cross-crate usage of associated consts.
1 parent 28422f7 commit 39c68b0

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
@@ -113,15 +113,25 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
113113
_ => None
114114
},
115115
Some(ast_map::NodeTraitItem(ti)) => match ti.node {
116-
ast::ConstTraitItem(_, ref default) => {
116+
ast::ConstTraitItem(_, _) => {
117117
match maybe_ref_id {
118+
// If we have a trait item, and we know the expression
119+
// that's the source of the obligation to resolve it,
120+
// `resolve_trait_associated_const` will select an impl
121+
// or the default.
118122
Some(ref_id) => {
119123
let trait_id = ty::trait_of_item(tcx, def_id)
120124
.unwrap();
121125
resolve_trait_associated_const(tcx, ti, trait_id,
122126
ref_id)
123127
}
124-
None => default.as_ref().map(|expr| &**expr),
128+
// Technically, without knowing anything about the
129+
// expression that generates the obligation, we could
130+
// still return the default if there is one. However,
131+
// it's safer to return `None` than to return some value
132+
// that may differ from what you would get from
133+
// correctly selecting an impl.
134+
None => None
125135
}
126136
}
127137
_ => None
@@ -149,17 +159,19 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
149159
ast::ItemConst(_, ref const_expr) => Some(const_expr.id),
150160
_ => None
151161
},
152-
csearch::FoundAst::Found(&ast::IITraitItem(_, ref ti)) => match ti.node {
153-
ast::ConstTraitItem(_, ref default) => {
162+
csearch::FoundAst::Found(&ast::IITraitItem(trait_id, ref ti)) => match ti.node {
163+
ast::ConstTraitItem(_, _) => {
154164
used_ref_id = true;
155165
match maybe_ref_id {
166+
// As mentioned in the comments above for in-crate
167+
// constants, we only try to find the expression for
168+
// a trait-associated const if the caller gives us
169+
// the expression that refers to it.
156170
Some(ref_id) => {
157-
let trait_id = ty::trait_of_item(tcx, def_id)
158-
.unwrap();
159171
resolve_trait_associated_const(tcx, ti, trait_id,
160172
ref_id).map(|e| e.id)
161173
}
162-
None => default.as_ref().map(|expr| expr.id),
174+
None => None
163175
}
164176
}
165177
_ => None
@@ -173,7 +185,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
173185
// If we used the reference expression, particularly to choose an impl
174186
// of a trait-associated const, don't cache that, because the next
175187
// lookup with the same def_id may yield a different result.
176-
if used_ref_id {
188+
if !used_ref_id {
177189
tcx.extern_const_statics
178190
.borrow_mut().insert(def_id,
179191
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
@@ -5258,8 +5258,7 @@ pub fn associated_consts<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
52585258
}
52595259
}
52605260
} else {
5261-
let acs = csearch::get_associated_consts(cx, id);
5262-
acs.iter().map(|ac| (*ac).clone()).collect()
5261+
csearch::get_associated_consts(cx, id)
52635262
}
52645263
}
52655264

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)