提交 3d9b5d04 编写于 作者: S Sean Patrick Santos

Fix a number of bugs that interfered with cross-crate usage of associated consts.

上级 7129e881
......@@ -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;
}
......
......@@ -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.
......
// 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;
}
// 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);
}
// 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);
}
// 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);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册