mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-04 02:54:00 +00:00
Use Option
in ImplItemKind::Method
.
This commit is contained in:
parent
73557faed2
commit
f6403c6c76
@ -1211,7 +1211,7 @@ impl<'a> LoweringContext<'a> {
|
||||
let ct = self.with_new_scopes(|this| {
|
||||
hir::AnonConst {
|
||||
hir_id: this.lower_node_id(node_id),
|
||||
body: this.lower_const_body(&path_expr),
|
||||
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
|
||||
}
|
||||
});
|
||||
return GenericArg::Const(ConstArg {
|
||||
@ -3003,7 +3003,7 @@ impl<'a> LoweringContext<'a> {
|
||||
self.with_new_scopes(|this| {
|
||||
hir::AnonConst {
|
||||
hir_id: this.lower_node_id(c.id),
|
||||
body: this.lower_const_body(&c.value),
|
||||
body: this.lower_const_body(c.value.span, Some(&c.value)),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ impl LoweringContext<'_> {
|
||||
return None;
|
||||
}
|
||||
|
||||
let kind = self.lower_item_kind(i.id, &mut ident, &attrs, &mut vis, &i.kind);
|
||||
let kind = self.lower_item_kind(i.span, i.id, &mut ident, &attrs, &mut vis, &i.kind);
|
||||
|
||||
Some(hir::Item {
|
||||
hir_id: self.lower_node_id(i.id),
|
||||
@ -264,6 +264,7 @@ impl LoweringContext<'_> {
|
||||
|
||||
fn lower_item_kind(
|
||||
&mut self,
|
||||
span: Span,
|
||||
id: NodeId,
|
||||
ident: &mut Ident,
|
||||
attrs: &hir::HirVec<Attribute>,
|
||||
@ -292,7 +293,7 @@ impl LoweringContext<'_> {
|
||||
}
|
||||
),
|
||||
m,
|
||||
self.lower_const_body(e),
|
||||
self.lower_const_body(span, Some(e)),
|
||||
)
|
||||
}
|
||||
ItemKind::Const(ref t, ref e) => {
|
||||
@ -305,7 +306,7 @@ impl LoweringContext<'_> {
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
|
||||
}
|
||||
),
|
||||
self.lower_const_body(e)
|
||||
self.lower_const_body(span, Some(e))
|
||||
)
|
||||
}
|
||||
ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => {
|
||||
@ -317,7 +318,12 @@ impl LoweringContext<'_> {
|
||||
// `impl Future<Output = T>` here because lower_body
|
||||
// only cares about the input argument patterns in the function
|
||||
// declaration (decl), not the return types.
|
||||
let body_id = this.lower_maybe_async_body(&decl, header.asyncness.node, body);
|
||||
let body_id = this.lower_maybe_async_body(
|
||||
span,
|
||||
&decl,
|
||||
header.asyncness.node,
|
||||
Some(body),
|
||||
);
|
||||
|
||||
let (generics, decl) = this.add_in_band_defs(
|
||||
generics,
|
||||
@ -817,7 +823,7 @@ impl LoweringContext<'_> {
|
||||
self.lower_ty(ty, ImplTraitContext::disallowed()),
|
||||
default
|
||||
.as_ref()
|
||||
.map(|x| self.lower_const_body(x)),
|
||||
.map(|x| self.lower_const_body(i.span, Some(x))),
|
||||
),
|
||||
),
|
||||
TraitItemKind::Method(ref sig, None) => {
|
||||
@ -832,7 +838,7 @@ impl LoweringContext<'_> {
|
||||
(generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names)))
|
||||
}
|
||||
TraitItemKind::Method(ref sig, Some(ref body)) => {
|
||||
let body_id = self.lower_fn_body_block(&sig.decl, body);
|
||||
let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body));
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
&i.generics,
|
||||
sig,
|
||||
@ -891,6 +897,11 @@ impl LoweringContext<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct `ExprKind::Err` for the given `span`.
|
||||
fn expr_err(&mut self, span: Span) -> hir::Expr {
|
||||
self.expr(span, hir::ExprKind::Err, ThinVec::new())
|
||||
}
|
||||
|
||||
fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
|
||||
let impl_item_def_id = self.resolver.definitions().local_def_id(i.id);
|
||||
|
||||
@ -899,19 +910,16 @@ impl LoweringContext<'_> {
|
||||
self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
|
||||
hir::ImplItemKind::Const(
|
||||
self.lower_ty(ty, ImplTraitContext::disallowed()),
|
||||
match expr {
|
||||
Some(expr) => self.lower_const_body(expr),
|
||||
None => self.lower_body(|this| (
|
||||
hir_vec![],
|
||||
this.expr(i.span, hir::ExprKind::Err, ThinVec::new()),
|
||||
)),
|
||||
}
|
||||
self.lower_const_body(i.span, expr.as_deref()),
|
||||
),
|
||||
),
|
||||
ImplItemKind::Method(ref sig, ref body) => {
|
||||
self.current_item = Some(i.span);
|
||||
let body_id = self.lower_maybe_async_body(
|
||||
&sig.decl, sig.header.asyncness.node, body
|
||||
i.span,
|
||||
&sig.decl,
|
||||
sig.header.asyncness.node,
|
||||
body.as_deref(),
|
||||
);
|
||||
let impl_trait_return_allow = !self.is_in_trait_impl;
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
@ -1069,23 +1077,39 @@ impl LoweringContext<'_> {
|
||||
))
|
||||
}
|
||||
|
||||
fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
|
||||
self.lower_fn_body(decl, |this| this.lower_block_expr(body))
|
||||
fn lower_fn_body_block(
|
||||
&mut self,
|
||||
span: Span,
|
||||
decl: &FnDecl,
|
||||
body: Option<&Block>,
|
||||
) -> hir::BodyId {
|
||||
self.lower_fn_body(decl, |this| this.lower_block_expr_opt(span, body))
|
||||
}
|
||||
|
||||
pub(super) fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId {
|
||||
self.lower_body(|this| (hir_vec![], this.lower_expr(expr)))
|
||||
fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr {
|
||||
match block {
|
||||
Some(block) => self.lower_block_expr(block),
|
||||
None => self.expr_err(span),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {
|
||||
self.lower_body(|this| (hir_vec![], match expr {
|
||||
Some(expr) => this.lower_expr(expr),
|
||||
None => this.expr_err(span),
|
||||
}))
|
||||
}
|
||||
|
||||
fn lower_maybe_async_body(
|
||||
&mut self,
|
||||
span: Span,
|
||||
decl: &FnDecl,
|
||||
asyncness: IsAsync,
|
||||
body: &Block,
|
||||
body: Option<&Block>,
|
||||
) -> hir::BodyId {
|
||||
let closure_id = match asyncness {
|
||||
IsAsync::Async { closure_id, .. } => closure_id,
|
||||
IsAsync::NotAsync => return self.lower_fn_body_block(decl, body),
|
||||
IsAsync::NotAsync => return self.lower_fn_body_block(span, decl, body),
|
||||
};
|
||||
|
||||
self.lower_body(|this| {
|
||||
@ -1219,15 +1243,16 @@ impl LoweringContext<'_> {
|
||||
parameters.push(new_parameter);
|
||||
}
|
||||
|
||||
let body_span = body.map_or(span, |b| b.span);
|
||||
let async_expr = this.make_async_expr(
|
||||
CaptureBy::Value,
|
||||
closure_id,
|
||||
None,
|
||||
body.span,
|
||||
body_span,
|
||||
hir::AsyncGeneratorKind::Fn,
|
||||
|this| {
|
||||
// Create a block from the user's function body:
|
||||
let user_body = this.lower_block_expr(body);
|
||||
let user_body = this.lower_block_expr_opt(body_span, body);
|
||||
|
||||
// Transform into `drop-temps { <user-body> }`, an expression:
|
||||
let desugared_span = this.mark_span_with_reason(
|
||||
@ -1257,7 +1282,7 @@ impl LoweringContext<'_> {
|
||||
);
|
||||
this.expr_block(P(body), ThinVec::new())
|
||||
});
|
||||
(HirVec::from(parameters), this.expr(body.span, async_expr, ThinVec::new()))
|
||||
(HirVec::from(parameters), this.expr(body_span, async_expr, ThinVec::new()))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -705,9 +705,7 @@ impl<'a> Parser<'a> {
|
||||
// FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
|
||||
(Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default())
|
||||
} else {
|
||||
let (name, inner_attrs, generics, kind) = self.parse_impl_method(at_end)?;
|
||||
attrs.extend(inner_attrs);
|
||||
(name, kind, generics)
|
||||
self.parse_impl_method(at_end, &mut attrs)?
|
||||
};
|
||||
|
||||
Ok(ImplItem {
|
||||
@ -1842,11 +1840,11 @@ impl<'a> Parser<'a> {
|
||||
fn parse_impl_method(
|
||||
&mut self,
|
||||
at_end: &mut bool,
|
||||
) -> PResult<'a, (Ident, Vec<Attribute>, Generics, ImplItemKind)> {
|
||||
attrs: &mut Vec<Attribute>,
|
||||
) -> PResult<'a, (Ident, ImplItemKind, Generics)> {
|
||||
let (ident, sig, generics) = self.parse_method_sig(|_| true)?;
|
||||
*at_end = true;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body)))
|
||||
let body = self.parse_trait_method_body(at_end, attrs)?;
|
||||
Ok((ident, ast::ImplItemKind::Method(sig, body), generics))
|
||||
}
|
||||
|
||||
fn parse_trait_item_method(
|
||||
|
@ -279,6 +279,22 @@ impl<'a> AstValidator<'a> {
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) {
|
||||
if body.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.err_handler()
|
||||
.struct_span_err(sp, &format!("associated {} in `impl` without body", ctx))
|
||||
.span_suggestion(
|
||||
self.session.source_map().end_point(sp),
|
||||
&format!("provide a definition for the {}", ctx),
|
||||
sugg.to_string(),
|
||||
Applicability::HasPlaceholders,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
enum GenericPosition {
|
||||
@ -747,18 +763,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
|
||||
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
|
||||
match &ii.kind {
|
||||
ImplItemKind::Const(ty, None) => {
|
||||
self.err_handler()
|
||||
.struct_span_err(ii.span, "associated constant in `impl` without body")
|
||||
.span_suggestion(
|
||||
ii.span,
|
||||
"provide a definition for the constant",
|
||||
format!("const {}: {} = <expr>;", ii.ident, pprust::ty_to_string(ty)),
|
||||
Applicability::HasPlaceholders,
|
||||
)
|
||||
.emit();
|
||||
ImplItemKind::Const(_, body) => {
|
||||
self.check_impl_item_provided(ii.span, body, "constant", " = <expr>;");
|
||||
}
|
||||
ImplItemKind::Method(sig, _) => {
|
||||
ImplItemKind::Method(sig, body) => {
|
||||
self.check_impl_item_provided(ii.span, body, "function", " { <body> }");
|
||||
self.check_fn_decl(&sig.decl);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -50,7 +50,7 @@ impl<'a> DefCollector<'a> {
|
||||
header: &FnHeader,
|
||||
generics: &'a Generics,
|
||||
decl: &'a FnDecl,
|
||||
body: &'a Block,
|
||||
body: Option<&'a Block>,
|
||||
) {
|
||||
let (closure_id, return_impl_trait_id) = match header.asyncness.node {
|
||||
IsAsync::Async {
|
||||
@ -74,7 +74,9 @@ impl<'a> DefCollector<'a> {
|
||||
closure_id, DefPathData::ClosureExpr, span,
|
||||
);
|
||||
this.with_parent(closure_def, |this| {
|
||||
visit::walk_block(this, body);
|
||||
if let Some(body) = body {
|
||||
visit::walk_block(this, body);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -123,7 +125,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
&sig.header,
|
||||
generics,
|
||||
&sig.decl,
|
||||
body,
|
||||
Some(body),
|
||||
)
|
||||
}
|
||||
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
|
||||
@ -237,7 +239,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
header,
|
||||
&ii.generics,
|
||||
decl,
|
||||
body,
|
||||
body.as_deref(),
|
||||
)
|
||||
}
|
||||
ImplItemKind::Method(..) |
|
||||
|
@ -1119,7 +1119,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
||||
ast::ImplItemKind::Method(ref sig, ref body) => {
|
||||
self.process_method(
|
||||
sig,
|
||||
Some(body),
|
||||
body.as_deref(),
|
||||
impl_item.id,
|
||||
impl_item.ident,
|
||||
&impl_item.generics,
|
||||
|
@ -1637,7 +1637,7 @@ pub struct ImplItem<K = ImplItemKind> {
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum ImplItemKind {
|
||||
Const(P<Ty>, Option<P<Expr>>),
|
||||
Method(FnSig, P<Block>),
|
||||
Method(FnSig, Option<P<Block>>),
|
||||
TyAlias(P<Ty>),
|
||||
Macro(Mac),
|
||||
}
|
||||
|
@ -985,7 +985,7 @@ pub fn noop_flat_map_impl_item<T: MutVisitor>(mut item: ImplItem, visitor: &mut
|
||||
}
|
||||
ImplItemKind::Method(sig, body) => {
|
||||
visit_fn_sig(sig, visitor);
|
||||
visitor.visit_block(body);
|
||||
visit_opt(body, |body| visitor.visit_block(body));
|
||||
}
|
||||
ImplItemKind::TyAlias(ty) => visitor.visit_ty(ty),
|
||||
ImplItemKind::Macro(mac) => visitor.visit_mac(mac),
|
||||
|
@ -1553,23 +1553,13 @@ impl<'a> State<'a> {
|
||||
self.print_defaultness(ti.defaultness);
|
||||
match ti.kind {
|
||||
ast::TraitItemKind::Const(ref ty, ref default) => {
|
||||
self.print_associated_const(
|
||||
ti.ident,
|
||||
ty,
|
||||
default.as_ref().map(|expr| &**expr),
|
||||
&source_map::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
|
||||
);
|
||||
self.print_associated_const(ti.ident, ty, default.as_deref(), &ti.vis);
|
||||
}
|
||||
ast::TraitItemKind::Method(ref sig, ref body) => {
|
||||
if body.is_some() {
|
||||
self.head("");
|
||||
}
|
||||
self.print_method_sig(
|
||||
ti.ident,
|
||||
&ti.generics,
|
||||
sig,
|
||||
&source_map::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
|
||||
);
|
||||
self.print_method_sig(ti.ident, &ti.generics, sig, &ti.vis);
|
||||
if let Some(ref body) = *body {
|
||||
self.nbsp();
|
||||
self.print_block_with_attrs(body, &ti.attrs);
|
||||
@ -1602,10 +1592,16 @@ impl<'a> State<'a> {
|
||||
self.print_associated_const(ii.ident, ty, expr.as_deref(), &ii.vis);
|
||||
}
|
||||
ast::ImplItemKind::Method(ref sig, ref body) => {
|
||||
self.head("");
|
||||
if body.is_some() {
|
||||
self.head("");
|
||||
}
|
||||
self.print_method_sig(ii.ident, &ii.generics, sig, &ii.vis);
|
||||
self.nbsp();
|
||||
self.print_block_with_attrs(body, &ii.attrs);
|
||||
if let Some(body) = body {
|
||||
self.nbsp();
|
||||
self.print_block_with_attrs(body, &ii.attrs);
|
||||
} else {
|
||||
self.s.word(";");
|
||||
}
|
||||
}
|
||||
ast::ImplItemKind::TyAlias(ref ty) => {
|
||||
self.print_associated_type(ii.ident, None, Some(ty));
|
||||
|
@ -25,7 +25,7 @@ pub enum FnKind<'a> {
|
||||
ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block),
|
||||
|
||||
/// E.g., `fn foo(&self)`.
|
||||
Method(Ident, &'a FnSig, Option<&'a Visibility>, &'a Block),
|
||||
Method(Ident, &'a FnSig, &'a Visibility, &'a Block),
|
||||
|
||||
/// E.g., `|x, y| body`.
|
||||
Closure(&'a Expr),
|
||||
@ -596,7 +596,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai
|
||||
walk_fn_decl(visitor, &sig.decl);
|
||||
}
|
||||
TraitItemKind::Method(ref sig, Some(ref body)) => {
|
||||
visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None, body),
|
||||
visitor.visit_fn(FnKind::Method(trait_item.ident, sig, &trait_item.vis, body),
|
||||
&sig.decl, trait_item.span, trait_item.id);
|
||||
}
|
||||
TraitItemKind::Type(ref bounds, ref default) => {
|
||||
@ -619,8 +619,12 @@ pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplIt
|
||||
visitor.visit_ty(ty);
|
||||
walk_list!(visitor, visit_expr, expr);
|
||||
}
|
||||
ImplItemKind::Method(ref sig, ref body) => {
|
||||
visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), body),
|
||||
ImplItemKind::Method(ref sig, None) => {
|
||||
visitor.visit_fn_header(&sig.header);
|
||||
walk_fn_decl(visitor, &sig.decl);
|
||||
}
|
||||
ImplItemKind::Method(ref sig, Some(ref body)) => {
|
||||
visitor.visit_fn(FnKind::Method(impl_item.ident, sig, &impl_item.vis, body),
|
||||
&sig.decl, impl_item.span, impl_item.id);
|
||||
}
|
||||
ImplItemKind::TyAlias(ref ty) => {
|
||||
|
@ -956,7 +956,7 @@ impl<'a> MethodDef<'a> {
|
||||
vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited),
|
||||
defaultness: ast::Defaultness::Final,
|
||||
ident: method_ident,
|
||||
kind: ast::ImplItemKind::Method(sig, body_block),
|
||||
kind: ast::ImplItemKind::Method(sig, Some(body_block)),
|
||||
tokens: None,
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
impl A {
|
||||
//~^ ERROR cannot find type `A` in this scope
|
||||
fn b(self>
|
||||
//~^ ERROR expected one of `)`, `,`, or `:`, found `>`
|
||||
//~| ERROR expected `;` or `{`, found `>`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,10 +1,23 @@
|
||||
error: expected one of `)`, `,`, or `:`, found `>`
|
||||
--> $DIR/issue-58856-1.rs:2:14
|
||||
--> $DIR/issue-58856-1.rs:3:14
|
||||
|
|
||||
LL | fn b(self>
|
||||
| - ^ help: `)` may belong here
|
||||
| |
|
||||
| unclosed delimiter
|
||||
|
||||
error: aborting due to previous error
|
||||
error: expected `;` or `{`, found `>`
|
||||
--> $DIR/issue-58856-1.rs:3:14
|
||||
|
|
||||
LL | fn b(self>
|
||||
| ^ expected `;` or `{`
|
||||
|
||||
error[E0412]: cannot find type `A` in this scope
|
||||
--> $DIR/issue-58856-1.rs:1:6
|
||||
|
|
||||
LL | impl A {
|
||||
| ^ not found in this scope
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0412`.
|
||||
|
@ -2,7 +2,9 @@ error: associated constant in `impl` without body
|
||||
--> $DIR/impl-item-const-semantic-fail.rs:6:5
|
||||
|
|
||||
LL | const Y: u8;
|
||||
| ^^^^^^^^^^^^ help: provide a definition for the constant: `const Y: u8 = <expr>;`
|
||||
| ^^^^^^^^^^^-
|
||||
| |
|
||||
| help: provide a definition for the constant: `= <expr>;`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
8
src/test/ui/parser/impl-item-fn-no-body-pass.rs
Normal file
8
src/test/ui/parser/impl-item-fn-no-body-pass.rs
Normal file
@ -0,0 +1,8 @@
|
||||
// check-pass
|
||||
|
||||
fn main() {}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
impl X {
|
||||
fn f();
|
||||
}
|
7
src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs
Normal file
7
src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs
Normal file
@ -0,0 +1,7 @@
|
||||
fn main() {}
|
||||
|
||||
struct X;
|
||||
|
||||
impl X {
|
||||
fn f(); //~ ERROR associated function in `impl` without body
|
||||
}
|
10
src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr
Normal file
10
src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: associated function in `impl` without body
|
||||
--> $DIR/impl-item-fn-no-body-semantic-fail.rs:6:5
|
||||
|
|
||||
LL | fn f();
|
||||
| ^^^^^^-
|
||||
| |
|
||||
| help: provide a definition for the function: `{ <body> }`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user