Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
9eeaf1fd
R
Rust
项目概览
int
/
Rust
12 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
9eeaf1fd
编写于
8月 04, 2023
作者:
L
lcnr
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
normalize in `trait_ref_is_knowable` in new solver
上级
1e836d12
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
214 addition
and
83 deletion
+214
-83
compiler/rustc_trait_selection/src/solve/assembly/mod.rs
compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+35
-19
compiler/rustc_trait_selection/src/solve/mod.rs
compiler/rustc_trait_selection/src/solve/mod.rs
+31
-0
compiler/rustc_trait_selection/src/solve/trait_goals.rs
compiler/rustc_trait_selection/src/solve/trait_goals.rs
+1
-38
compiler/rustc_trait_selection/src/traits/coherence.rs
compiler/rustc_trait_selection/src/traits/coherence.rs
+43
-25
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
+1
-1
tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.rs
...w-solver/coherence/trait_ref_is_knowable-norm-overflow.rs
+20
-0
tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
...lver/coherence/trait_ref_is_knowable-norm-overflow.stderr
+12
-0
tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-1.rs
...solver/coherence/trait_ref_is_knowable-normalization-1.rs
+22
-0
tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-2.rs
...solver/coherence/trait_ref_is_knowable-normalization-2.rs
+25
-0
tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-3.rs
...solver/coherence/trait_ref_is_knowable-normalization-3.rs
+24
-0
未找到文件。
compiler/rustc_trait_selection/src/solve/assembly/mod.rs
浏览文件 @
9eeaf1fd
...
@@ -316,6 +316,8 @@ pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>(
...
@@ -316,6 +316,8 @@ pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>(
self
.assemble_param_env_candidates
(
goal
,
&
mut
candidates
);
self
.assemble_param_env_candidates
(
goal
,
&
mut
candidates
);
self
.assemble_coherence_unknowable_candidates
(
goal
,
&
mut
candidates
);
candidates
candidates
}
}
...
@@ -363,10 +365,7 @@ fn assemble_candidates_via_self_ty<G: GoalKind<'tcx>>(
...
@@ -363,10 +365,7 @@ fn assemble_candidates_via_self_ty<G: GoalKind<'tcx>>(
self
.assemble_object_bound_candidates
(
goal
,
&
mut
candidates
);
self
.assemble_object_bound_candidates
(
goal
,
&
mut
candidates
);
self
.assemble_coherence_unknowable_candidates
(
goal
,
&
mut
candidates
);
self
.assemble_candidates_after_normalizing_self_ty
(
goal
,
&
mut
candidates
,
num_steps
);
self
.assemble_candidates_after_normalizing_self_ty
(
goal
,
&
mut
candidates
,
num_steps
);
candidates
candidates
}
}
...
@@ -877,26 +876,43 @@ fn assemble_coherence_unknowable_candidates<G: GoalKind<'tcx>>(
...
@@ -877,26 +876,43 @@ fn assemble_coherence_unknowable_candidates<G: GoalKind<'tcx>>(
goal
:
Goal
<
'tcx
,
G
>
,
goal
:
Goal
<
'tcx
,
G
>
,
candidates
:
&
mut
Vec
<
Candidate
<
'tcx
>>
,
candidates
:
&
mut
Vec
<
Candidate
<
'tcx
>>
,
)
{
)
{
let
tcx
=
self
.tcx
();
match
self
.solver_mode
()
{
match
self
.solver_mode
()
{
SolverMode
::
Normal
=>
return
,
SolverMode
::
Normal
=>
return
,
SolverMode
::
Coherence
=>
{
SolverMode
::
Coherence
=>
{}
let
trait_ref
=
goal
.predicate
.trait_ref
(
self
.tcx
());
};
match
coherence
::
trait_ref_is_knowable
(
self
.tcx
(),
trait_ref
)
{
Ok
(())
=>
{}
let
result
=
self
.probe_candidate
(
"coherence unknowable"
)
.enter
(|
ecx
|
{
Err
(
_
)
=>
match
self
let
trait_ref
=
goal
.predicate
.trait_ref
(
tcx
);
.evaluate_added_goals_and_make_canonical_response
(
Certainty
::
AMBIGUOUS
)
{
#[derive(Debug)]
Ok
(
result
)
=>
candidates
.push
(
Candidate
{
enum
FailureKind
{
source
:
CandidateSource
::
BuiltinImpl
(
BuiltinImplSource
::
Misc
),
Overflow
,
result
,
NoSolution
(
NoSolution
),
}),
}
// FIXME: This will be reachable at some point if we're in
let
lazily_normalize_ty
=
|
ty
|
match
ecx
.try_normalize_ty
(
goal
.param_env
,
ty
)
{
// `assemble_candidates_after_normalizing_self_ty` and we get a
Ok
(
Some
(
ty
))
=>
Ok
(
ty
),
// universe error. We'll deal with it at this point.
Ok
(
None
)
=>
Err
(
FailureKind
::
Overflow
),
Err
(
NoSolution
)
=>
bug!
(
"coherence candidate resulted in NoSolution"
),
Err
(
e
)
=>
Err
(
FailureKind
::
NoSolution
(
e
)),
},
};
match
coherence
::
trait_ref_is_knowable
(
tcx
,
trait_ref
,
lazily_normalize_ty
)
{
Err
(
FailureKind
::
Overflow
)
=>
{
ecx
.evaluate_added_goals_and_make_canonical_response
(
Certainty
::
OVERFLOW
)
}
Err
(
FailureKind
::
NoSolution
(
NoSolution
))
|
Ok
(
Ok
(()))
=>
Err
(
NoSolution
),
Ok
(
Err
(
_
))
=>
{
ecx
.evaluate_added_goals_and_make_canonical_response
(
Certainty
::
AMBIGUOUS
)
}
}
}
}
});
match
result
{
Ok
(
result
)
=>
candidates
.push
(
Candidate
{
source
:
CandidateSource
::
BuiltinImpl
(
BuiltinImplSource
::
Misc
),
result
,
}),
Err
(
NoSolution
)
=>
{}
}
}
}
}
...
...
compiler/rustc_trait_selection/src/solve/mod.rs
浏览文件 @
9eeaf1fd
...
@@ -283,6 +283,37 @@ fn flounder(&mut self, responses: &[CanonicalResponse<'tcx>]) -> QueryResult<'tc
...
@@ -283,6 +283,37 @@ fn flounder(&mut self, responses: &[CanonicalResponse<'tcx>]) -> QueryResult<'tc
Ok
(
self
.make_ambiguous_response_no_constraints
(
maybe_cause
))
Ok
(
self
.make_ambiguous_response_no_constraints
(
maybe_cause
))
}
}
/// Normalize a type when it is structually matched on.
///
/// For self types this is generally already handled through
/// `assemble_candidates_after_normalizing_self_ty`, so anything happening
/// in [`EvalCtxt::assemble_candidates_via_self_ty`] does not have to normalize
/// the self type. It is required when structurally matching on any other
/// arguments of a trait goal, e.g. when assembling builtin unsize candidates.
fn
try_normalize_ty
(
&
mut
self
,
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
mut
ty
:
Ty
<
'tcx
>
,
)
->
Result
<
Option
<
Ty
<
'tcx
>>
,
NoSolution
>
{
for
_
in
0
..
self
.local_overflow_limit
()
{
let
ty
::
Alias
(
_
,
projection_ty
)
=
*
ty
.kind
()
else
{
return
Ok
(
Some
(
ty
));
};
let
normalized_ty
=
self
.next_ty_infer
();
let
normalizes_to_goal
=
Goal
::
new
(
self
.tcx
(),
param_env
,
ty
::
ProjectionPredicate
{
projection_ty
,
term
:
normalized_ty
.into
()
},
);
self
.add_goal
(
normalizes_to_goal
);
self
.try_evaluate_added_goals
()
?
;
ty
=
self
.resolve_vars_if_possible
(
normalized_ty
);
}
Ok
(
None
)
}
}
}
fn
response_no_constraints_raw
<
'tcx
>
(
fn
response_no_constraints_raw
<
'tcx
>
(
...
...
compiler/rustc_trait_selection/src/solve/trait_goals.rs
浏览文件 @
9eeaf1fd
...
@@ -448,7 +448,7 @@ fn consider_builtin_unsize_candidates(
...
@@ -448,7 +448,7 @@ fn consider_builtin_unsize_candidates(
// We need to normalize the b_ty since it's matched structurally
// We need to normalize the b_ty since it's matched structurally
// in the other functions below.
// in the other functions below.
let
b_ty
=
match
ecx
let
b_ty
=
match
ecx
.
normalize_non_self_ty
(
goal
.predicate.trait_ref.args
.type_at
(
1
),
goal
.param_env
)
.
try_normalize_ty
(
goal
.param_env
,
goal
.predicate.trait_ref.args
.type_at
(
1
)
)
{
{
Ok
(
Some
(
b_ty
))
=>
b_ty
,
Ok
(
Some
(
b_ty
))
=>
b_ty
,
Ok
(
None
)
=>
return
vec!
[
misc_candidate
(
ecx
,
Certainty
::
OVERFLOW
)],
Ok
(
None
)
=>
return
vec!
[
misc_candidate
(
ecx
,
Certainty
::
OVERFLOW
)],
...
@@ -927,41 +927,4 @@ pub(super) fn compute_trait_goal(
...
@@ -927,41 +927,4 @@ pub(super) fn compute_trait_goal(
let
candidates
=
self
.assemble_and_evaluate_candidates
(
goal
);
let
candidates
=
self
.assemble_and_evaluate_candidates
(
goal
);
self
.merge_candidates
(
candidates
)
self
.merge_candidates
(
candidates
)
}
}
/// Normalize a non-self type when it is structually matched on when solving
/// a built-in goal.
///
/// This is handled already through `assemble_candidates_after_normalizing_self_ty`
/// for the self type, but for other goals, additional normalization of other
/// arguments may be needed to completely implement the semantics of the trait.
///
/// This is required when structurally matching on any trait argument that is
/// not the self type.
fn
normalize_non_self_ty
(
&
mut
self
,
mut
ty
:
Ty
<
'tcx
>
,
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
)
->
Result
<
Option
<
Ty
<
'tcx
>>
,
NoSolution
>
{
if
!
matches!
(
ty
.kind
(),
ty
::
Alias
(
..
))
{
return
Ok
(
Some
(
ty
));
}
for
_
in
0
..
self
.local_overflow_limit
()
{
let
ty
::
Alias
(
_
,
projection_ty
)
=
*
ty
.kind
()
else
{
return
Ok
(
Some
(
ty
));
};
let
normalized_ty
=
self
.next_ty_infer
();
let
normalizes_to_goal
=
Goal
::
new
(
self
.tcx
(),
param_env
,
ty
::
ProjectionPredicate
{
projection_ty
,
term
:
normalized_ty
.into
()
},
);
self
.add_goal
(
normalizes_to_goal
);
self
.try_evaluate_added_goals
()
?
;
ty
=
self
.resolve_vars_if_possible
(
normalized_ty
);
}
Ok
(
None
)
}
}
}
compiler/rustc_trait_selection/src/traits/coherence.rs
浏览文件 @
9eeaf1fd
...
@@ -452,22 +452,23 @@ fn prove_negated_obligation<'tcx>(
...
@@ -452,22 +452,23 @@ fn prove_negated_obligation<'tcx>(
/// This both checks whether any downstream or sibling crates could
/// This both checks whether any downstream or sibling crates could
/// implement it and whether an upstream crate can add this impl
/// implement it and whether an upstream crate can add this impl
/// without breaking backwards compatibility.
/// without breaking backwards compatibility.
#[instrument(level
=
"debug"
,
skip(tcx),
ret)]
#[instrument(level
=
"debug"
,
skip(tcx
,
lazily_normalize_ty
),
ret)]
pub
fn
trait_ref_is_knowable
<
'tcx
>
(
pub
fn
trait_ref_is_knowable
<
'tcx
,
E
:
Debug
>
(
tcx
:
TyCtxt
<
'tcx
>
,
tcx
:
TyCtxt
<
'tcx
>
,
trait_ref
:
ty
::
TraitRef
<
'tcx
>
,
trait_ref
:
ty
::
TraitRef
<
'tcx
>
,
)
->
Result
<
(),
Conflict
>
{
mut
lazily_normalize_ty
:
impl
FnMut
(
Ty
<
'tcx
>
)
->
Result
<
Ty
<
'tcx
>
,
E
>
,
)
->
Result
<
Result
<
(),
Conflict
>
,
E
>
{
if
Some
(
trait_ref
.def_id
)
==
tcx
.lang_items
()
.fn_ptr_trait
()
{
if
Some
(
trait_ref
.def_id
)
==
tcx
.lang_items
()
.fn_ptr_trait
()
{
// The only types implementing `FnPtr` are function pointers,
// The only types implementing `FnPtr` are function pointers,
// so if there's no impl of `FnPtr` in the current crate,
// so if there's no impl of `FnPtr` in the current crate,
// then such an impl will never be added in the future.
// then such an impl will never be added in the future.
return
Ok
(
(
));
return
Ok
(
Ok
(()
));
}
}
if
orphan_check_trait_ref
(
trait_ref
,
InCrate
::
Remote
)
.is_ok
()
{
if
orphan_check_trait_ref
(
trait_ref
,
InCrate
::
Remote
,
&
mut
lazily_normalize_ty
)
?
.is_ok
()
{
// A downstream or cousin crate is allowed to implement some
// A downstream or cousin crate is allowed to implement some
// substitution of this trait-ref.
// substitution of this trait-ref.
return
Err
(
Conflict
::
Downstream
);
return
Ok
(
Err
(
Conflict
::
Downstream
)
);
}
}
if
trait_ref_is_local_or_fundamental
(
tcx
,
trait_ref
)
{
if
trait_ref_is_local_or_fundamental
(
tcx
,
trait_ref
)
{
...
@@ -476,7 +477,7 @@ pub fn trait_ref_is_knowable<'tcx>(
...
@@ -476,7 +477,7 @@ pub fn trait_ref_is_knowable<'tcx>(
// allowed to implement a substitution of this trait ref, which
// allowed to implement a substitution of this trait ref, which
// means impls could only come from dependencies of this crate,
// means impls could only come from dependencies of this crate,
// which we already know about.
// which we already know about.
return
Ok
(
(
));
return
Ok
(
Ok
(()
));
}
}
// This is a remote non-fundamental trait, so if another crate
// This is a remote non-fundamental trait, so if another crate
...
@@ -487,10 +488,10 @@ pub fn trait_ref_is_knowable<'tcx>(
...
@@ -487,10 +488,10 @@ pub fn trait_ref_is_knowable<'tcx>(
// and if we are an intermediate owner, then we don't care
// and if we are an intermediate owner, then we don't care
// about future-compatibility, which means that we're OK if
// about future-compatibility, which means that we're OK if
// we are an owner.
// we are an owner.
if
orphan_check_trait_ref
(
trait_ref
,
InCrate
::
Local
)
.is_ok
()
{
if
orphan_check_trait_ref
(
trait_ref
,
InCrate
::
Local
,
&
mut
lazily_normalize_ty
)
?
.is_ok
()
{
Ok
(
(
))
Ok
(
Ok
(()
))
}
else
{
}
else
{
Err
(
Conflict
::
Upstream
)
Ok
(
Err
(
Conflict
::
Upstream
)
)
}
}
}
}
...
@@ -526,7 +527,7 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
...
@@ -526,7 +527,7 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
return
Ok
(());
return
Ok
(());
}
}
orphan_check_trait_ref
(
trait_ref
,
InCrate
::
Local
)
orphan_check_trait_ref
::
<!>
(
trait_ref
,
InCrate
::
Local
,
|
ty
|
Ok
(
ty
))
.unwrap
(
)
}
}
/// Checks whether a trait-ref is potentially implementable by a crate.
/// Checks whether a trait-ref is potentially implementable by a crate.
...
@@ -615,11 +616,12 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
...
@@ -615,11 +616,12 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
///
///
/// Note that this function is never called for types that have both type
/// Note that this function is never called for types that have both type
/// parameters and inference variables.
/// parameters and inference variables.
#[instrument(level
=
"trace"
,
ret)]
#[instrument(level
=
"trace"
,
skip(lazily_normalize_ty),
ret)]
fn
orphan_check_trait_ref
<
'tcx
>
(
fn
orphan_check_trait_ref
<
'tcx
,
E
:
Debug
>
(
trait_ref
:
ty
::
TraitRef
<
'tcx
>
,
trait_ref
:
ty
::
TraitRef
<
'tcx
>
,
in_crate
:
InCrate
,
in_crate
:
InCrate
,
)
->
Result
<
(),
OrphanCheckErr
<
'tcx
>>
{
lazily_normalize_ty
:
impl
FnMut
(
Ty
<
'tcx
>
)
->
Result
<
Ty
<
'tcx
>
,
E
>
,
)
->
Result
<
Result
<
(),
OrphanCheckErr
<
'tcx
>>
,
E
>
{
if
trait_ref
.has_infer
()
&&
trait_ref
.has_param
()
{
if
trait_ref
.has_infer
()
&&
trait_ref
.has_param
()
{
bug!
(
bug!
(
"can't orphan check a trait ref with both params and inference variables {:?}"
,
"can't orphan check a trait ref with both params and inference variables {:?}"
,
...
@@ -627,9 +629,10 @@ fn orphan_check_trait_ref<'tcx>(
...
@@ -627,9 +629,10 @@ fn orphan_check_trait_ref<'tcx>(
);
);
}
}
let
mut
checker
=
OrphanChecker
::
new
(
in_crate
);
let
mut
checker
=
OrphanChecker
::
new
(
in_crate
,
lazily_normalize_ty
);
match
trait_ref
.visit_with
(
&
mut
checker
)
{
Ok
(
match
trait_ref
.visit_with
(
&
mut
checker
)
{
ControlFlow
::
Continue
(())
=>
Err
(
OrphanCheckErr
::
NonLocalInputType
(
checker
.non_local_tys
)),
ControlFlow
::
Continue
(())
=>
Err
(
OrphanCheckErr
::
NonLocalInputType
(
checker
.non_local_tys
)),
ControlFlow
::
Break
(
OrphanCheckEarlyExit
::
NormalizationFailure
(
err
))
=>
return
Err
(
err
),
ControlFlow
::
Break
(
OrphanCheckEarlyExit
::
ParamTy
(
ty
))
=>
{
ControlFlow
::
Break
(
OrphanCheckEarlyExit
::
ParamTy
(
ty
))
=>
{
// Does there exist some local type after the `ParamTy`.
// Does there exist some local type after the `ParamTy`.
checker
.search_first_local_ty
=
true
;
checker
.search_first_local_ty
=
true
;
...
@@ -642,34 +645,39 @@ fn orphan_check_trait_ref<'tcx>(
...
@@ -642,34 +645,39 @@ fn orphan_check_trait_ref<'tcx>(
}
}
}
}
ControlFlow
::
Break
(
OrphanCheckEarlyExit
::
LocalTy
(
_
))
=>
Ok
(()),
ControlFlow
::
Break
(
OrphanCheckEarlyExit
::
LocalTy
(
_
))
=>
Ok
(()),
}
}
)
}
}
struct
OrphanChecker
<
'tcx
>
{
struct
OrphanChecker
<
'tcx
,
F
>
{
in_crate
:
InCrate
,
in_crate
:
InCrate
,
in_self_ty
:
bool
,
in_self_ty
:
bool
,
lazily_normalize_ty
:
F
,
/// Ignore orphan check failures and exclusively search for the first
/// Ignore orphan check failures and exclusively search for the first
/// local type.
/// local type.
search_first_local_ty
:
bool
,
search_first_local_ty
:
bool
,
non_local_tys
:
Vec
<
(
Ty
<
'tcx
>
,
bool
)
>
,
non_local_tys
:
Vec
<
(
Ty
<
'tcx
>
,
bool
)
>
,
}
}
impl
<
'tcx
>
OrphanChecker
<
'tcx
>
{
impl
<
'tcx
,
F
,
E
>
OrphanChecker
<
'tcx
,
F
>
fn
new
(
in_crate
:
InCrate
)
->
Self
{
where
F
:
FnOnce
(
Ty
<
'tcx
>
)
->
Result
<
Ty
<
'tcx
>
,
E
>
,
{
fn
new
(
in_crate
:
InCrate
,
lazily_normalize_ty
:
F
)
->
Self
{
OrphanChecker
{
OrphanChecker
{
in_crate
,
in_crate
,
in_self_ty
:
true
,
in_self_ty
:
true
,
lazily_normalize_ty
,
search_first_local_ty
:
false
,
search_first_local_ty
:
false
,
non_local_tys
:
Vec
::
new
(),
non_local_tys
:
Vec
::
new
(),
}
}
}
}
fn
found_non_local_ty
(
&
mut
self
,
t
:
Ty
<
'tcx
>
)
->
ControlFlow
<
OrphanCheckEarlyExit
<
'tcx
>>
{
fn
found_non_local_ty
(
&
mut
self
,
t
:
Ty
<
'tcx
>
)
->
ControlFlow
<
OrphanCheckEarlyExit
<
'tcx
,
E
>>
{
self
.non_local_tys
.push
((
t
,
self
.in_self_ty
));
self
.non_local_tys
.push
((
t
,
self
.in_self_ty
));
ControlFlow
::
Continue
(())
ControlFlow
::
Continue
(())
}
}
fn
found_param_ty
(
&
mut
self
,
t
:
Ty
<
'tcx
>
)
->
ControlFlow
<
OrphanCheckEarlyExit
<
'tcx
>>
{
fn
found_param_ty
(
&
mut
self
,
t
:
Ty
<
'tcx
>
)
->
ControlFlow
<
OrphanCheckEarlyExit
<
'tcx
,
E
>>
{
if
self
.search_first_local_ty
{
if
self
.search_first_local_ty
{
ControlFlow
::
Continue
(())
ControlFlow
::
Continue
(())
}
else
{
}
else
{
...
@@ -685,18 +693,28 @@ fn def_id_is_local(&mut self, def_id: DefId) -> bool {
...
@@ -685,18 +693,28 @@ fn def_id_is_local(&mut self, def_id: DefId) -> bool {
}
}
}
}
enum
OrphanCheckEarlyExit
<
'tcx
>
{
enum
OrphanCheckEarlyExit
<
'tcx
,
E
>
{
NormalizationFailure
(
E
),
ParamTy
(
Ty
<
'tcx
>
),
ParamTy
(
Ty
<
'tcx
>
),
LocalTy
(
Ty
<
'tcx
>
),
LocalTy
(
Ty
<
'tcx
>
),
}
}
impl
<
'tcx
>
TypeVisitor
<
TyCtxt
<
'tcx
>>
for
OrphanChecker
<
'tcx
>
{
impl
<
'tcx
,
F
,
E
>
TypeVisitor
<
TyCtxt
<
'tcx
>>
for
OrphanChecker
<
'tcx
,
F
>
type
BreakTy
=
OrphanCheckEarlyExit
<
'tcx
>
;
where
F
:
FnMut
(
Ty
<
'tcx
>
)
->
Result
<
Ty
<
'tcx
>
,
E
>
,
{
type
BreakTy
=
OrphanCheckEarlyExit
<
'tcx
,
E
>
;
fn
visit_region
(
&
mut
self
,
_
r
:
ty
::
Region
<
'tcx
>
)
->
ControlFlow
<
Self
::
BreakTy
>
{
fn
visit_region
(
&
mut
self
,
_
r
:
ty
::
Region
<
'tcx
>
)
->
ControlFlow
<
Self
::
BreakTy
>
{
ControlFlow
::
Continue
(())
ControlFlow
::
Continue
(())
}
}
fn
visit_ty
(
&
mut
self
,
ty
:
Ty
<
'tcx
>
)
->
ControlFlow
<
Self
::
BreakTy
>
{
fn
visit_ty
(
&
mut
self
,
ty
:
Ty
<
'tcx
>
)
->
ControlFlow
<
Self
::
BreakTy
>
{
// Need to lazily normalize here in with `-Ztrait-solver=next-coherence`.
let
ty
=
match
(
self
.lazily_normalize_ty
)(
ty
)
{
Ok
(
ty
)
=>
ty
,
Err
(
err
)
=>
return
ControlFlow
::
Break
(
OrphanCheckEarlyExit
::
NormalizationFailure
(
err
)),
};
let
result
=
match
*
ty
.kind
()
{
let
result
=
match
*
ty
.kind
()
{
ty
::
Bool
ty
::
Bool
|
ty
::
Char
|
ty
::
Char
...
...
compiler/rustc_trait_selection/src/traits/select/mod.rs
浏览文件 @
9eeaf1fd
...
@@ -1457,7 +1457,7 @@ fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<
...
@@ -1457,7 +1457,7 @@ fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<
// bound regions.
// bound regions.
let
trait_ref
=
predicate
.skip_binder
()
.trait_ref
;
let
trait_ref
=
predicate
.skip_binder
()
.trait_ref
;
coherence
::
trait_ref_is_knowable
(
self
.tcx
(),
trait_ref
)
coherence
::
trait_ref_is_knowable
::
<!>
(
self
.tcx
(),
trait_ref
,
|
ty
|
Ok
(
ty
))
.unwrap
(
)
}
}
/// Returns `true` if the global caches can be used.
/// Returns `true` if the global caches can be used.
...
...
tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.rs
0 → 100644
浏览文件 @
9eeaf1fd
// compile-flags: -Ztrait-solver=next
// Coherence should handle overflow while normalizing for
// `trait_ref_is_knowable` correctly.
trait
Overflow
{
type
Assoc
;
}
impl
<
T
>
Overflow
for
T
{
type
Assoc
=
<
T
as
Overflow
>
::
Assoc
;
}
trait
Trait
{}
impl
<
T
:
Copy
>
Trait
for
T
{}
struct
LocalTy
;
impl
Trait
for
<
LocalTy
as
Overflow
>
::
Assoc
{}
//~^ ERROR conflicting implementations of trait `Trait` for type `<LocalTy as Overflow>::Assoc`
fn
main
()
{}
tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
0 → 100644
浏览文件 @
9eeaf1fd
error[E0119]: conflicting implementations of trait `Trait` for type `<LocalTy as Overflow>::Assoc`
--> $DIR/trait_ref_is_knowable-norm-overflow.rs:17:1
|
LL | impl<T: Copy> Trait for T {}
| ------------------------- first implementation here
LL | struct LocalTy;
LL | impl Trait for <LocalTy as Overflow>::Assoc {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<LocalTy as Overflow>::Assoc`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0119`.
tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-1.rs
0 → 100644
浏览文件 @
9eeaf1fd
// compile-flags: -Ztrait-solver=next
// check-pass
trait
Id
{
type
Assoc
;
}
impl
<
T
>
Id
for
T
{
type
Assoc
=
T
;
}
// Coherence should be able to reason that `<LocalTy as Id>::Assoc: Copy`
// does not hold.
//
// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/51
// for more details.
trait
Trait
{}
impl
<
T
:
Copy
>
Trait
for
T
{}
struct
LocalTy
;
impl
Trait
for
<
LocalTy
as
Id
>
::
Assoc
{}
fn
main
()
{}
tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-2.rs
0 → 100644
浏览文件 @
9eeaf1fd
// compile-flags: -Ztrait-solver=next
// check-pass
use
std
::
future
::{
Future
,
IntoFuture
};
use
std
::
pin
::
Pin
;
// We check that this does not overlap with the following impl from std:
// impl<P> Future for Pin<P> where P: DerefMut, <P as Deref>::Target: Future { .. }
// This should fail because we know ` <&mut Value as Deref>::Target: Future` not to hold.
// For this to work we have to normalize in the `trait_ref_is_knowable` check as we
// otherwise add an ambiguous candidate here.
//
// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/51
// for more details.
struct
Value
;
impl
<
'a
>
IntoFuture
for
Pin
<&
'a
mut
Value
>
{
type
Output
=
();
type
IntoFuture
=
Pin
<
Box
<
dyn
Future
<
Output
=
()
>
+
Send
>>
;
fn
into_future
(
self
)
->
Self
::
IntoFuture
{
todo!
()
}
}
fn
main
()
{}
tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-normalization-3.rs
0 → 100644
浏览文件 @
9eeaf1fd
// compile-flags: -Ztrait-solver=next
// check-pass
trait
Id
{
type
Assoc
;
}
impl
<
T
>
Id
for
T
{
type
Assoc
=
T
;
}
// Coherence should be able to reason that `(): PartialEq<<T as Id>::Assoc>>`
// does not hold.
//
// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/51
// for more details.
trait
Trait
{}
impl
<
T
>
Trait
for
T
where
():
PartialEq
<
T
>
{}
struct
LocalTy
;
impl
Trait
for
<
LocalTy
as
Id
>
::
Assoc
{}
fn
main
()
{}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录