Skip to content

Commit d37de53

Browse files
authored
Rollup merge of rust-lang#119803 - oli-obk:even_more_follow_up_errors, r=compiler-errors
Silence some follow-up errors [1/x] this is one piece of the requested cleanups from rust-lang#117449 When we use `-> impl SomeTrait<_>` as a return type, we are both using the "infer return type suggestion" code path, and the infer opaque type code path within the same function. That can lead to confusing diagnostics, so silence all opaque type diagnostics in that case.
2 parents d93df41 + 0e82aae commit d37de53

File tree

7 files changed

+73
-86
lines changed

7 files changed

+73
-86
lines changed

Diff for: compiler/rustc_hir/src/hir.rs

+43-1
Original file line numberDiff line numberDiff line change
@@ -2405,6 +2405,39 @@ impl<'hir> Ty<'hir> {
24052405
my_visitor.visit_ty(self);
24062406
my_visitor.0
24072407
}
2408+
2409+
/// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to
2410+
/// use inference to provide suggestions for the appropriate type if possible.
2411+
pub fn is_suggestable_infer_ty(&self) -> bool {
2412+
fn are_suggestable_generic_args(generic_args: &[GenericArg<'_>]) -> bool {
2413+
generic_args.iter().any(|arg| match arg {
2414+
GenericArg::Type(ty) => ty.is_suggestable_infer_ty(),
2415+
GenericArg::Infer(_) => true,
2416+
_ => false,
2417+
})
2418+
}
2419+
debug!(?self);
2420+
match &self.kind {
2421+
TyKind::Infer => true,
2422+
TyKind::Slice(ty) => ty.is_suggestable_infer_ty(),
2423+
TyKind::Array(ty, length) => {
2424+
ty.is_suggestable_infer_ty() || matches!(length, ArrayLen::Infer(_, _))
2425+
}
2426+
TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty),
2427+
TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(),
2428+
TyKind::OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args),
2429+
TyKind::Path(QPath::TypeRelative(ty, segment)) => {
2430+
ty.is_suggestable_infer_ty() || are_suggestable_generic_args(segment.args().args)
2431+
}
2432+
TyKind::Path(QPath::Resolved(ty_opt, Path { segments, .. })) => {
2433+
ty_opt.is_some_and(Self::is_suggestable_infer_ty)
2434+
|| segments
2435+
.iter()
2436+
.any(|segment| are_suggestable_generic_args(segment.args().args))
2437+
}
2438+
_ => false,
2439+
}
2440+
}
24082441
}
24092442

24102443
/// Not represented directly in the AST; referred to by name through a `ty_path`.
@@ -2735,14 +2768,23 @@ pub enum FnRetTy<'hir> {
27352768
Return(&'hir Ty<'hir>),
27362769
}
27372770

2738-
impl FnRetTy<'_> {
2771+
impl<'hir> FnRetTy<'hir> {
27392772
#[inline]
27402773
pub fn span(&self) -> Span {
27412774
match *self {
27422775
Self::DefaultReturn(span) => span,
27432776
Self::Return(ref ty) => ty.span,
27442777
}
27452778
}
2779+
2780+
pub fn get_infer_ret_ty(&self) -> Option<&'hir Ty<'hir>> {
2781+
if let Self::Return(ty) = self {
2782+
if ty.is_suggestable_infer_ty() {
2783+
return Some(*ty);
2784+
}
2785+
}
2786+
None
2787+
}
27462788
}
27472789

27482790
/// Represents `for<...>` binder before a closure

Diff for: compiler/rustc_hir_analysis/src/collect.rs

