mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-24 13:43:04 +00:00
Fix a number of bugs that interfered with cross-crate usage of associated consts.
This commit is contained in:
parent
7129e8815e
commit
3d9b5d0424
@ -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);
|
||||
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())
|
||||
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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
46
src/test/auxiliary/associated-const-cc-lib.rs
Normal file
46
src/test/auxiliary/associated-const-cc-lib.rs
Normal file
@ -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;
|
||||
}
|
30
src/test/run-pass/associated-const-cross-crate-defaults.rs
Normal file
30
src/test/run-pass/associated-const-cross-crate-defaults.rs
Normal file
@ -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);
|
||||
}
|
25
src/test/run-pass/associated-const-cross-crate.rs
Normal file
25
src/test/run-pass/associated-const-cross-crate.rs
Normal file
@ -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);
|
||||
}
|
21
src/test/run-pass/associated-const-in-global-const.rs
Normal file
21
src/test/run-pass/associated-const-in-global-const.rs
Normal file
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user