Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
ee0357af
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,发现更多精彩内容 >>
提交
ee0357af
编写于
3月 13, 2021
作者:
V
Vadim Petrochenkov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
resolve: Partially unify early and late scope-relative ident resolution
上级
afaf33dc
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
96 addition
and
143 deletion
+96
-143
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_lint_defs/src/builtin.rs
+1
-1
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/diagnostics.rs
+2
-2
compiler/rustc_resolve/src/lib.rs
compiler/rustc_resolve/src/lib.rs
+63
-131
compiler/rustc_resolve/src/macros.rs
compiler/rustc_resolve/src/macros.rs
+22
-5
src/test/ui/proc-macro/generate-mod.stderr
src/test/ui/proc-macro/generate-mod.stderr
+8
-4
未找到文件。
compiler/rustc_lint_defs/src/builtin.rs
浏览文件 @
ee0357af
...
...
@@ -1977,7 +1977,7 @@
Warn
,
"detects proc macro derives using inaccessible names from parent modules"
,
@
future_incompatible
=
FutureIncompatibleInfo
{
reference
:
"issue #
50504 <https://github.com/rust-lang/rust/issues/50504
>"
,
reference
:
"issue #
83583 <https://github.com/rust-lang/rust/issues/83583
>"
,
edition
:
None
,
};
}
...
...
compiler/rustc_resolve/src/diagnostics.rs
浏览文件 @
ee0357af
...
...
@@ -606,7 +606,7 @@ impl<'a> Resolver<'a> {
/// Lookup typo candidate in scope for a macro or import.
fn
early_lookup_typo_candidate
(
&
mut
self
,
scope_set
:
ScopeSet
,
scope_set
:
ScopeSet
<
'a
>
,
parent_scope
:
&
ParentScope
<
'a
>
,
ident
:
Ident
,
filter_fn
:
&
impl
Fn
(
Res
)
->
bool
,
...
...
@@ -662,7 +662,7 @@ fn early_lookup_typo_candidate(
let
root_module
=
this
.resolve_crate_root
(
root_ident
);
this
.add_module_candidates
(
root_module
,
&
mut
suggestions
,
filter_fn
);
}
Scope
::
Module
(
module
)
=>
{
Scope
::
Module
(
module
,
_
)
=>
{
this
.add_module_candidates
(
module
,
&
mut
suggestions
,
filter_fn
);
}
Scope
::
RegisteredAttrs
=>
{
...
...
compiler/rustc_resolve/src/lib.rs
浏览文件 @
ee0357af
...
...
@@ -25,7 +25,6 @@
use
rustc_arena
::{
DroplessArena
,
TypedArena
};
use
rustc_ast
::
node_id
::
NodeMap
;
use
rustc_ast
::
ptr
::
P
;
use
rustc_ast
::
unwrap_or
;
use
rustc_ast
::
visit
::{
self
,
Visitor
};
use
rustc_ast
::{
self
as
ast
,
NodeId
};
use
rustc_ast
::{
Crate
,
CRATE_NODE_ID
};
...
...
@@ -42,7 +41,7 @@
use
rustc_hir
::
def
::{
self
,
CtorOf
,
DefKind
,
NonMacroAttrKind
,
PartialRes
};
use
rustc_hir
::
def_id
::{
CrateNum
,
DefId
,
DefIdMap
,
LocalDefId
,
CRATE_DEF_INDEX
};
use
rustc_hir
::
definitions
::{
DefKey
,
DefPathData
,
Definitions
};
use
rustc_hir
::
{
PrimTy
,
TraitCandidate
}
;
use
rustc_hir
::
TraitCandidate
;
use
rustc_index
::
vec
::
IndexVec
;
use
rustc_metadata
::
creader
::{
CStore
,
CrateLoader
};
use
rustc_middle
::
hir
::
exports
::
ExportMap
;
...
...
@@ -108,7 +107,9 @@ enum Scope<'a> {
DeriveHelpersCompat
,
MacroRules
(
MacroRulesScopeRef
<
'a
>
),
CrateRoot
,
Module
(
Module
<
'a
>
),
// The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK`
// lint if it should be reported.
Module
(
Module
<
'a
>
,
Option
<
NodeId
>
),
RegisteredAttrs
,
MacroUsePrelude
,
BuiltinAttrs
,
...
...
@@ -122,13 +123,17 @@ enum Scope<'a> {
/// with different restrictions when looking up the resolution.
/// This enum is currently used only for early resolution (imports and macros),
/// but not for late resolution yet.
enum
ScopeSet
{
#[derive(Clone,
Copy)]
enum
ScopeSet
<
'a
>
{
/// All scopes with the given namespace.
All
(
Namespace
,
/*is_import*/
bool
),
/// Crate root, then extern prelude (used for mixed 2015-2018 mode in macros).
AbsolutePath
(
Namespace
),
/// All scopes with macro namespace and the given macro kind restriction.
Macro
(
MacroKind
),
/// All scopes with the given namespace, used for partially performing late resolution.
/// The node id enables lints and is used for reporting them.
Late
(
Namespace
,
Module
<
'a
>
,
Option
<
NodeId
>
),
}
/// Everything you need to know about a name's location to resolve it.
...
...
@@ -1466,7 +1471,7 @@ pub fn traits_in_scope(
self
.visit_scopes
(
ScopeSet
::
All
(
TypeNS
,
false
),
parent_scope
,
ctxt
,
|
this
,
scope
,
_
,
_
|
{
match
scope
{
Scope
::
Module
(
module
)
=>
{
Scope
::
Module
(
module
,
_
)
=>
{
this
.traits_in_module
(
module
,
assoc_item
,
&
mut
found_traits
);
}
Scope
::
StdLibPrelude
=>
{
...
...
@@ -1630,7 +1635,7 @@ fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) {
/// If the callback returns `Some` result, we stop visiting scopes and return it.
fn
visit_scopes
<
T
>
(
&
mut
self
,
scope_set
:
ScopeSet
,
scope_set
:
ScopeSet
<
'a
>
,
parent_scope
:
&
ParentScope
<
'a
>
,
ctxt
:
SyntaxContext
,
mut
visitor
:
impl
FnMut
(
...
...
@@ -1686,12 +1691,17 @@ fn visit_scopes<T>(
ScopeSet
::
All
(
ns
,
_
)
=>
(
ns
,
None
,
false
),
ScopeSet
::
AbsolutePath
(
ns
)
=>
(
ns
,
None
,
true
),
ScopeSet
::
Macro
(
macro_kind
)
=>
(
MacroNS
,
Some
(
macro_kind
),
false
),
ScopeSet
::
Late
(
ns
,
..
)
=>
(
ns
,
None
,
false
),
};
let
module
=
match
scope_set
{
// Start with the specified module.
ScopeSet
::
Late
(
_
,
module
,
_
)
=>
module
,
// Jump out of trait or enum modules, they do not act as scopes.
_
=>
parent_scope
.module
.nearest_item_scope
(),
};
// Jump out of trait or enum modules, they do not act as scopes.
let
module
=
parent_scope
.module
.nearest_item_scope
();
let
mut
scope
=
match
ns
{
_
if
is_absolute_path
=>
Scope
::
CrateRoot
,
TypeNS
|
ValueNS
=>
Scope
::
Module
(
module
),
TypeNS
|
ValueNS
=>
Scope
::
Module
(
module
,
None
),
MacroNS
=>
Scope
::
DeriveHelpers
(
parent_scope
.expansion
),
};
let
mut
ctxt
=
ctxt
.normalize_to_macros_2_0
();
...
...
@@ -1756,7 +1766,7 @@ fn visit_scopes<T>(
MacroRulesScope
::
Invocation
(
invoc_id
)
=>
{
Scope
::
MacroRules
(
self
.invocation_parent_scopes
[
&
invoc_id
]
.macro_rules
)
}
MacroRulesScope
::
Empty
=>
Scope
::
Module
(
module
),
MacroRulesScope
::
Empty
=>
Scope
::
Module
(
module
,
None
),
},
Scope
::
CrateRoot
=>
match
ns
{
TypeNS
=>
{
...
...
@@ -1765,10 +1775,16 @@ fn visit_scopes<T>(
}
ValueNS
|
MacroNS
=>
break
,
},
Scope
::
Module
(
module
)
=>
{
Scope
::
Module
(
module
,
prev_lint_id
)
=>
{
use_prelude
=
!
module
.no_implicit_prelude
;
match
self
.hygienic_lexical_parent
(
module
,
&
mut
ctxt
)
{
Some
(
parent_module
)
=>
Scope
::
Module
(
parent_module
),
let
derive_fallback_lint_id
=
match
scope_set
{
ScopeSet
::
Late
(
..
,
lint_id
)
=>
lint_id
,
_
=>
None
,
};
match
self
.hygienic_lexical_parent
(
module
,
&
mut
ctxt
,
derive_fallback_lint_id
)
{
Some
((
parent_module
,
lint_id
))
=>
{
Scope
::
Module
(
parent_module
,
lint_id
.or
(
prev_lint_id
))
}
None
=>
{
ctxt
.adjust
(
ExpnId
::
root
());
match
ns
{
...
...
@@ -1824,6 +1840,7 @@ fn resolve_ident_in_lexical_scope(
ribs
:
&
[
Rib
<
'a
>
],
)
->
Option
<
LexicalScopeBinding
<
'a
>>
{
assert
!
(
ns
==
TypeNS
||
ns
==
ValueNS
);
let
orig_ident
=
ident
;
if
ident
.name
==
kw
::
Empty
{
return
Some
(
LexicalScopeBinding
::
Res
(
Res
::
Err
));
}
...
...
@@ -1873,135 +1890,49 @@ fn resolve_ident_in_lexical_scope(
_
=>
continue
,
};
let
item
=
self
.resolve_ident_in_module_unadjusted
(
ModuleOrUniformRoot
::
Module
(
module
),
ident
,
ns
,
parent_scope
,
record_used
,
path_span
,
);
if
let
Ok
(
binding
)
=
item
{
// The ident resolves to an item.
return
Some
(
LexicalScopeBinding
::
Item
(
binding
));
}
match
module
.kind
{
ModuleKind
::
Block
(
..
)
=>
{}
// We can see through blocks
_
=>
break
,
}
}
ident
=
normalized_ident
;
let
mut
poisoned
=
None
;
loop
{
let
mut
span_data
=
ident
.span
.data
();
let
opt_module
=
if
let
Some
(
node_id
)
=
record_used_id
{
self
.hygienic_lexical_parent_with_compatibility_fallback
(
module
,
&
mut
span_data
.ctxt
,
node_id
,
&
mut
poisoned
,
)
}
else
{
self
.hygienic_lexical_parent
(
module
,
&
mut
span_data
.ctxt
)
};
ident
.span
=
span_data
.span
();
module
=
unwrap_or!
(
opt_module
,
break
);
let
adjusted_parent_scope
=
&
ParentScope
{
module
,
..*
parent_scope
};
let
result
=
self
.resolve_ident_in_module_unadjusted
(
let
item
=
self
.resolve_ident_in_module_unadjusted
(
ModuleOrUniformRoot
::
Module
(
module
),
ident
,
ns
,
adjusted_
parent_scope
,
parent_scope
,
record_used
,
path_span
,
);
match
result
{
Ok
(
binding
)
=>
{
if
let
Some
(
node_id
)
=
poisoned
{
self
.lint_buffer
.buffer_lint_with_diagnostic
(
lint
::
builtin
::
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK
,
node_id
,
ident
.span
,
&
format!
(
"cannot find {} `{}` in this scope"
,
ns
.descr
(),
ident
),
BuiltinLintDiagnostics
::
ProcMacroDeriveResolutionFallback
(
ident
.span
),
);
}
return
Some
(
LexicalScopeBinding
::
Item
(
binding
));
}
Err
(
Determined
)
=>
continue
,
Err
(
Undetermined
)
=>
{
span_bug!
(
ident
.span
,
"undetermined resolution during main resolution pass"
)
}
}
}
if
!
module
.no_implicit_prelude
{
ident
.span
.adjust
(
ExpnId
::
root
());
if
ns
==
TypeNS
{
if
let
Some
(
binding
)
=
self
.extern_prelude_get
(
ident
,
!
record_used
)
{
return
Some
(
LexicalScopeBinding
::
Item
(
binding
));
}
if
let
Some
(
ident
)
=
self
.registered_tools
.get
(
&
ident
)
{
let
binding
=
(
Res
::
ToolMod
,
ty
::
Visibility
::
Public
,
ident
.span
,
ExpnId
::
root
())
.to_name_binding
(
self
.arenas
);
return
Some
(
LexicalScopeBinding
::
Item
(
binding
));
}
}
if
let
Some
(
prelude
)
=
self
.prelude
{
if
let
Ok
(
binding
)
=
self
.resolve_ident_in_module_unadjusted
(
ModuleOrUniformRoot
::
Module
(
prelude
),
ident
,
ns
,
parent_scope
,
false
,
path_span
,
)
{
return
Some
(
LexicalScopeBinding
::
Item
(
binding
));
}
}
}
if
ns
==
TypeNS
{
if
let
Some
(
prim_ty
)
=
PrimTy
::
from_name
(
ident
.name
)
{
let
binding
=
(
Res
::
PrimTy
(
prim_ty
),
ty
::
Visibility
::
Public
,
DUMMY_SP
,
ExpnId
::
root
())
.to_name_binding
(
self
.arenas
);
if
let
Ok
(
binding
)
=
item
{
// The ident resolves to an item.
return
Some
(
LexicalScopeBinding
::
Item
(
binding
));
}
}
None
self
.early_resolve_ident_in_lexical_scope
(
orig_ident
,
ScopeSet
::
Late
(
ns
,
module
,
record_used_id
),
parent_scope
,
record_used
,
record_used
,
path_span
,
)
.ok
()
.map
(
LexicalScopeBinding
::
Item
)
}
fn
hygienic_lexical_parent
(
&
mut
self
,
module
:
Module
<
'a
>
,
ctxt
:
&
mut
SyntaxContext
,
)
->
Option
<
Module
<
'a
>>
{
derive_fallback_lint_id
:
Option
<
NodeId
>
,
)
->
Option
<
(
Module
<
'a
>
,
Option
<
NodeId
>
)
>
{
if
!
module
.expansion
.outer_expn_is_descendant_of
(
*
ctxt
)
{
return
Some
(
self
.macro_def_scope
(
ctxt
.remove_mark
()
));
return
Some
(
(
self
.macro_def_scope
(
ctxt
.remove_mark
()),
None
));
}
if
let
ModuleKind
::
Block
(
..
)
=
module
.kind
{
return
Some
(
module
.parent
.unwrap
()
.nearest_item_scope
());
}
None
}
fn
hygienic_lexical_parent_with_compatibility_fallback
(
&
mut
self
,
module
:
Module
<
'a
>
,
ctxt
:
&
mut
SyntaxContext
,
node_id
:
NodeId
,
poisoned
:
&
mut
Option
<
NodeId
>
,
)
->
Option
<
Module
<
'a
>>
{
if
let
module
@
Some
(
..
)
=
self
.hygienic_lexical_parent
(
module
,
ctxt
)
{
return
module
;
return
Some
((
module
.parent
.unwrap
()
.nearest_item_scope
(),
None
));
}
// We need to support the next case under a deprecation warning
...
...
@@ -2015,20 +1946,21 @@ fn hygienic_lexical_parent_with_compatibility_fallback(
// ---- end
// ```
// So we have to fall back to the module's parent during lexical resolution in this case.
if
let
Some
(
parent
)
=
module
.parent
{
// Inner module is inside the macro, parent module is outside of the macro.
if
module
.expansion
!=
parent
.expansion
&&
module
.expansion
.is_descendant_of
(
parent
.expansion
)
{
// The macro is a proc macro derive
if
let
Some
(
def_id
)
=
module
.expansion
.expn_data
()
.macro_def_id
{
let
ext
=
self
.get_macro_by_def_id
(
def_id
);
if
ext
.builtin_name
.is_none
()
&&
ext
.macro_kind
()
==
MacroKind
::
Derive
&&
parent
.expansion
.outer_expn_is_descendant_of
(
*
ctxt
)
{
*
poisoned
=
Some
(
node_id
);
return
module
.parent
;
if
derive_fallback_lint_id
.is_some
()
{
if
let
Some
(
parent
)
=
module
.parent
{
// Inner module is inside the macro, parent module is outside of the macro.
if
module
.expansion
!=
parent
.expansion
&&
module
.expansion
.is_descendant_of
(
parent
.expansion
)
{
// The macro is a proc macro derive
if
let
Some
(
def_id
)
=
module
.expansion
.expn_data
()
.macro_def_id
{
let
ext
=
self
.get_macro_by_def_id
(
def_id
);
if
ext
.builtin_name
.is_none
()
&&
ext
.macro_kind
()
==
MacroKind
::
Derive
&&
parent
.expansion
.outer_expn_is_descendant_of
(
*
ctxt
)
{
return
Some
((
parent
,
derive_fallback_lint_id
));
}
}
}
}
...
...
compiler/rustc_resolve/src/macros.rs
浏览文件 @
ee0357af
...
...
@@ -24,7 +24,8 @@
use
rustc_hir
::
PrimTy
;
use
rustc_middle
::
middle
::
stability
;
use
rustc_middle
::
ty
;
use
rustc_session
::
lint
::
builtin
::{
LEGACY_DERIVE_HELPERS
,
SOFT_UNSTABLE
,
UNUSED_MACROS
};
use
rustc_session
::
lint
::
builtin
::{
LEGACY_DERIVE_HELPERS
,
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK
};
use
rustc_session
::
lint
::
builtin
::{
SOFT_UNSTABLE
,
UNUSED_MACROS
};
use
rustc_session
::
lint
::
BuiltinLintDiagnostics
;
use
rustc_session
::
parse
::
feature_err
;
use
rustc_session
::
Session
;
...
...
@@ -642,7 +643,7 @@ pub fn resolve_macro_path(
crate
fn
early_resolve_ident_in_lexical_scope
(
&
mut
self
,
orig_ident
:
Ident
,
scope_set
:
ScopeSet
,
scope_set
:
ScopeSet
<
'a
>
,
parent_scope
:
&
ParentScope
<
'a
>
,
record_used
:
bool
,
force
:
bool
,
...
...
@@ -669,6 +670,7 @@ struct Flags: u8 {
ScopeSet
::
All
(
ns
,
is_import
)
=>
(
ns
,
None
,
is_import
),
ScopeSet
::
AbsolutePath
(
ns
)
=>
(
ns
,
None
,
false
),
ScopeSet
::
Macro
(
macro_kind
)
=>
(
MacroNS
,
Some
(
macro_kind
),
false
),
ScopeSet
::
Late
(
ns
,
..
)
=>
(
ns
,
None
,
false
),
};
// This is *the* result, resolution from the scope closest to the resolved identifier.
...
...
@@ -777,19 +779,34 @@ struct Flags: u8 {
Err
((
Determinacy
::
Determined
,
_
))
=>
Err
(
Determinacy
::
Determined
),
}
}
Scope
::
Module
(
module
)
=>
{
Scope
::
Module
(
module
,
derive_fallback_lint_id
)
=>
{
let
adjusted_parent_scope
=
&
ParentScope
{
module
,
..*
parent_scope
};
let
binding
=
this
.resolve_ident_in_module_unadjusted_ext
(
ModuleOrUniformRoot
::
Module
(
module
),
ident
,
ns
,
adjusted_parent_scope
,
true
,
!
matches!
(
scope_set
,
ScopeSet
::
Late
(
..
))
,
record_used
,
path_span
,
);
match
binding
{
Ok
(
binding
)
=>
{
if
let
Some
(
lint_id
)
=
derive_fallback_lint_id
{
this
.lint_buffer
.buffer_lint_with_diagnostic
(
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK
,
lint_id
,
orig_ident
.span
,
&
format!
(
"cannot find {} `{}` in this scope"
,
ns
.descr
(),
ident
),
BuiltinLintDiagnostics
::
ProcMacroDeriveResolutionFallback
(
orig_ident
.span
,
),
);
}
let
misc_flags
=
if
ptr
::
eq
(
module
,
this
.graph_root
)
{
Flags
::
MISC_SUGGEST_CRATE
}
else
if
module
.is_normal
()
{
...
...
@@ -873,7 +890,7 @@ struct Flags: u8 {
Ok
((
binding
,
flags
))
if
sub_namespace_match
(
binding
.macro_kind
(),
macro_kind
)
=>
{
if
!
record_used
{
if
!
record_used
||
matches!
(
scope_set
,
ScopeSet
::
Late
(
..
))
{
return
Some
(
Ok
(
binding
));
}
...
...
src/test/ui/proc-macro/generate-mod.stderr
浏览文件 @
ee0357af
...
...
@@ -46,7 +46,8 @@ LL | #[derive(generate_mod::CheckDerive)]
|
= note: `#[warn(proc_macro_derive_resolution_fallback)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
= note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
warning: cannot find type `OuterDerive` in this scope
--> $DIR/generate-mod.rs:16:10
...
...
@@ -55,7 +56,8 @@ LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
= note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
warning: cannot find type `FromOutside` in this scope
--> $DIR/generate-mod.rs:23:14
...
...
@@ -64,7 +66,8 @@ LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
= note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
warning: cannot find type `OuterDerive` in this scope
--> $DIR/generate-mod.rs:23:14
...
...
@@ -73,7 +76,8 @@ LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
= note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors; 4 warnings emitted
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录