Skip to content

Emit an error when return-type-notation is used with type/const params #111047

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

Merged
merged 2 commits into from
Jun 7, 2023
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
7 changes: 7 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ hir_analysis_return_type_notation_conflicting_bound =
hir_analysis_return_type_notation_equality_bound =
return type notation is not allowed to use type equality

hir_analysis_return_type_notation_illegal_param_const =
return type notation is not allowed for functions that have const parameters
.label = const parameter declared here
hir_analysis_return_type_notation_illegal_param_type =
return type notation is not allowed for functions that have type parameters
.label = type parameter declared here

hir_analysis_return_type_notation_missing_method =
cannot find associated function `{$assoc_name}` for `{$ty_name}`

Expand Down
63 changes: 24 additions & 39 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{walk_generics, Visitor as _};
use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::middle::stability::AllowUnstable;
use rustc_middle::ty::fold::FnMutDelegate;
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
Expand Down Expand Up @@ -1215,6 +1213,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}

let projection_ty = if return_type_notation {
let mut emitted_bad_param_err = false;
// If we have an method return type bound, then we need to substitute
// the method's early bound params with suitable late-bound params.
let mut num_bound_vars = candidate.bound_vars().len();
Expand All @@ -1230,16 +1229,35 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
},
)
.into(),
GenericParamDefKind::Type { .. } => tcx
.mk_bound(
GenericParamDefKind::Type { .. } => {
if !emitted_bad_param_err {
tcx.sess.emit_err(
crate::errors::ReturnTypeNotationIllegalParam::Type {
span: path_span,
param_span: tcx.def_span(param.def_id),
},
);
emitted_bad_param_err = true;
}
tcx.mk_bound(
ty::INNERMOST,
ty::BoundTy {
var: ty::BoundVar::from_usize(num_bound_vars),
kind: ty::BoundTyKind::Param(param.def_id, param.name),
},
)
.into(),
.into()
}
GenericParamDefKind::Const { .. } => {
if !emitted_bad_param_err {
tcx.sess.emit_err(
crate::errors::ReturnTypeNotationIllegalParam::Const {
span: path_span,
param_span: tcx.def_span(param.def_id),
},
);
emitted_bad_param_err = true;
}
let ty = tcx
.type_of(param.def_id)
.no_bound_vars()
Expand Down Expand Up @@ -2468,7 +2486,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
infcx.probe(|_| {
let ocx = ObligationCtxt::new_in_snapshot(&infcx);

let impl_substs = infcx.fresh_item_substs(impl_);
let impl_substs = infcx.fresh_substs_for_item(span, impl_);
let impl_ty = tcx.type_of(impl_).subst(tcx, impl_substs);
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);

Expand Down Expand Up @@ -3755,36 +3773,3 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
}

pub trait InferCtxtExt<'tcx> {
fn fresh_item_substs(&self, def_id: DefId) -> SubstsRef<'tcx>;
}

impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
fn fresh_item_substs(&self, def_id: DefId) -> SubstsRef<'tcx> {
InternalSubsts::for_item(self.tcx, def_id, |param, _| match param.kind {
GenericParamDefKind::Lifetime => self.tcx.lifetimes.re_erased.into(),
GenericParamDefKind::Type { .. } => self
.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::SubstitutionPlaceholder,
span: self.tcx.def_span(def_id),
})
.into(),
GenericParamDefKind::Const { .. } => {
let span = self.tcx.def_span(def_id);
let origin = ConstVariableOrigin {
kind: ConstVariableOriginKind::SubstitutionPlaceholder,
span,
};
self.next_const_var(
self.tcx
.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic"),
origin,
)
.into()
}
})
}
}
18 changes: 18 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,3 +857,21 @@ pub(crate) enum DropImplPolarity {
span: Span,
},
}

#[derive(Diagnostic)]
pub(crate) enum ReturnTypeNotationIllegalParam {
#[diag(hir_analysis_return_type_notation_illegal_param_type)]
Type {
#[primary_span]
span: Span,
#[label]
param_span: Span,
},
#[diag(hir_analysis_return_type_notation_illegal_param_const)]
Const {
#[primary_span]
span: Span,
#[label]
param_span: Span,
},
}
5 changes: 2 additions & 3 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir_analysis::astconv::InferCtxtExt as _;
use rustc_hir_analysis::autoderef::{self, Autoderef};
use rustc_infer::infer::canonical::OriginalQueryValues;
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
Expand Down Expand Up @@ -954,7 +953,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
trait_def_id: DefId,
) {
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
let trait_substs = self.fresh_item_substs(trait_def_id);
let trait_substs = self.fresh_substs_for_item(self.span, trait_def_id);
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_substs);

if self.tcx.is_trait_alias(trait_def_id) {
Expand Down Expand Up @@ -1899,7 +1898,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
&self,
impl_def_id: DefId,
) -> (ty::EarlyBinder<Ty<'tcx>>, SubstsRef<'tcx>) {
(self.tcx.type_of(impl_def_id), self.fresh_item_substs(impl_def_id))
(self.tcx.type_of(impl_def_id), self.fresh_substs_for_item(self.span, impl_def_id))
}

/// Replaces late-bound-regions bound by `value` with `'static` using
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_infer/src/infer/type_variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ pub enum TypeVariableOriginKind {
/// (before it has been determined).
// FIXME(eddyb) distinguish upvar inference variables from the rest.
ClosureSynthetic,
SubstitutionPlaceholder,
AutoDeref,
AdjustmentType,

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/infer/unify_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ pub enum ConstVariableOriginKind {
MiscVariable,
ConstInference,
ConstParameterDefinition(Symbol, DefId),
SubstitutionPlaceholder,
}

#[derive(Copy, Clone, Debug)]
Expand Down
20 changes: 20 additions & 0 deletions tests/ui/async-await/return-type-notation/ty-or-ct-params.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// edition: 2021

#![feature(async_fn_in_trait, return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete

trait Foo {
async fn bar<T>() {}

async fn baz<const N: usize>() {}
}

fn test<T>()
where
T: Foo<bar(): Send, baz(): Send>,
//~^ ERROR return type notation is not allowed for functions that have const parameters
//~| ERROR return type notation is not allowed for functions that have type parameters
{
}

fn main() {}
29 changes: 29 additions & 0 deletions tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/ty-or-ct-params.rs:3:31
|
LL | #![feature(async_fn_in_trait, return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
= note: `#[warn(incomplete_features)]` on by default

error: return type notation is not allowed for functions that have type parameters
--> $DIR/ty-or-ct-params.rs:14:12
|
LL | async fn bar<T>() {}
| - type parameter declared here
...
LL | T: Foo<bar(): Send, baz(): Send>,
| ^^^^^^^^^^^

error: return type notation is not allowed for functions that have const parameters
--> $DIR/ty-or-ct-params.rs:14:25
|
LL | async fn baz<const N: usize>() {}
| -------------- const parameter declared here
...
LL | T: Foo<bar(): Send, baz(): Send>,
| ^^^^^^^^^^^

error: aborting due to 2 previous errors; 1 warning emitted