+4-46
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
642642
tcx.ensure().generics_of(def_id);
643643
tcx.ensure().type_of(def_id);
644644
tcx.ensure().predicates_of(def_id);
645-
if !is_suggestable_infer_ty(ty) {
645+
if !ty.is_suggestable_infer_ty() {
646646
let mut visitor = HirPlaceholderCollector::default();
647647
visitor.visit_item(it);
648648
placeholder_type_error(tcx, None, visitor.0, false, None, it.kind.descr());
@@ -674,7 +674,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
674674
hir::TraitItemKind::Const(ty, body_id) => {
675675
tcx.ensure().type_of(def_id);
676676
if !tcx.dcx().has_stashed_diagnostic(ty.span, StashKey::ItemNoType)
677-
&& !(is_suggestable_infer_ty(ty) && body_id.is_some())
677+
&& !(ty.is_suggestable_infer_ty() && body_id.is_some())
678678
{
679679
// Account for `const C: _;`.
680680
let mut visitor = HirPlaceholderCollector::default();
@@ -726,7 +726,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
726726
}
727727
hir::ImplItemKind::Const(ty, _) => {
728728
// Account for `const T: _ = ..;`
729-
if !is_suggestable_infer_ty(ty) {
729+
if !ty.is_suggestable_infer_ty() {
730730
let mut visitor = HirPlaceholderCollector::default();
731731
visitor.visit_impl_item(impl_item);
732732
placeholder_type_error(tcx, None, visitor.0, false, None, "associated constant");
@@ -1054,48 +1054,6 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
10541054
}
10551055
}
10561056

1057-
fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
1058-
generic_args.iter().any(|arg| match arg {
1059-
hir::GenericArg::Type(ty) => is_suggestable_infer_ty(ty),
1060-
hir::GenericArg::Infer(_) => true,
1061-
_ => false,
1062-
})
1063-
}
1064-
1065-
/// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to
1066-
/// use inference to provide suggestions for the appropriate type if possible.
1067-
fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
1068-
debug!(?ty);
1069-
use hir::TyKind::*;
1070-
match &ty.kind {
1071-
Infer => true,
1072-
Slice(ty) => is_suggestable_infer_ty(ty),
1073-
Array(ty, length) => {
1074-
is_suggestable_infer_ty(ty) || matches!(length, hir::ArrayLen::Infer(_, _))
1075-
}
1076-
Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
1077-
Ptr(mut_ty) | Ref(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
1078-
OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args),
1079-
Path(hir::QPath::TypeRelative(ty, segment)) => {
1080-
is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args)
1081-
}
1082-
Path(hir::QPath::Resolved(ty_opt, hir::Path { segments, .. })) => {
1083-
ty_opt.is_some_and(is_suggestable_infer_ty)
1084-
|| segments.iter().any(|segment| are_suggestable_generic_args(segment.args().args))
1085-
}
1086-
_ => false,
1087-
}
1088-
}
1089-
1090-
pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> {
1091-
if let hir::FnRetTy::Return(ty) = output {
1092-
if is_suggestable_infer_ty(ty) {
1093-
return Some(*ty);
1094-
}
1095-
}
1096-
None
1097-
}
1098-
10991057
#[instrument(level = "debug", skip(tcx))]
11001058
fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<'_>> {
11011059
use rustc_hir::Node::*;
@@ -1188,7 +1146,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
11881146
) -> ty::PolyFnSig<'tcx> {
11891147
let hir_id = tcx.local_def_id_to_hir_id(def_id);
11901148

