Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
66e41bc6
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,发现更多精彩内容 >>
提交
66e41bc6
编写于
3月 11, 2019
作者:
G
Giles Cope
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Improved error message when type must be bound due to generator.
Error now mentions type var name and span is highlighted.
上级
3bee49f4
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
135 addition
and
35 deletion
+135
-35
src/librustc/error_codes.rs
src/librustc/error_codes.rs
+30
-0
src/librustc/infer/error_reporting/need_type_info.rs
src/librustc/infer/error_reporting/need_type_info.rs
+31
-13
src/librustc/infer/mod.rs
src/librustc/infer/mod.rs
+4
-3
src/librustc/infer/resolve.rs
src/librustc/infer/resolve.rs
+27
-9
src/librustc/traits/project.rs
src/librustc/traits/project.rs
+3
-3
src/librustc_typeck/check/generator_interior.rs
src/librustc_typeck/check/generator_interior.rs
+10
-6
src/librustc_typeck/error_codes.rs
src/librustc_typeck/error_codes.rs
+0
-1
src/test/ui/generator/unresolved_type_param.rs
src/test/ui/generator/unresolved_type_param.rs
+14
-0
src/test/ui/generator/unresolved_type_param.stderr
src/test/ui/generator/unresolved_type_param.stderr
+16
-0
未找到文件。
src/librustc/error_codes.rs
浏览文件 @
66e41bc6
...
...
@@ -2043,6 +2043,36 @@ struct Foo {
transparent wrapper around a float. This can make a difference for the ABI.
"##
,
E0698
:
r##"
When using generators (or async) all type variables must be bound so a
generator can be constructed.
Erroneous code example:
```edition2018,compile-fail,E0698
#![feature(futures_api, async_await, await_macro)]
async fn bar<T>() -> () {}
async fn foo() {
await!(bar()); // error: cannot infer type for `T`
}
```
In the above example `T` is unknowable by the compiler.
To fix this you must bind `T` to a concrete type such as `String`
so that a generator can then be constructed:
```edition2018
#![feature(futures_api, async_await, await_macro)]
async fn bar<T>() -> () {}
async fn foo() {
await!(bar::<String>());
// ^^^^^^^^ specify type explicitly
}
```
"##
,
E0700
:
r##"
The `impl Trait` return type captures lifetime parameters that do not
appear within the `impl Trait` itself.
...
...
src/librustc/infer/error_reporting/need_type_info.rs
浏览文件 @
66e41bc6
...
...
@@ -88,23 +88,17 @@ pub fn extract_type_name(
s
}
pub
fn
need_type_info_err
(
&
self
,
body_id
:
Option
<
hir
::
BodyId
>
,
span
:
Span
,
ty
:
Ty
<
'tcx
>
)
->
DiagnosticBuilder
<
'gcx
>
{
pub
fn
need_type_info_err
(
&
self
,
body_id
:
Option
<
hir
::
BodyId
>
,
span
:
Span
,
ty
:
Ty
<
'tcx
>
)
->
DiagnosticBuilder
<
'gcx
>
{
let
ty
=
self
.resolve_type_vars_if_possible
(
&
ty
);
let
name
=
self
.extract_type_name
(
&
ty
,
None
);
let
mut
err_span
=
span
;
let
mut
labels
=
vec!
[(
span
,
if
&
name
==
"_"
{
"cannot infer type"
.to_owned
()
}
else
{
format!
(
"cannot infer type for `{}`"
,
name
)
},
)];
let
mut
labels
=
vec!
[(
span
,
InferCtxt
::
missing_type_msg
(
&
name
))];
let
mut
local_visitor
=
FindLocalByTypeVisitor
{
infcx
:
&
self
,
...
...
@@ -166,4 +160,28 @@ pub fn need_type_info_err(&self,
err
}
pub
fn
need_type_info_err_in_generator
(
&
self
,
span
:
Span
,
ty
:
Ty
<
'tcx
>
)
->
DiagnosticBuilder
<
'gcx
>
{
let
ty
=
self
.resolve_type_vars_if_possible
(
&
ty
);
let
name
=
self
.extract_type_name
(
&
ty
,
None
);
let
mut
err
=
struct_span_err!
(
self
.tcx.sess
,
span
,
E0698
,
"type inside generator must be known in this context"
);
err
.span_label
(
span
,
InferCtxt
::
missing_type_msg
(
&
name
));
err
}
fn
missing_type_msg
(
type_name
:
&
str
)
->
String
{
if
type_name
==
"_"
{
"cannot infer type"
.to_owned
()
}
else
{
format!
(
"cannot infer type for `{}`"
,
type_name
)
}
}
}
src/librustc/infer/mod.rs
浏览文件 @
66e41bc6
...
...
@@ -1312,17 +1312,18 @@ pub fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T
value
.fold_with
(
&
mut
r
)
}
/// Returns
`true` if `T` contains unresolved type variables
. In the
/// Returns
first unresolved variable contained in `T`
. In the
/// process of visiting `T`, this will resolve (where possible)
/// type variables in `T`, but it never constructs the final,
/// resolved type, so it's more efficient than
/// `resolve_type_vars_if_possible()`.
pub
fn
any_unresolved_type_vars
<
T
>
(
&
self
,
value
:
&
T
)
->
bool
pub
fn
unresolved_type_vars
<
T
>
(
&
self
,
value
:
&
T
)
->
Option
<
(
Ty
<
'tcx
>
,
Option
<
Span
>
)
>
where
T
:
TypeFoldable
<
'tcx
>
,
{
let
mut
r
=
resolve
::
UnresolvedTypeFinder
::
new
(
self
);
value
.visit_with
(
&
mut
r
)
value
.visit_with
(
&
mut
r
);
r
.first_unresolved
}
pub
fn
fully_resolve
<
T
:
TypeFoldable
<
'tcx
>>
(
&
self
,
value
:
&
T
)
->
FixupResult
<
T
>
{
...
...
src/librustc/infer/resolve.rs
浏览文件 @
66e41bc6
use
super
::{
InferCtxt
,
FixupError
,
FixupResult
};
use
super
::{
InferCtxt
,
FixupError
,
FixupResult
,
Span
,
type_variable
::
TypeVariableOrigin
};
use
crate
::
ty
::{
self
,
Ty
,
TyCtxt
,
TypeFoldable
};
use
crate
::
ty
::
fold
::{
TypeFolder
,
TypeVisitor
};
...
...
@@ -77,17 +77,20 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
///////////////////////////////////////////////////////////////////////////
// UNRESOLVED TYPE FINDER
/// The unresolved type **finder** walks
your type and searches
for
/// type variables that don't yet have a value. The
y get pushed into a
///
vector.
It does not construct the fully resolved type (which might
/// The unresolved type **finder** walks
a type searching
for
/// type variables that don't yet have a value. The
first unresolved type is stored.
/// It does not construct the fully resolved type (which might
/// involve some hashing and so forth).
pub
struct
UnresolvedTypeFinder
<
'a
,
'gcx
:
'a
+
'tcx
,
'tcx
:
'a
>
{
infcx
:
&
'a
InferCtxt
<
'a
,
'gcx
,
'tcx
>
,
/// Used to find the type parameter name and location for error reporting.
pub
first_unresolved
:
Option
<
(
Ty
<
'tcx
>
,
Option
<
Span
>
)
>
,
}
impl
<
'a
,
'gcx
,
'tcx
>
UnresolvedTypeFinder
<
'a
,
'gcx
,
'tcx
>
{
pub
fn
new
(
infcx
:
&
'a
InferCtxt
<
'a
,
'gcx
,
'tcx
>
)
->
Self
{
UnresolvedTypeFinder
{
infcx
}
UnresolvedTypeFinder
{
infcx
,
first_unresolved
:
None
}
}
}
...
...
@@ -95,22 +98,37 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'gcx, 'tcx>
fn
visit_ty
(
&
mut
self
,
t
:
Ty
<
'tcx
>
)
->
bool
{
let
t
=
self
.infcx
.shallow_resolve
(
t
);
if
t
.has_infer_types
()
{
if
let
ty
::
Infer
(
_
)
=
t
.sty
{
if
let
ty
::
Infer
(
infer_ty
)
=
t
.sty
{
// Since we called `shallow_resolve` above, this must
// be an (as yet...) unresolved inference variable.
true
let
ty_var_span
=
if
let
ty
::
TyVar
(
ty_vid
)
=
infer_ty
{
let
ty_vars
=
self
.infcx.type_variables
.borrow
();
if
let
TypeVariableOrigin
::
TypeParameterDefinition
(
span
,
_
name
)
=
*
ty_vars
.var_origin
(
ty_vid
)
{
Some
(
span
)
}
else
{
None
}
}
else
{
None
};
self
.first_unresolved
=
Some
((
t
,
ty_var_span
));
true
// Halt visiting.
}
else
{
// Otherwise, visit its contents.
t
.super_visit_with
(
self
)
}
}
else
{
//
Micro-optimize: no inference types at all Can't have unresolved type
//
variables, no need to visit the contents
.
//
All type variables in inference types must already be resolved,
//
- no need to visit the contents, continue visiting
.
false
}
}
}
///////////////////////////////////////////////////////////////////////////
// FULL TYPE RESOLUTION
...
...
src/librustc/traits/project.rs
浏览文件 @
66e41bc6
...
...
@@ -594,7 +594,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
// Once we have inferred everything we need to know, we
// can ignore the `obligations` from that point on.
if
!
infcx
.any_unresolved_type_vars
(
&
ty
.value
)
{
if
infcx
.unresolved_type_vars
(
&
ty
.value
)
.is_none
(
)
{
infcx
.projection_cache
.borrow_mut
()
.complete_normalized
(
cache_key
,
&
ty
);
// No need to extend `obligations`.
}
else
{
...
...
@@ -704,7 +704,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
fn
prune_cache_value_obligations
<
'a
,
'gcx
,
'tcx
>
(
infcx
:
&
'a
InferCtxt
<
'a
,
'gcx
,
'tcx
>
,
result
:
&
NormalizedTy
<
'tcx
>
)
->
NormalizedTy
<
'tcx
>
{
if
!
infcx
.any_unresolved_type_vars
(
&
result
.value
)
{
if
infcx
.unresolved_type_vars
(
&
result
.value
)
.is_none
(
)
{
return
NormalizedTy
{
value
:
result
.value
,
obligations
:
vec!
[]
};
}
...
...
@@ -722,7 +722,7 @@ fn prune_cache_value_obligations<'a, 'gcx, 'tcx>(infcx: &'a InferCtxt<'a, 'gcx,
// but we have `T: Foo<X = ?1>` and `?1: Bar<X =
// ?0>`).
ty
::
Predicate
::
Projection
(
ref
data
)
=>
infcx
.
any_unresolved_type_vars
(
&
data
.ty
()
),
infcx
.
unresolved_type_vars
(
&
data
.ty
())
.is_some
(
),
// We are only interested in `T: Foo<X = U>` predicates, whre
// `U` references one of `unresolved_type_vars`. =)
...
...
src/librustc_typeck/check/generator_interior.rs
浏览文件 @
66e41bc6
...
...
@@ -54,12 +54,16 @@ fn record(&mut self,
debug!
(
"type in expr = {:?}, scope = {:?}, type = {:?}, count = {}, yield_span = {:?}"
,
expr
,
scope
,
ty
,
self
.expr_count
,
yield_span
);
if
self
.fcx
.any_unresolved_type_vars
(
&
ty
)
{
let
mut
err
=
struct_span_err!
(
self
.fcx.tcx.sess
,
source_span
,
E0698
,
"type inside generator must be known in this context"
);
err
.span_note
(
yield_span
,
"the type is part of the generator because of this `yield`"
);
err
.emit
();
if
let
Some
((
unresolved_type
,
unresolved_type_span
))
=
self
.fcx
.unresolved_type_vars
(
&
ty
)
{
// If unresolved type isn't a ty_var then unresolved_type_span is None
self
.fcx
.need_type_info_err_in_generator
(
unresolved_type_span
.unwrap_or
(
yield_span
),
unresolved_type
)
.span_note
(
yield_span
,
"the type is part of the generator because of this `yield`"
)
.emit
();
}
else
{
// Map the type to the number of types added before it
let
entries
=
self
.types
.len
();
...
...
src/librustc_typeck/error_codes.rs
浏览文件 @
66e41bc6
...
...
@@ -4728,7 +4728,6 @@ fn make_recursive_type() -> impl Sized {
E0640
,
// infer outlives requirements
E0641
,
// cannot cast to/from a pointer with an unknown kind
E0645
,
// trait aliases not finished
E0698
,
// type inside generator must be known in this context
E0719
,
// duplicate values for associated type binding
E0722
,
// Malformed #[optimize] attribute
E0724
,
// `#[ffi_returns_twice]` is only allowed in foreign functions
...
...
src/test/ui/generator/unresolved_type_param.rs
0 → 100644
浏览文件 @
66e41bc6
// Provoke an unresolved type error (T).
// Error message should pinpoint the type parameter T as needing to be bound
// (rather than give a general error message)
// edition:2018
#![feature(futures_api,
async_await,
await_macro)]
async
fn
bar
<
T
>
()
->
()
{}
async
fn
foo
()
{
await
!
(
bar
());
//~^ ERROR type inside generator must be known in this context
//~| NOTE cannot infer type for `T`
//~| NOTE the type is part of the generator because of this `yield`
}
fn
main
()
{}
src/test/ui/generator/unresolved_type_param.stderr
0 → 100644
浏览文件 @
66e41bc6
error[E0698]: type inside generator must be known in this context
--> $DIR/unresolved_type_param.rs:9:16
|
LL | await!(bar());
| ^^^ cannot infer type for `T`
|
note: the type is part of the generator because of this `yield`
--> $DIR/unresolved_type_param.rs:9:9
|
LL | await!(bar());
| ^^^^^^^^^^^^^^
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0698`.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录