Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Silence some follow-up errors [1/x] #119803

Merged
merged 3 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2405,6 +2405,39 @@ impl<'hir> Ty<'hir> {
my_visitor.visit_ty(self);
my_visitor.0
}

/// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to
/// use inference to provide suggestions for the appropriate type if possible.
pub fn is_suggestable_infer_ty(&self) -> bool {
fn are_suggestable_generic_args(generic_args: &[GenericArg<'_>]) -> bool {
generic_args.iter().any(|arg| match arg {
GenericArg::Type(ty) => ty.is_suggestable_infer_ty(),
GenericArg::Infer(_) => true,
_ => false,
})
}
debug!(?self);
match &self.kind {
TyKind::Infer => true,
TyKind::Slice(ty) => ty.is_suggestable_infer_ty(),
TyKind::Array(ty, length) => {
ty.is_suggestable_infer_ty() || matches!(length, ArrayLen::Infer(_, _))
}
TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty),
TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(),
TyKind::OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args),
TyKind::Path(QPath::TypeRelative(ty, segment)) => {
ty.is_suggestable_infer_ty() || are_suggestable_generic_args(segment.args().args)
}
TyKind::Path(QPath::Resolved(ty_opt, Path { segments, .. })) => {
ty_opt.is_some_and(Self::is_suggestable_infer_ty)
|| segments
.iter()
.any(|segment| are_suggestable_generic_args(segment.args().args))
}
_ => false,
}
}
}

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

impl FnRetTy<'_> {
impl<'hir> FnRetTy<'hir> {
#[inline]
pub fn span(&self) -> Span {
match *self {
Self::DefaultReturn(span) => span,
Self::Return(ref ty) => ty.span,
}
}

pub fn get_infer_ret_ty(&self) -> Option<&'hir Ty<'hir>> {
if let Self::Return(ty) = self {
if ty.is_suggestable_infer_ty() {
return Some(*ty);
}
}
None
}
}

/// Represents `for<...>` binder before a closure
Expand Down
50 changes: 4 additions & 46 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
tcx.ensure().generics_of(def_id);
tcx.ensure().type_of(def_id);
tcx.ensure().predicates_of(def_id);
if !is_suggestable_infer_ty(ty) {
if !ty.is_suggestable_infer_ty() {
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_item(it);
placeholder_type_error(tcx, None, visitor.0, false, None, it.kind.descr());
Expand Down Expand Up @@ -674,7 +674,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
hir::TraitItemKind::Const(ty, body_id) => {
tcx.ensure().type_of(def_id);
if !tcx.dcx().has_stashed_diagnostic(ty.span, StashKey::ItemNoType)
&& !(is_suggestable_infer_ty(ty) && body_id.is_some())
&& !(ty.is_suggestable_infer_ty() && body_id.is_some())
{
// Account for `const C: _;`.
let mut visitor = HirPlaceholderCollector::default();
Expand Down Expand Up @@ -726,7 +726,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
}
hir::ImplItemKind::Const(ty, _) => {
// Account for `const T: _ = ..;`
if !is_suggestable_infer_ty(ty) {
if !ty.is_suggestable_infer_ty() {
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_impl_item(impl_item);
placeholder_type_error(tcx, None, visitor.0, false, None, "associated constant");
Expand Down Expand Up @@ -1054,48 +1054,6 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
}
}

fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
generic_args.iter().any(|arg| match arg {
hir::GenericArg::Type(ty) => is_suggestable_infer_ty(ty),
hir::GenericArg::Infer(_) => true,
_ => false,
})
}

/// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to
/// use inference to provide suggestions for the appropriate type if possible.
fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
debug!(?ty);
use hir::TyKind::*;
match &ty.kind {
Infer => true,
Slice(ty) => is_suggestable_infer_ty(ty),
Array(ty, length) => {
is_suggestable_infer_ty(ty) || matches!(length, hir::ArrayLen::Infer(_, _))
}
Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
Ptr(mut_ty) | Ref(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args),
Path(hir::QPath::TypeRelative(ty, segment)) => {
is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args)
}
Path(hir::QPath::Resolved(ty_opt, hir::Path { segments, .. })) => {
ty_opt.is_some_and(is_suggestable_infer_ty)
|| segments.iter().any(|segment| are_suggestable_generic_args(segment.args().args))
}
_ => false,
}
}

pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> {
if let hir::FnRetTy::Return(ty) = output {
if is_suggestable_infer_ty(ty) {
return Some(*ty);
}
}
None
}

#[instrument(level = "debug", skip(tcx))]
fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<'_>> {
use rustc_hir::Node::*;
Expand Down Expand Up @@ -1188,7 +1146,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
) -> ty::PolyFnSig<'tcx> {
let hir_id = tcx.local_def_id_to_hir_id(def_id);

