Skip to content

Commit

Permalink
Rollup merge of rust-lang#74270 - davidtwco:issue-74086-more-placehol…
Browse files Browse the repository at this point in the history
…der-type-error, r=estebank

typeck: report placeholder type error w/out span

Fixes rust-lang#74086.

This PR fixes a regression introduced in rust-lang#70369 which meant that an error was not being emitted for invalid placeholder types when there wasn't a span available.

r? @estebank
  • Loading branch information
Manishearth authored Jul 14, 2020
2 parents 70fa235 + 5afbc52 commit bed27ce
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 63 deletions.
4 changes: 2 additions & 2 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3049,14 +3049,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let bare_fn_ty =
ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi));

if let (false, Some(ident_span)) = (self.allow_ty_infer(), ident_span) {
if !self.allow_ty_infer() {
// We always collect the spans for placeholder types when evaluating `fn`s, but we
// only want to emit an error complaining about them if infer types (`_`) are not
// allowed. `allow_ty_infer` gates this behavior. We check for the presence of
// `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
crate::collect::placeholder_type_error(
tcx,
ident_span.shrink_to_hi(),
ident_span.map(|sp| sp.shrink_to_hi()),
&generics.params[..],
visitor.0,
true,
Expand Down
16 changes: 10 additions & 6 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,20 +129,23 @@ struct CollectItemTypesVisitor<'tcx> {
/// all already existing generic type parameters to avoid suggesting a name that is already in use.
crate fn placeholder_type_error(
tcx: TyCtxt<'tcx>,
span: Span,
span: Option<Span>,
generics: &[hir::GenericParam<'_>],
placeholder_types: Vec<Span>,
suggest: bool,
) {
if placeholder_types.is_empty() {
return;
}
let type_name = generics.next_type_param_name(None);

let type_name = generics.next_type_param_name(None);
let mut sugg: Vec<_> =
placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();

if generics.is_empty() {
sugg.push((span, format!("<{}>", type_name)));
if let Some(span) = span {
sugg.push((span, format!("<{}>", type_name)));
}
} else if let Some(arg) = generics.iter().find(|arg| match arg.name {
hir::ParamName::Plain(Ident { name: kw::Underscore, .. }) => true,
_ => false,
Expand All @@ -158,6 +161,7 @@ crate fn placeholder_type_error(
format!(", {}", type_name),
));
}

let mut err = bad_placeholder_type(tcx, placeholder_types);
if suggest {
err.multipart_suggestion(
Expand Down Expand Up @@ -186,7 +190,7 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
let mut visitor = PlaceholderHirTyCollector::default();
visitor.visit_item(item);

placeholder_type_error(tcx, generics.span, &generics.params[..], visitor.0, suggest);
placeholder_type_error(tcx, Some(generics.span), &generics.params[..], visitor.0, suggest);
}

impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
Expand Down Expand Up @@ -722,7 +726,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
// Account for `const C: _;` and `type T = _;`.
let mut visitor = PlaceholderHirTyCollector::default();
visitor.visit_trait_item(trait_item);
placeholder_type_error(tcx, DUMMY_SP, &[], visitor.0, false);
placeholder_type_error(tcx, None, &[], visitor.0, false);
}

hir::TraitItemKind::Type(_, None) => {}
Expand All @@ -745,7 +749,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) {
// Account for `type T = _;`
let mut visitor = PlaceholderHirTyCollector::default();
visitor.visit_impl_item(impl_item);
placeholder_type_error(tcx, DUMMY_SP, &[], visitor.0, false);
placeholder_type_error(tcx, None, &[], visitor.0, false);
}
hir::ImplItemKind::Const(..) => {}
}
Expand Down
4 changes: 4 additions & 0 deletions src/test/ui/issues/issue-74086.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main() {
static BUG: fn(_) -> u8 = |_| 8;
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121]
}
12 changes: 12 additions & 0 deletions src/test/ui/issues/issue-74086.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> $DIR/issue-74086.rs:2:20
|
LL | static BUG: fn(_) -> u8 = |_| 8;
| ^
| |
| not allowed in type signatures
| help: use type parameters instead: `T`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0121`.
2 changes: 2 additions & 0 deletions src/test/ui/typeck/typeck_type_placeholder_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ fn test7(x: _) { let _x: usize = x; }

fn test8(_f: fn() -> _) { }
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures

struct Test9;

Expand Down Expand Up @@ -98,6 +99,7 @@ pub fn main() {

fn fn_test8(_f: fn() -> _) { }
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures

struct FnTest9;

Expand Down
Loading

0 comments on commit bed27ce

Please sign in to comment.