Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
97bf80df
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,发现更多精彩内容 >>
提交
97bf80df
编写于
8月 24, 2021
作者:
J
jackh726
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Treat types in unnormalized function signatures as well-formed
上级
b03ccace
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
90 addition
and
9 deletion
+90
-9
compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs
..._mir/src/borrow_check/type_check/free_region_relations.rs
+17
-2
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/compare_method.rs
+11
-1
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/mod.rs
+12
-4
compiler/rustc_typeck/src/check/regionck.rs
compiler/rustc_typeck/src/check/regionck.rs
+10
-1
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/check/wfcheck.rs
+10
-1
src/test/ui/generic-associated-types/issue-87748.rs
src/test/ui/generic-associated-types/issue-87748.rs
+30
-0
未找到文件。
compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs
浏览文件 @
97bf80df
...
...
@@ -256,6 +256,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
let
constraint_sets
:
Vec
<
_
>
=
unnormalized_input_output_tys
.flat_map
(|
ty
|
{
debug!
(
"build: input_or_output={:?}"
,
ty
);
// We add implied bounds from both the unnormalized and normalized ty
// See issue #87748
let
constraints_implied_1
=
self
.add_implied_bounds
(
ty
);
let
TypeOpOutput
{
output
:
ty
,
constraints
:
constraints1
,
..
}
=
self
.param_env
.and
(
type_op
::
normalize
::
Normalize
::
new
(
ty
))
...
...
@@ -271,9 +274,21 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
canonicalized_query
:
None
,
}
});
let
constraints2
=
self
.add_implied_bounds
(
ty
);
// Note: we need this in examples like
// ```
// trait Foo {
// type Bar;
// fn foo(&self) -> &Self::Bar;
// }
// impl Foo for () {
// type Bar = ();
// fn foo(&self) ->&() {}
// }
// ```
// Both &Self::Bar and &() are WF
let
constraints_implied_2
=
self
.add_implied_bounds
(
ty
);
normalized_inputs_and_output
.push
(
ty
);
constraints1
.into_iter
()
.chain
(
constraints2
)
constraints1
.into_iter
()
.chain
(
constraints
_implied_1
)
.chain
(
constraints_implied_
2
)
})
.collect
();
...
...
compiler/rustc_typeck/src/check/compare_method.rs
浏览文件 @
97bf80df
...
...
@@ -250,6 +250,8 @@ fn compare_predicate_entailment<'tcx>(
// Compute placeholder form of impl and trait method tys.
let
tcx
=
infcx
.tcx
;
let
mut
wf_tys
=
vec!
[];
let
(
impl_sig
,
_
)
=
infcx
.replace_bound_vars_with_fresh_vars
(
impl_m_span
,
infer
::
HigherRankedType
,
...
...
@@ -260,10 +262,18 @@ fn compare_predicate_entailment<'tcx>(
let
impl_fty
=
tcx
.mk_fn_ptr
(
ty
::
Binder
::
dummy
(
impl_sig
));
debug!
(
"compare_impl_method: impl_fty={:?}"
,
impl_fty
);
// First liberate late bound regions and subst placeholders
let
trait_sig
=
tcx
.liberate_late_bound_regions
(
impl_m
.def_id
,
tcx
.fn_sig
(
trait_m
.def_id
));
let
trait_sig
=
trait_sig
.subst
(
tcx
,
trait_to_placeholder_substs
);
// Next, add all inputs and output as well-formed tys. Importantly,
// we have to do this before normalization, since the normalized ty may
// not contain the input parameters. See issue #87748.
wf_tys
.extend
(
trait_sig
.inputs_and_output
.iter
());
let
trait_sig
=
inh
.normalize_associated_types_in
(
impl_m_span
,
impl_m_hir_id
,
param_env
,
trait_sig
);
// Also add the resulting inputs and output as well-formed.
// This probably isn't strictly necessary.
wf_tys
.extend
(
trait_sig
.inputs_and_output
.iter
());
let
trait_fty
=
tcx
.mk_fn_ptr
(
ty
::
Binder
::
dummy
(
trait_sig
));
debug!
(
"compare_impl_method: trait_fty={:?}"
,
trait_fty
);
...
...
@@ -388,7 +398,7 @@ fn compare_predicate_entailment<'tcx>(
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
let
fcx
=
FnCtxt
::
new
(
&
inh
,
param_env
,
impl_m_hir_id
);
fcx
.regionck_item
(
impl_m_hir_id
,
impl_m_span
,
trait_sig
.inputs_and_output
);
fcx
.regionck_item
(
impl_m_hir_id
,
impl_m_span
,
&
wf_tys
);
Ok
(())
})
...
...
compiler/rustc_typeck/src/check/mod.rs
浏览文件 @
97bf80df
...
...
@@ -364,7 +364,7 @@ fn typeck_with_fallback<'tcx>(
let
typeck_results
=
Inherited
::
build
(
tcx
,
def_id
)
.enter
(|
inh
|
{
let
param_env
=
tcx
.param_env
(
def_id
);
let
fcx
=
if
let
Some
(
hir
::
FnSig
{
header
,
decl
,
..
})
=
fn_sig
{
let
(
fcx
,
wf_tys
)
=
if
let
Some
(
hir
::
FnSig
{
header
,
decl
,
..
})
=
fn_sig
{
let
fn_sig
=
if
crate
::
collect
::
get_infer_ret_ty
(
&
decl
.output
)
.is_some
()
{
let
fcx
=
FnCtxt
::
new
(
&
inh
,
param_env
,
body
.value.hir_id
);
<
dyn
AstConv
<
'_
>>
::
ty_of_fn
(
...
...
@@ -383,17 +383,25 @@ fn typeck_with_fallback<'tcx>(
check_abi
(
tcx
,
id
,
span
,
fn_sig
.abi
());
// When normalizing the function signature, we assume all types are
// well-formed. So, we don't need to worry about the obligations
// from normalization. We could just discard these, but to align with
// compare_method and elsewhere, we just add implied bounds for
// these types.
let
mut
wf_tys
=
vec!
[];
// Compute the fty from point of view of inside the fn.
let
fn_sig
=
tcx
.liberate_late_bound_regions
(
def_id
.to_def_id
(),
fn_sig
);
wf_tys
.extend
(
fn_sig
.inputs_and_output
.iter
());
let
fn_sig
=
inh
.normalize_associated_types_in
(
body
.value.span
,
body_id
.hir_id
,
param_env
,
fn_sig
,
);
wf_tys
.extend
(
fn_sig
.inputs_and_output
.iter
());
let
fcx
=
check_fn
(
&
inh
,
param_env
,
fn_sig
,
decl
,
id
,
body
,
None
,
true
)
.0
;
fcx
(
fcx
,
wf_tys
)
}
else
{
let
fcx
=
FnCtxt
::
new
(
&
inh
,
param_env
,
body
.value.hir_id
);
let
expected_type
=
body_ty
...
...
@@ -443,7 +451,7 @@ fn typeck_with_fallback<'tcx>(
fcx
.write_ty
(
id
,
expected_type
);
fcx
(
fcx
,
vec!
[])
};
let
fallback_has_occurred
=
fcx
.type_inference_fallback
();
...
...
@@ -467,7 +475,7 @@ fn typeck_with_fallback<'tcx>(
fcx
.select_all_obligations_or_error
();
if
fn_sig
.is_some
()
{
fcx
.regionck_fn
(
id
,
body
);
fcx
.regionck_fn
(
id
,
body
,
span
,
&
wf_tys
);
}
else
{
fcx
.regionck_expr
(
body
);
}
...
...
compiler/rustc_typeck/src/check/regionck.rs
浏览文件 @
97bf80df
...
...
@@ -144,11 +144,20 @@ pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]
/// rest of type check and because sometimes we need type
/// inference to have completed before we can determine which
/// constraints to add.
pub
fn
regionck_fn
(
&
self
,
fn_id
:
hir
::
HirId
,
body
:
&
'tcx
hir
::
Body
<
'tcx
>
)
{
pub
(
crate
)
fn
regionck_fn
(
&
self
,
fn_id
:
hir
::
HirId
,
body
:
&
'tcx
hir
::
Body
<
'tcx
>
,
span
:
Span
,
wf_tys
:
&
[
Ty
<
'tcx
>
],
)
{
debug!
(
"regionck_fn(id={})"
,
fn_id
);
let
subject
=
self
.tcx
.hir
()
.body_owner_def_id
(
body
.id
());
let
hir_id
=
body
.value.hir_id
;
let
mut
rcx
=
RegionCtxt
::
new
(
self
,
hir_id
,
Subject
(
subject
),
self
.param_env
);
// We need to add the implied bounds from the function signature
rcx
.outlives_environment
.add_implied_bounds
(
self
,
wf_tys
,
fn_id
,
span
);
rcx
.outlives_environment
.save_implied_bounds
(
fn_id
);
if
!
self
.errors_reported_since_creation
()
{
// regionck assumes typeck succeeded
...
...
compiler/rustc_typeck/src/check/wfcheck.rs
浏览文件 @
97bf80df
...
...
@@ -908,6 +908,7 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy
}
}
#[tracing::instrument(level
=
"debug"
,
skip(fcx,
span,
hir_decl))]
fn
check_fn_or_method
<
'fcx
,
'tcx
>
(
fcx
:
&
FnCtxt
<
'fcx
,
'tcx
>
,
span
:
Span
,
...
...
@@ -918,6 +919,11 @@ fn check_fn_or_method<'fcx, 'tcx>(
)
{
let
sig
=
fcx
.tcx
.liberate_late_bound_regions
(
def_id
,
sig
);
// Unnormalized types in signature are WF too
implied_bounds
.extend
(
sig
.inputs
());
// FIXME(#27579) return types should not be implied bounds
implied_bounds
.push
(
sig
.output
());
// Normalize the input and output types one at a time, using a different
// `WellFormedLoc` for each. We cannot call `normalize_associated_types`
// on the entire `FnSig`, since this would use the same `WellFormedLoc`
...
...
@@ -967,9 +973,11 @@ fn check_fn_or_method<'fcx, 'tcx>(
ObligationCauseCode
::
ReturnType
,
);
// FIXME(#2
575
9) return types should not be implied bounds
// FIXME(#2
757
9) return types should not be implied bounds
implied_bounds
.push
(
sig
.output
());
debug!
(
?
implied_bounds
);
check_where_clauses
(
fcx
,
span
,
def_id
,
Some
((
sig
.output
(),
hir_decl
.output
.span
())));
}
...
...
@@ -1116,6 +1124,7 @@ fn check_opaque_types<'fcx, 'tcx>(
`self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one
\
of the previous types except `Self`)"
;
#[tracing::instrument(level
=
"debug"
,
skip(fcx))]
fn
check_method_receiver
<
'fcx
,
'tcx
>
(
fcx
:
&
FnCtxt
<
'fcx
,
'tcx
>
,
fn_sig
:
&
hir
::
FnSig
<
'_
>
,
...
...
src/test/ui/generic-associated-types/issue-87748.rs
0 → 100644
浏览文件 @
97bf80df
// Checks that we properly add implied bounds from unnormalized projections in
// inputs when typechecking functions.
// check-pass
#![feature(generic_associated_types)]
trait
MyTrait
{
type
Assoc
<
'a
,
'b
>
where
'b
:
'a
;
fn
do_sth
(
arg
:
Self
::
Assoc
<
'_
,
'_
>
);
}
struct
A
;
struct
B
;
struct
C
;
impl
MyTrait
for
A
{
type
Assoc
<
'a
,
'b
>
where
'b
:
'a
=
u32
;
fn
do_sth
(
_
:
u32
)
{}
}
impl
MyTrait
for
B
{
type
Assoc
<
'a
,
'b
>
where
'b
:
'a
=
u32
;
fn
do_sth
(
_
:
Self
::
Assoc
<
'_
,
'_
>
)
{}
}
impl
MyTrait
for
C
{
type
Assoc
<
'a
,
'b
>
where
'b
:
'a
=
u32
;
fn
do_sth
(
_
:
Self
::
Assoc
<
'static
,
'static
>
)
{}
}
fn
main
()
{}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录