match get_infer_ret_ty(&sig.decl.output) {
match sig.decl.output.get_infer_ret_ty() {
Some(ty) => {
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
// Typeck doesn't expect erased regions to be returned from `type_of`.
Expand Down
20 changes: 8 additions & 12 deletions compiler/rustc_hir_analysis/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, Ty
use rustc_span::symbol::Ident;
use rustc_span::{Span, DUMMY_SP};

use super::bad_placeholder;
use super::ItemCtxt;
use super::{bad_placeholder, is_suggestable_infer_ty};
pub use opaque::test_opaque_hidden_types;

mod opaque;
Expand Down Expand Up @@ -368,7 +368,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
}
TraitItemKind::Const(ty, body_id) => body_id
.and_then(|body_id| {
is_suggestable_infer_ty(ty).then(|| {
ty.is_suggestable_infer_ty().then(|| {
infer_placeholder_type(
tcx,
def_id,
Expand All @@ -392,7 +392,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Ty::new_fn_def(tcx, def_id.to_def_id(), args)
}
ImplItemKind::Const(ty, body_id) => {
if is_suggestable_infer_ty(ty) {
if ty.is_suggestable_infer_ty() {
infer_placeholder_type(
tcx,
def_id,
Expand All @@ -416,7 +416,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty

Node::Item(item) => match item.kind {
ItemKind::Static(ty, .., body_id) => {
if is_suggestable_infer_ty(ty) {
if ty.is_suggestable_infer_ty() {
infer_placeholder_type(
tcx,
def_id,
Expand All @@ -430,7 +430,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
}
}
ItemKind::Const(ty, _, body_id) => {
if is_suggestable_infer_ty(ty) {
if ty.is_suggestable_infer_ty() {
infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant")
} else {
icx.to_ty(ty)
Expand Down Expand Up @@ -603,6 +603,8 @@ fn infer_placeholder_type<'a>(
}

err.emit();
// diagnostic stashing loses the information of whether something is a hard error.
Ty::new_error_with_message(tcx, span, "ItemNoType is a hard error")
compiler-errors marked this conversation as resolved.
Show resolved Hide resolved
}
None => {
let mut diag = bad_placeholder(tcx, vec![span], kind);
Expand All @@ -623,15 +625,9 @@ fn infer_placeholder_type<'a>(
}
}

diag.emit();
Ty::new_error(tcx, diag.emit())
}
}

// Typeck doesn't expect erased regions to be returned from `type_of`.
tcx.fold_regions(ty, |r, _| match *r {
ty::ReErased => tcx.lifetimes.re_static,
_ => r,
})
}

fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,21 @@ impl TaitConstraintLocator<'_> {
debug!("no constraint: no typeck results");
return;
}

if let Some(hir_sig) = self.tcx.hir_node_by_def_id(item_def_id).fn_decl() {
if hir_sig.output.get_infer_ret_ty().is_some() {
let guar = self.tcx.dcx().span_delayed_bug(
hir_sig.output.span(),
"inferring return types and opaque types do not mix well",
);
self.found = Some(ty::OpaqueHiddenType {
span: DUMMY_SP,
ty: Ty::new_error(self.tcx, guar),
});
return;
}
}

// Calling `mir_borrowck` can lead to cycle errors through
// const-checking, avoid calling it if we don't have to.
// ```rust
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ fn typeck_with_fallback<'tcx>(
let mut fcx = FnCtxt::new(&inh, param_env, def_id);

if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() {
let fn_sig = if decl.output.get_infer_ret_ty().is_some() {
fcx.astconv().ty_of_fn(id, header.unsafety, header.abi, decl, None, None)
} else {
tcx.fn_sig(def_id).instantiate_identity()
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/type-alias-impl-trait/issue-77179.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ type Pointer<T> = impl std::ops::Deref<Target = T>;

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

fn main() {
Expand Down
26 changes: 2 additions & 24 deletions tests/ui/type-alias-impl-trait/issue-77179.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,6 @@ LL | fn test() -> Pointer<_> {
| | not allowed in type signatures
| help: replace with the correct return type: `Pointer<i32>`

error[E0792]: non-defining opaque type use in defining scope
--> $DIR/issue-77179.rs:7:14
|
LL | fn test() -> Pointer<_> {
| ^^^^^^^^^^ argument `i32` is not a generic parameter
|
note: for this opaque type
--> $DIR/issue-77179.rs:5:19
|
LL | type Pointer<T> = impl std::ops::Deref<Target = T>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0792]: expected generic type parameter, found `i32`
--> $DIR/issue-77179.rs:10:5
|
LL | type Pointer<T> = impl std::ops::Deref<Target = T>;
| - this generic parameter must be used with a generic type parameter
...
LL | Box::new(1)
| ^^^^^^^^^^^

error: aborting due to 3 previous errors
error: aborting due to 1 previous error

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