Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
1769c63d
R
Rust
项目概览
int
/
Rust
接近 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
1769c63d
编写于
11月 29, 2017
作者:
A
Ariel Ben-Yehuda
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add a comment and assertion explaining everything
上级
9d38541d
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
93 addition
and
1 deletion
+93
-1
src/librustc/traits/coherence.rs
src/librustc/traits/coherence.rs
+93
-1
未找到文件。
src/librustc/traits/coherence.rs
浏览文件 @
1769c63d
...
...
@@ -16,13 +16,14 @@
use
traits
::
IntercrateMode
;
use
traits
::
select
::
IntercrateAmbiguityCause
;
use
ty
::{
self
,
Ty
,
TyCtxt
};
use
ty
::
fold
::
TypeFoldable
;
use
ty
::
subst
::
Subst
;
use
infer
::{
InferCtxt
,
InferOk
};
#[derive(Copy,
Clone,
Debug)]
/// Whether we do the orphan check relative to this crate or
/// to some remote crate.
#[derive(Copy,
Clone,
Debug)]
enum
InCrate
{
Local
,
Remote
...
...
@@ -224,6 +225,92 @@ pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
orphan_check_trait_ref
(
tcx
,
trait_ref
,
InCrate
::
Local
)
}
/// Check whether a trait-ref is potentially implementable by a crate.
///
/// The current rule is that a trait-ref orphan checks in a crate C:
///
/// 1. Order the parameters in the trait-ref in subst order - Self first,
/// others linearly (e.g. `<U as Foo<V, W>>` is U < V < W).
/// 2. Of these type parameters, there is at least one type parameter
/// in which, walking the type as a tree, you can reach a type local
/// to C where all types in-between are fundamental types. Call the
/// first such parameter the "local key parameter".
/// - e.g. `Box<LocalType>` is OK, because you can visit LocalType
/// going through `Box`, which is fundamental.
/// - similarly, `FundamentalPair<Vec<()>, Box<LocalType>>` is OK for
/// the same reason.
/// - but (knowing that `Vec<T>` is non-fundamental, and assuming it's
/// not local), `Vec<LocalType>` is bad, because `Vec<->` is between
/// the local type and the type parameter.
/// 3. Every type parameter before the local key parameter is fully known in C.
/// - e.g. `impl<T> T: Trait<LocalType>` is bad, because `T` might be
/// an unknown type.
/// - but `impl<T> LocalType: Trait<T>` is OK, because `LocalType`
/// occurs before `T`.
/// 4. Every type in the local key parameter not known in C, going
/// through the parameter's type tree, must appear only as a subtree of
/// a type local to C, with only fundamental types between the type
/// local to C and the local key parameter.
/// - e.g. `Vec<LocalType<T>>>` (or equivalently `Box<Vec<LocalType<T>>>`)
/// is bad, because the only local type with `T` as a subtree is
/// `LocalType<T>`, and `Vec<->` is between it and the type parameter.
/// - similarly, `FundamentalPair<LocalType<T>, T>` is bad, because
/// the second occurence of `T` is not a subtree of *any* local type.
/// - however, `LocalType<Vec<T>>` is OK, because `T` is a subtree of
/// `LocalType<Vec<T>>`, which is local and has no types between it and
/// the type parameter.
///
/// The orphan rules actually serve several different purposes:
///
/// 1. They enable link-safety - i.e. 2 mutually-unknowing crates (where
/// every type local to one crate is unknown in the other) can't implement
/// the same trait-ref. This follows because it can be seen that no such
/// type can orphan-check in 2 such crates.
///
/// To check that a local impl follows the orphan rules, we check it in
/// InCrate::Local mode, using type parameters for the "generic" types.
///
/// 2. They ground negative reasoning for coherence. If a user wants to
/// write both a conditional blanket impl and a specific impl, we need to
/// make sure they do not overlap. For example, if we write
/// ```
/// impl<T> IntoIterator for Vec<T>
/// impl<T: Iterator> IntoIterator for T
/// ```
/// We need to be able to prove that `Option<$0>: !Iterator` for every type $0.
/// We can observe that this holds in the current crate, but we need to make
/// sure this will also hold in all unknown crates (both "independent" crates,
/// which we need for link-safety, and also child crates, because we don't want
/// child crates to get error for impl conflicts in a *dependency*).
///
/// For that, we only allow negative reasoning if, for every assignment to the
/// inference variables, every unknown crate would get an orphan error if they
/// try to implement this trait-ref. To check for this, we use InCrate::Remote
/// mode. That is sound because we already know all the impls from known crates.
///
/// 3. For non-#[fundamental] traits, they guarantee that parent crates can
/// add "non-blanket" impls without breaking negative reasoning in dependent
/// crates. This is the "rebalancing coherence" (RFC 1023) restriction.
///
/// For that, we only a allow crate to perform negative reasoning on
/// non-local-non-#[fundamental] only if there's a local key parameter as per (2).
///
/// Because we never perform negative reasoning generically (coherence does
/// not involve type parameters), this can be interpreted as doing the full
/// orphan check (using InCrate::Local mode), substituting non-local known
/// types for all inference variables.
///
/// This allows for crates to future-compatibly add impls as long as they
/// can't apply to types with a key parameter in a child crate - applying
/// the rules, this basically means that every type parameter in the impl
/// must appear behind a non-fundamental type (because this is not a
/// type-system requirement, crate owners might also go for "semantic
/// future-compatibility" involving things such as sealed traits, but
/// the above requirement is sufficient, and is necessary in "open world"
/// cases).
///
/// Note that this function is never called for types that have both type
/// parameters and inference variables.
fn
orphan_check_trait_ref
<
'tcx
>
(
tcx
:
TyCtxt
,
trait_ref
:
ty
::
TraitRef
<
'tcx
>
,
in_crate
:
InCrate
)
...
...
@@ -232,6 +319,11 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
debug!
(
"orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})"
,
trait_ref
,
in_crate
);
if
trait_ref
.needs_infer
()
&&
trait_ref
.needs_subst
()
{
bug!
(
"can't orphan check a trait ref with both params and inference variables {:?}"
,
trait_ref
);
}
// First, create an ordered iterator over all the type parameters to the trait, with the self
// type appearing first.
// Find the first input type that either references a type parameter OR
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录