1191-
match get_infer_ret_ty(&sig.decl.output) {
1149+
match sig.decl.output.get_infer_ret_ty() {
11921150
Some(ty) => {
11931151
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
11941152
// Typeck doesn't expect erased regions to be returned from `type_of`.

Diff for: compiler/rustc_hir_analysis/src/collect/type_of.rs

+8-12
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, Ty
99
use rustc_span::symbol::Ident;
1010
use rustc_span::{Span, DUMMY_SP};
1111

12+
use super::bad_placeholder;
1213
use super::ItemCtxt;
13-
use super::{bad_placeholder, is_suggestable_infer_ty};
1414
pub use opaque::test_opaque_hidden_types;
1515

1616
mod opaque;
@@ -368,7 +368,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
368368
}
369369
TraitItemKind::Const(ty, body_id) => body_id
370370
.and_then(|body_id| {
371-
is_suggestable_infer_ty(ty).then(|| {
371+
ty.is_suggestable_infer_ty().then(|| {
372372
infer_placeholder_type(
373373
tcx,
374374
def_id,
@@ -392,7 +392,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
392392
Ty::new_fn_def(tcx, def_id.to_def_id(), args)
393393
}
394394
ImplItemKind::Const(ty, body_id) => {
395-
if is_suggestable_infer_ty(ty) {
395+
if ty.is_suggestable_infer_ty() {
396396
infer_placeholder_type(
397397
tcx,
398398
def_id,
@@ -416,7 +416,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
416416

417417
Node::Item(item) => match item.kind {
418418
ItemKind::Static(ty, .., body_id) => {
419-
if is_suggestable_infer_ty(ty) {
419+
if ty.is_suggestable_infer_ty() {
420420
infer_placeholder_type(
421421
tcx,
422422
def_id,
@@ -430,7 +430,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
430430
}
431431
}
432432
ItemKind::Const(ty, _, body_id) => {
433-
if is_suggestable_infer_ty(ty) {
433+
if ty.is_suggestable_infer_ty() {
434434
infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant")
435435
} else {
436436
icx.to_ty(ty)
@@ -603,6 +603,8 @@ fn infer_placeholder_type<'a>(
603603
}
604604

605605
err.emit();
606+
// diagnostic stashing loses the information of whether something is a hard error.
607+
Ty::new_error_with_message(tcx, span, "ItemNoType is a hard error")
606608
}
607609
None => {
608610
let mut diag = bad_placeholder(tcx, vec![span], kind);
@@ -623,15 +625,9 @@ fn infer_placeholder_type<'a>(
623625
}
624626
}
625627

626-
diag.emit();
628+
Ty::new_error(tcx, diag.emit())
627629
}
628630
}
629-
630-
// Typeck doesn't expect erased regions to be returned from `type_of`.
631-
tcx.fold_regions(ty, |r, _| match *r {
632-
ty::ReErased => tcx.lifetimes.re_static,
633-
_ => r,
634-
})
635631
}
636632

637633
fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {

Diff for: compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs

+15
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,21 @@ impl TaitConstraintLocator<'_> {
134134
debug!("no constraint: no typeck results");
135135
return;
136136
}
137+
138+
if let Some(hir_sig) = self.tcx.hir_node_by_def_id(item_def_id).fn_decl() {
139+
if hir_sig.output.get_infer_ret_ty().is_some() {
140+
let guar = self.tcx.dcx().span_delayed_bug(
141+
hir_sig.output.span(),
142+
"inferring return types and opaque types do not mix well",
143+
);
144+
self.found = Some(ty::OpaqueHiddenType {
145+
span: DUMMY_SP,
146+
ty: Ty::new_error(self.tcx, guar),
147+
});
148+
return;
149+
}
150+
}
151+
137152
// Calling `mir_borrowck` can lead to cycle errors through
138153
// const-checking, avoid calling it if we don't have to.
139154
// ```rust

Diff for: compiler/rustc_hir_typeck/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ fn typeck_with_fallback<'tcx>(
181181
let mut fcx = FnCtxt::new(&inh, param_env, def_id);
182182

183183
if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
184-
let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() {
184+
let fn_sig = if decl.output.get_infer_ret_ty().is_some() {
185185
fcx.astconv().ty_of_fn(id, header.unsafety, header.abi, decl, None, None)
186186
} else {
187187
tcx.fn_sig(def_id).instantiate_identity()

Diff for: tests/ui/type-alias-impl-trait/issue-77179.rs

-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ type Pointer<T> = impl std::ops::Deref<Target = T>;
66

77
fn test() -> Pointer<_> {
88
//~^ ERROR: the placeholder `_` is not allowed within types
9-
//~| ERROR: non-defining opaque type use in defining scope
109
Box::new(1)
11-
//~^ ERROR expected generic type parameter, found `i32`
1210
}
1311

1412
fn main() {

Diff for: tests/ui/type-alias-impl-trait/issue-77179.stderr

+2-24
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,6 @@ LL | fn test() -> Pointer<_> {
77
| | not allowed in type signatures
88
| help: replace with the correct return type: `Pointer<i32>`
99

10-
error[E0792]: non-defining opaque type use in defining scope
11-
--> $DIR/issue-77179.rs:7:14
12-
|
13-
LL | fn test() -> Pointer<_> {
14-
| ^^^^^^^^^^ argument `i32` is not a generic parameter
15-
|
16-
note: for this opaque type
17-
--> $DIR/issue-77179.rs:5:19
18-
|
19-
LL | type Pointer<T> = impl std::ops::Deref<Target = T>;
20-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21-
22-
error[E0792]: expected generic type parameter, found `i32`
23-
--> $DIR/issue-77179.rs:10:5
24-
|
25-
LL | type Pointer<T> = impl std::ops::Deref<Target = T>;
26-
| - this generic parameter must be used with a generic type parameter
27-
...
28-
LL | Box::new(1)
29-
| ^^^^^^^^^^^
30-
31-
error: aborting due to 3 previous errors
10+
error: aborting due to 1 previous error
3211

33-
Some errors have detailed explanations: E0121, E0792.
34-
For more information about an error, try `rustc --explain E0121`.
12+
For more information about this error, try `rustc --explain E0121`.

0 commit comments

Comments
 (0)