Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
d7d4d7c8
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
d7d4d7c8
编写于
8月 08, 2018
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add a `user_substs` table and store the annotations in there
上级
1884fe35
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
202 addition
and
6 deletion
+202
-6
src/librustc/ty/subst.rs
src/librustc/ty/subst.rs
+29
-3
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+62
-2
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/check/writeback.rs
+25
-1
src/libsyntax/feature_gate.rs
src/libsyntax/feature_gate.rs
+6
-0
src/test/ui/nll/user-annotations/dump-fn-method.rs
src/test/ui/nll/user-annotations/dump-fn-method.rs
+54
-0
src/test/ui/nll/user-annotations/dump-fn-method.stderr
src/test/ui/nll/user-annotations/dump-fn-method.stderr
+26
-0
未找到文件。
src/librustc/ty/subst.rs
浏览文件 @
d7d4d7c8
...
...
@@ -12,13 +12,14 @@
use
hir
::
def_id
::
DefId
;
use
infer
::
canonical
::
Canonical
;
use
ty
::{
self
,
Lift
,
List
,
Ty
,
TyCtxt
};
use
ty
::{
self
,
CanonicalVar
,
Lift
,
List
,
Ty
,
TyCtxt
};
use
ty
::
fold
::{
TypeFoldable
,
TypeFolder
,
TypeVisitor
};
use
serialize
::{
self
,
Encodable
,
Encoder
,
Decodable
,
Decoder
};
use
syntax_pos
::{
Span
,
DUMMY_SP
};
use
rustc_data_structures
::
accumulate_vec
::
AccumulateVec
;
use
rustc_data_structures
::
array_vec
::
ArrayVec
;
use
rustc_data_structures
::
indexed_vec
::
Idx
;
use
core
::
intrinsics
;
use
std
::
cmp
::
Ordering
;
...
...
@@ -180,8 +181,6 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Kind<'tcx>, D::Error> {
/// A substitution mapping generic parameters to new values.
pub
type
Substs
<
'tcx
>
=
List
<
Kind
<
'tcx
>>
;
pub
type
CanonicalSubsts
<
'gcx
>
=
Canonical
<
'gcx
,
&
'gcx
Substs
<
'gcx
>>
;
impl
<
'a
,
'gcx
,
'tcx
>
Substs
<
'tcx
>
{
/// Creates a Substs that maps each generic parameter to itself.
pub
fn
identity_for_item
(
tcx
:
TyCtxt
<
'a
,
'gcx
,
'tcx
>
,
def_id
:
DefId
)
...
...
@@ -342,6 +341,33 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
pub
type
CanonicalSubsts
<
'gcx
>
=
Canonical
<
'gcx
,
&
'gcx
Substs
<
'gcx
>>
;
impl
<
'gcx
>
CanonicalSubsts
<
'gcx
>
{
/// True if this represents a substitution like
///
/// ```ignore
/// [?0, ?1, ?2]
/// ```
///
/// i.e., each thing is mapped to a canonical variable with the same index.
pub
fn
is_identity
(
&
self
)
->
bool
{
self
.value
.iter
()
.zip
(
CanonicalVar
::
new
(
0
)
..
)
.all
(|(
kind
,
cvar
)|
{
match
kind
.unpack
()
{
UnpackedKind
::
Type
(
ty
)
=>
match
ty
.sty
{
ty
::
Infer
(
ty
::
CanonicalTy
(
cvar1
))
=>
cvar
==
cvar1
,
_
=>
false
,
},
UnpackedKind
::
Lifetime
(
r
)
=>
match
r
{
ty
::
ReCanonical
(
cvar1
)
=>
cvar
==
*
cvar1
,
_
=>
false
,
},
}
})
}
}
impl
<
'tcx
>
serialize
::
UseSpecializedDecodable
for
&
'tcx
Substs
<
'tcx
>
{}
///////////////////////////////////////////////////////////////////////////
...
...
src/librustc_typeck/check/mod.rs
浏览文件 @
d7d4d7c8
...
...
@@ -95,7 +95,7 @@
use
rustc
::
infer
::
type_variable
::{
TypeVariableOrigin
};
use
rustc
::
middle
::
region
;
use
rustc
::
mir
::
interpret
::{
GlobalId
};
use
rustc
::
ty
::
subst
::{
UnpackedKind
,
Subst
,
Substs
};
use
rustc
::
ty
::
subst
::{
CanonicalSubsts
,
UnpackedKind
,
Subst
,
Substs
};
use
rustc
::
traits
::{
self
,
ObligationCause
,
ObligationCauseCode
,
TraitEngine
};
use
rustc
::
ty
::{
self
,
Ty
,
TyCtxt
,
GenericParamDefKind
,
Visibility
,
ToPredicate
,
RegionKind
};
use
rustc
::
ty
::
adjustment
::{
Adjust
,
Adjustment
,
AllowTwoPhase
,
AutoBorrow
,
AutoBorrowMutability
};
...
...
@@ -122,6 +122,7 @@
use
rustc_target
::
spec
::
abi
::
Abi
;
use
syntax
::
ast
;
use
syntax
::
attr
;
use
syntax
::
source_map
::
DUMMY_SP
;
use
syntax
::
source_map
::
original_sp
;
use
syntax
::
feature_gate
::{
GateIssue
,
emit_feature_err
};
use
syntax
::
ptr
::
P
;
...
...
@@ -2058,11 +2059,47 @@ pub fn write_field_index(&self, node_id: ast::NodeId, index: usize) {
pub
fn
write_method_call
(
&
self
,
hir_id
:
hir
::
HirId
,
method
:
MethodCallee
<
'tcx
>
)
{
debug!
(
"write_method_call(hir_id={:?}, method={:?})"
,
hir_id
,
method
);
self
.tables
.borrow_mut
()
.type_dependent_defs_mut
()
.insert
(
hir_id
,
Def
::
Method
(
method
.def_id
));
self
.write_substs
(
hir_id
,
method
.substs
);
// When the method is confirmed, the `method.substs` includes
// parameters from not just the method, but also the impl of
// the method -- in particular, the `Self` type will be fully
// resolved. However, those are not something that the "user
// specified" -- i.e., those types come from the inferred type
// of the receiver, not something the user wrote. So when we
// create the user-substs, we want to replace those earlier
// types with just the types that the user actually wrote --
// that is, those that appear on the *method itself*.
//
// As an example, if the user wrote something like
// `foo.bar::<u32>(...)` -- the `Self` type here will be the
// type of `foo` (possibly adjusted), but we don't want to
// include that. We want just the `[_, u32]` part.
if
!
method
.substs
.is_noop
()
{
let
method_generics
=
self
.tcx
.generics_of
(
method
.def_id
);
if
!
method_generics
.params
.is_empty
()
{
let
user_substs
=
self
.infcx
.probe
(|
_
|
{
let
just_method_substs
=
Substs
::
for_item
(
self
.tcx
,
method
.def_id
,
|
param
,
_
|
{
let
i
=
param
.index
as
usize
;
if
i
<
method_generics
.parent_count
{
self
.infcx
.var_for_def
(
DUMMY_SP
,
param
)
}
else
{
method
.substs
[
i
]
}
});
self
.infcx
.canonicalize_response
(
&
just_method_substs
)
});
debug!
(
"write_method_call: user_substs = {:?}"
,
user_substs
);
self
.write_user_substs
(
hir_id
,
user_substs
);
}
}
}
pub
fn
write_substs
(
&
self
,
node_id
:
hir
::
HirId
,
substs
:
&
'tcx
Substs
<
'tcx
>
)
{
...
...
@@ -2076,6 +2113,21 @@ pub fn write_substs(&self, node_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
}
}
pub
fn
write_user_substs
(
&
self
,
node_id
:
hir
::
HirId
,
substs
:
CanonicalSubsts
<
'tcx
>
)
{
debug!
(
"write_user_substs({:?}, {:?}) in fcx {}"
,
node_id
,
substs
,
self
.tag
(),
);
if
!
substs
.is_identity
()
{
self
.tables
.borrow_mut
()
.user_substs_mut
()
.insert
(
node_id
,
substs
);
}
else
{
debug!
(
"write_user_substs: skipping identity substs"
);
}
}
pub
fn
apply_adjustments
(
&
self
,
expr
:
&
hir
::
Expr
,
adj
:
Vec
<
Adjustment
<
'tcx
>>
)
{
debug!
(
"apply_adjustments(expr={:?}, adj={:?})"
,
expr
,
adj
);
...
...
@@ -5083,7 +5135,15 @@ pub fn instantiate_value_path(&self,
debug!
(
"instantiate_value_path: type of {:?} is {:?}"
,
node_id
,
ty_substituted
);
self
.write_substs
(
self
.tcx.hir
.node_to_hir_id
(
node_id
),
substs
);
let
hir_id
=
self
.tcx.hir
.node_to_hir_id
(
node_id
);
self
.write_substs
(
hir_id
,
substs
);
if
!
substs
.is_noop
()
{
let
user_substs
=
self
.infcx
.canonicalize_response
(
&
substs
);
debug!
(
"instantiate_value_path: user_substs = {:?}"
,
user_substs
);
self
.write_user_substs
(
hir_id
,
user_substs
);
}
ty_substituted
}
...
...
src/librustc_typeck/check/writeback.rs
浏览文件 @
d7d4d7c8
...
...
@@ -35,7 +35,11 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type
let
item_id
=
self
.tcx.hir
.body_owner
(
body
.id
());
let
item_def_id
=
self
.tcx.hir
.local_def_id
(
item_id
);
let
mut
wbcx
=
WritebackCx
::
new
(
self
,
body
);
// This attribute causes us to dump some writeback information
// in the form of errors, which is used for unit tests.
let
rustc_dump_user_substs
=
self
.tcx
.has_attr
(
item_def_id
,
"rustc_dump_user_substs"
);
let
mut
wbcx
=
WritebackCx
::
new
(
self
,
body
,
rustc_dump_user_substs
);
for
arg
in
&
body
.arguments
{
wbcx
.visit_node_id
(
arg
.pat.span
,
arg
.hir_id
);
}
...
...
@@ -84,12 +88,15 @@ struct WritebackCx<'cx, 'gcx: 'cx + 'tcx, 'tcx: 'cx> {
tables
:
ty
::
TypeckTables
<
'gcx
>
,
body
:
&
'gcx
hir
::
Body
,
rustc_dump_user_substs
:
bool
,
}
impl
<
'cx
,
'gcx
,
'tcx
>
WritebackCx
<
'cx
,
'gcx
,
'tcx
>
{
fn
new
(
fcx
:
&
'cx
FnCtxt
<
'cx
,
'gcx
,
'tcx
>
,
body
:
&
'gcx
hir
::
Body
,
rustc_dump_user_substs
:
bool
,
)
->
WritebackCx
<
'cx
,
'gcx
,
'tcx
>
{
let
owner
=
fcx
.tcx.hir
.definitions
()
.node_to_hir_id
(
body
.id
()
.node_id
);
...
...
@@ -97,6 +104,7 @@ fn new(
fcx
,
tables
:
ty
::
TypeckTables
::
empty
(
Some
(
DefId
::
local
(
owner
.owner
))),
body
,
rustc_dump_user_substs
,
}
}
...
...
@@ -558,6 +566,22 @@ fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) {
assert
!
(
!
substs
.needs_infer
()
&&
!
substs
.has_skol
());
self
.tables
.node_substs_mut
()
.insert
(
hir_id
,
substs
);
}
// Copy over any user-substs
if
let
Some
(
user_substs
)
=
self
.fcx.tables
.borrow
()
.user_substs
(
hir_id
)
{
let
user_substs
=
self
.tcx
()
.lift_to_global
(
&
user_substs
)
.unwrap
();
self
.tables
.user_substs_mut
()
.insert
(
hir_id
,
user_substs
);
// Unit-testing mechanism:
if
self
.rustc_dump_user_substs
{
let
node_id
=
self
.tcx
()
.hir
.hir_to_node_id
(
hir_id
);
let
span
=
self
.tcx
()
.hir
.span
(
node_id
);
self
.tcx
()
.sess
.span_err
(
span
,
&
format!
(
"user substs: {:?}"
,
user_substs
),
);
}
}
}
fn
visit_adjustments
(
&
mut
self
,
span
:
Span
,
hir_id
:
hir
::
HirId
)
{
...
...
src/libsyntax/feature_gate.rs
浏览文件 @
d7d4d7c8
...
...
@@ -865,6 +865,12 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
is just used for rustc unit tests
\
and will never be stable"
,
cfg_fn!
(
rustc_attrs
))),
(
"rustc_dump_user_substs"
,
Whitelisted
,
Gated
(
Stability
::
Unstable
,
"rustc_attrs"
,
"the `#[rustc_error]` attribute
\
is just used for rustc unit tests
\
and will never be stable"
,
cfg_fn!
(
rustc_attrs
))),
(
"rustc_if_this_changed"
,
Whitelisted
,
Gated
(
Stability
::
Unstable
,
"rustc_attrs"
,
"the `#[rustc_if_this_changed]` attribute
\
...
...
src/test/ui/nll/user-annotations/dump-fn-method.rs
0 → 100644
浏览文件 @
d7d4d7c8
// Copyright 2017 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.
// Unit test for the "user substitutions" that are annotated on each
// node.
// compile-flags:-Zverbose
#![feature(nll)]
#![feature(rustc_attrs)]
trait
Bazoom
<
T
>
{
fn
method
<
U
>
(
&
self
,
arg
:
T
,
arg2
:
U
)
{
}
}
impl
<
T
,
U
>
Bazoom
<
U
>
for
T
{
}
fn
foo
<
'a
,
T
>
(
_
:
T
)
{
}
#[rustc_dump_user_substs]
fn
main
()
{
// Here: nothing is given, so we don't have any annotation.
let
x
=
foo
;
x
(
22
);
// Here: `u32` is given.
let
x
=
foo
::
<
u32
>
;
//~ ERROR [u32]
x
(
22
);
// Here: we only want the `T` to be given, the rest should be variables.
let
x
=
<
_
as
Bazoom
<
u32
>>
::
method
::
<
_
>
;
//~ ERROR [?0, u32, ?1]
x
(
&
22
,
44
,
66
);
// Here: all are given
let
x
=
<
u8
as
Bazoom
<
u16
>>
::
method
::
<
u32
>
;
//~ ERROR [u8, u16, u32]
x
(
&
22
,
44
,
66
);
// Here: we want in particular that *only* the method `U`
// annotation is given, the rest are variables.
let
y
=
22_u32
;
y
.method
::
<
u32
>
(
44
,
66
);
//~ ERROR [?0, ?1, u32]
// Here: nothing is given, so we don't have any annotation.
let
y
=
22_u32
;
y
.method
(
44
,
66
);
}
src/test/ui/nll/user-annotations/dump-fn-method.stderr
0 → 100644
浏览文件 @
d7d4d7c8
error: user substs: Canonical { variables: [], value: [u32] }
--> $DIR/dump-fn-method.rs:35:13
|
LL | let x = foo::<u32>; //~ ERROR [u32]
| ^^^^^^^^^^
error: user substs: Canonical { variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: [?0, u32, ?1] }
--> $DIR/dump-fn-method.rs:39:13
|
LL | let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [?0, u32, ?1]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: user substs: Canonical { variables: [], value: [u8, u16, u32] }
--> $DIR/dump-fn-method.rs:43:13
|
LL | let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: user substs: Canonical { variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: [?0, ?1, u32] }
--> $DIR/dump-fn-method.rs:49:5
|
LL | y.method::<u32>(44, 66); //~ ERROR [?0, ?1, u32]
| ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录