Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Use Option in ImplItemKind::Method.
  • Loading branch information
Centril committed Dec 12, 2019
1 parent 73557fa commit f6403c6
Show file tree
Hide file tree
Showing 17 changed files with 149 additions and 73 deletions.
4 changes: 2 additions & 2 deletions src/librustc/hir/lowering.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)),
}
})
}
Expand Down
71 changes: 48 additions & 23 deletions src/librustc/hir/lowering/item.rs
Expand Up @@ -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),
Expand All @@ -264,6 +264,7 @@ impl LoweringContext<'_> {

fn lower_item_kind(
&mut self,
span: Span,
id: NodeId,
ident: &mut Ident,
attrs: &hir::HirVec<Attribute>,
Expand Down Expand Up @@ -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) => {
Expand All @@ -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) => {
Expand All @@ -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,
Expand Down Expand Up @@ -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) => {
Expand All @@ -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,
Expand Down Expand Up @@ -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);

Expand All @@ -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(
Expand Down Expand Up @@ -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))
}

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, expr: &Expr) -> hir::BodyId {
self.lower_body(|this| (hir_vec![], this.lower_expr(expr)))
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| {
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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()))
})
}

Expand Down
12 changes: 5 additions & 7 deletions src/librustc_parse/parser/item.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -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(
Expand Down
31 changes: 20 additions & 11 deletions src/librustc_passes/ast_validation.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}
_ => {}
Expand Down
10 changes: 6 additions & 4 deletions src/librustc_resolve/def_collector.rs
Expand Up @@ -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 {
Expand All @@ -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);
}
})
})
}
Expand Down Expand Up @@ -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(..) =>
Expand Down Expand Up @@ -237,7 +239,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
header,
&ii.generics,
decl,
body,
body.as_deref(),
)
}
ImplItemKind::Method(..) |
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_save_analysis/dump_visitor.rs
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ast.rs
Expand Up @@ -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),
}
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/mut_visit.rs
Expand Up @@ -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),
Expand Down
26 changes: 11 additions & 15 deletions src/libsyntax/print/pprust.rs
Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down

0 comments on commit f6403c6

Please sign in to comment.