Auto merge of #97980 - Dylan-DPC:rollup-l8exe4b, r=Dylan-DPC

Rollup of 6 pull requests

Successful merges:

 - #96868 (Stabilize explicit_generic_args_with_impl_trait)
 - #97703 (some additional `need_type_info.rs` cleanup)
 - #97812 (Suggest to swap a struct and a trait in trait impls)
 - #97958 (ExitStatus docs fixups)
 - #97967 (Mention `infer::Trace` methods on `infer::At` methods' docs)
 - #97972 (Update #[doc(html_playground_url)] documentation to mention what the request will be)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-06-11 06:17:54 +00:00
commit 7092d42c04
51 changed files with 495 additions and 368 deletions

View File

@ -1,9 +1,11 @@
#### Note: this error code is no longer emitted by the compiler.
An explicit generic argument was provided when calling a function that An explicit generic argument was provided when calling a function that
uses `impl Trait` in argument position. uses `impl Trait` in argument position.
Erroneous code example: Erroneous code example:
```compile_fail,E0632 ```ignore (no longer an error)
fn foo<T: Copy>(a: T, b: impl Clone) {} fn foo<T: Copy>(a: T, b: impl Clone) {}
foo::<i32>(0i32, "abc".to_string()); foo::<i32>(0i32, "abc".to_string());

View File

@ -95,12 +95,6 @@ typeck-expected-return-type = expected `{$expected}` because of return type
typeck-unconstrained-opaque-type = unconstrained opaque type typeck-unconstrained-opaque-type = unconstrained opaque type
.note = `{$name}` must be used in combination with a concrete type within the same module .note = `{$name}` must be used in combination with a concrete type within the same module
typeck-explicit-generic-args-with-impl-trait =
cannot provide explicit generic arguments when `impl Trait` is used in argument position
.label = explicit generic argument not allowed
.note = see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
.help = add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
typeck-missing-type-params = typeck-missing-type-params =
the type {$parameterCount -> the type {$parameterCount ->
[one] parameter [one] parameter

View File

@ -142,6 +142,8 @@ macro_rules! declare_features {
(accepted, dyn_trait, "1.27.0", Some(44662), None), (accepted, dyn_trait, "1.27.0", Some(44662), None),
/// Allows integer match exhaustiveness checking (RFC 2591). /// Allows integer match exhaustiveness checking (RFC 2591).
(accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None),
/// Allows explicit generic arguments specification with `impl Trait` present.
(accepted, explicit_generic_args_with_impl_trait, "1.63.0", Some(83701), None),
/// Allows arbitrary expressions in key-value attributes at parse time. /// Allows arbitrary expressions in key-value attributes at parse time.
(accepted, extended_key_value_attributes, "1.54.0", Some(78835), None), (accepted, extended_key_value_attributes, "1.54.0", Some(78835), None),
/// Allows resolving absolute paths as paths from other crates. /// Allows resolving absolute paths as paths from other crates.

View File

@ -383,8 +383,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
(active, exclusive_range_pattern, "1.11.0", Some(37854), None), (active, exclusive_range_pattern, "1.11.0", Some(37854), None),
/// Allows exhaustive pattern matching on types that contain uninhabited types. /// Allows exhaustive pattern matching on types that contain uninhabited types.
(active, exhaustive_patterns, "1.13.0", Some(51085), None), (active, exhaustive_patterns, "1.13.0", Some(51085), None),
/// Allows explicit generic arguments specification with `impl Trait` present.
(active, explicit_generic_args_with_impl_trait, "1.56.0", Some(83701), None),
/// Allows defining `extern type`s. /// Allows defining `extern type`s.
(active, extern_types, "1.23.0", Some(43467), None), (active, extern_types, "1.23.0", Some(43467), None),
/// Allows the use of `#[ffi_const]` on foreign functions. /// Allows the use of `#[ffi_const]` on foreign functions.

View File

@ -111,6 +111,9 @@ pub fn eq_impl_headers(
} }
/// Makes `a <: b`, where `a` may or may not be expected. /// Makes `a <: b`, where `a` may or may not be expected.
///
/// See [`At::trace_exp`] and [`Trace::sub`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn sub_exp<T>(self, a_is_expected: bool, a: T, b: T) -> InferResult<'tcx, ()> pub fn sub_exp<T>(self, a_is_expected: bool, a: T, b: T) -> InferResult<'tcx, ()>
where where
T: ToTrace<'tcx>, T: ToTrace<'tcx>,
@ -122,6 +125,9 @@ pub fn sub_exp<T>(self, a_is_expected: bool, a: T, b: T) -> InferResult<'tcx, ()
/// call like `foo(x)`, where `foo: fn(i32)`, you might have /// call like `foo(x)`, where `foo: fn(i32)`, you might have
/// `sup(i32, x)`, since the "expected" type is the type that /// `sup(i32, x)`, since the "expected" type is the type that
/// appears in the signature. /// appears in the signature.
///
/// See [`At::trace`] and [`Trace::sub`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn sup<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()> pub fn sup<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()>
where where
T: ToTrace<'tcx>, T: ToTrace<'tcx>,
@ -130,6 +136,9 @@ pub fn sup<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()>
} }
/// Makes `expected <: actual`. /// Makes `expected <: actual`.
///
/// See [`At::trace`] and [`Trace::sub`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn sub<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()> pub fn sub<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()>
where where
T: ToTrace<'tcx>, T: ToTrace<'tcx>,
@ -138,6 +147,9 @@ pub fn sub<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()>
} }
/// Makes `expected <: actual`. /// Makes `expected <: actual`.
///
/// See [`At::trace_exp`] and [`Trace::eq`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn eq_exp<T>(self, a_is_expected: bool, a: T, b: T) -> InferResult<'tcx, ()> pub fn eq_exp<T>(self, a_is_expected: bool, a: T, b: T) -> InferResult<'tcx, ()>
where where
T: ToTrace<'tcx>, T: ToTrace<'tcx>,
@ -146,6 +158,9 @@ pub fn eq_exp<T>(self, a_is_expected: bool, a: T, b: T) -> InferResult<'tcx, ()>
} }
/// Makes `expected <: actual`. /// Makes `expected <: actual`.
///
/// See [`At::trace`] and [`Trace::eq`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn eq<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()> pub fn eq<T>(self, expected: T, actual: T) -> InferResult<'tcx, ()>
where where
T: ToTrace<'tcx>, T: ToTrace<'tcx>,
@ -176,6 +191,9 @@ pub fn relate<T>(self, expected: T, variance: ty::Variance, actual: T) -> InferR
/// this can result in an error (e.g., if asked to compute LUB of /// this can result in an error (e.g., if asked to compute LUB of
/// u32 and i32), it is meaningful to call one of them the /// u32 and i32), it is meaningful to call one of them the
/// "expected type". /// "expected type".
///
/// See [`At::trace`] and [`Trace::lub`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn lub<T>(self, expected: T, actual: T) -> InferResult<'tcx, T> pub fn lub<T>(self, expected: T, actual: T) -> InferResult<'tcx, T>
where where
T: ToTrace<'tcx>, T: ToTrace<'tcx>,
@ -186,6 +204,9 @@ pub fn lub<T>(self, expected: T, actual: T) -> InferResult<'tcx, T>
/// Computes the greatest-lower-bound, or mutual subtype, of two /// Computes the greatest-lower-bound, or mutual subtype, of two
/// values. As with `lub` order doesn't matter, except for error /// values. As with `lub` order doesn't matter, except for error
/// cases. /// cases.
///
/// See [`At::trace`] and [`Trace::glb`] for a version of
/// this method that only requires `T: Relate<'tcx>`
pub fn glb<T>(self, expected: T, actual: T) -> InferResult<'tcx, T> pub fn glb<T>(self, expected: T, actual: T) -> InferResult<'tcx, T>
where where
T: ToTrace<'tcx>, T: ToTrace<'tcx>,

View File

@ -67,10 +67,8 @@
use rustc_middle::dep_graph::DepContext; use rustc_middle::dep_graph::DepContext;
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, self, error::TypeError, Binder, List, Region, Subst, Ty, TyCtxt, TypeFoldable,
error::TypeError, TypeSuperFoldable,
subst::{GenericArgKind, Subst, SubstsRef},
Binder, EarlyBinder, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
}; };
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi; use rustc_target::spec::abi;
@ -926,10 +924,13 @@ fn cmp_type_arg(
mut t1_out: &mut DiagnosticStyledString, mut t1_out: &mut DiagnosticStyledString,
mut t2_out: &mut DiagnosticStyledString, mut t2_out: &mut DiagnosticStyledString,
path: String, path: String,
sub: ty::subst::SubstsRef<'tcx>, sub: &'tcx [ty::GenericArg<'tcx>],
other_path: String, other_path: String,
other_ty: Ty<'tcx>, other_ty: Ty<'tcx>,
) -> Option<()> { ) -> Option<()> {
// FIXME/HACK: Go back to `SubstsRef` to use its inherent methods,
// ideally that shouldn't be necessary.
let sub = self.tcx.intern_substs(sub);
for (i, ta) in sub.types().enumerate() { for (i, ta) in sub.types().enumerate() {
if ta == other_ty { if ta == other_ty {
self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, other_ty); self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, other_ty);
@ -960,45 +961,6 @@ fn push_comma(
} }
} }
/// For generic types with parameters with defaults, remove the parameters corresponding to
/// the defaults. This repeats a lot of the logic found in `ty::print::pretty`.
fn strip_generic_default_params(
&self,
def_id: DefId,
substs: ty::subst::SubstsRef<'tcx>,
) -> SubstsRef<'tcx> {
let generics = self.tcx.generics_of(def_id);
let mut num_supplied_defaults = 0;
let default_params = generics.params.iter().rev().filter_map(|param| match param.kind {
ty::GenericParamDefKind::Type { has_default: true, .. } => Some(param.def_id),
ty::GenericParamDefKind::Const { has_default: true } => Some(param.def_id),
_ => None,
});
for (def_id, actual) in iter::zip(default_params, substs.iter().rev()) {
match actual.unpack() {
GenericArgKind::Const(c) => {
if EarlyBinder(self.tcx.const_param_default(def_id)).subst(self.tcx, substs)
!= c
{
break;
}
}
GenericArgKind::Type(ty) => {
if self.tcx.bound_type_of(def_id).subst(self.tcx, substs) != ty {
break;
}
}
_ => break,
}
num_supplied_defaults += 1;
}
let len = generics.params.len();
let mut generics = generics.clone();
generics.params.truncate(len - num_supplied_defaults);
substs.truncate_to(self.tcx, &generics)
}
/// Given two `fn` signatures highlight only sub-parts that are different. /// Given two `fn` signatures highlight only sub-parts that are different.
fn cmp_fn_sig( fn cmp_fn_sig(
&self, &self,
@ -1156,8 +1118,10 @@ fn push_ty_ref<'tcx>(
(&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => { (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
let did1 = def1.did(); let did1 = def1.did();
let did2 = def2.did(); let did2 = def2.did();
let sub_no_defaults_1 = self.strip_generic_default_params(did1, sub1); let sub_no_defaults_1 =
let sub_no_defaults_2 = self.strip_generic_default_params(did2, sub2); self.tcx.generics_of(did1).own_substs_no_defaults(self.tcx, sub1);
let sub_no_defaults_2 =
self.tcx.generics_of(did2).own_substs_no_defaults(self.tcx, sub2);
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new()); let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
let path1 = self.tcx.def_path_str(did1); let path1 = self.tcx.def_path_str(did1);
let path2 = self.tcx.def_path_str(did2); let path2 = self.tcx.def_path_str(did2);

View File

@ -2,6 +2,7 @@
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def::{CtorOf, DefKind, Namespace};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor};
@ -11,7 +12,7 @@
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, InferConst}; use rustc_middle::ty::{self, DefIdTree, InferConst};
use rustc_middle::ty::{Ty, TyCtxt, TypeckResults}; use rustc_middle::ty::{Ty, TyCtxt, TypeckResults};
use rustc_span::symbol::{kw, Ident}; use rustc_span::symbol::{kw, Ident};
use rustc_span::{BytePos, Span}; use rustc_span::{BytePos, Span};
@ -853,12 +854,23 @@ fn path_inferred_subst_iter(
hir::TyKind::Path(hir::QPath::Resolved(_self_ty, path)), hir::TyKind::Path(hir::QPath::Resolved(_self_ty, path)),
) => { ) => {
if tcx.res_generics_def_id(path.res) != Some(def.did()) { if tcx.res_generics_def_id(path.res) != Some(def.did()) {
bug!( match path.res {
"unexpected path: def={:?} substs={:?} path={:?}", Res::Def(DefKind::TyAlias, _) => {
def, // FIXME: Ideally we should support this. For that
substs, // we have to map back from the self type to the
path, // type alias though. That's difficult.
); //
// See the `need_type_info/type-alias.rs` test for
// some examples.
}
// There cannot be inference variables in the self type,
// so there's nothing for us to do here.
Res::SelfTy { .. } => {}
_ => warn!(
"unexpected path: def={:?} substs={:?} path={:?}",
def, substs, path,
),
}
} else { } else {
return Box::new( return Box::new(
self.resolved_path_inferred_subst_iter(path, substs) self.resolved_path_inferred_subst_iter(path, substs)
@ -958,26 +970,8 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg)) generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg))
{ {
let substs = self.infcx.resolve_vars_if_possible(substs); let substs = self.infcx.resolve_vars_if_possible(substs);
let num_args = generics let generic_args = &generics.own_substs_no_defaults(tcx, substs)
.params [generics.own_counts().lifetimes..];
.iter()
.rev()
.filter(|&p| !matches!(p.kind, GenericParamDefKind::Lifetime))
.skip_while(|&param| {
if let Some(default) = param.default_value(tcx) {
// FIXME: Using structural comparisions has a bunch of false negatives.
//
// We should instead try to replace inference variables with placeholders and
// then use `infcx.can_eq`. That probably should be a separate method
// generally used during error reporting.
default.subst(tcx, substs) == substs[param.index as usize]
} else {
false
}
})
.count();
let generic_args =
&generics.own_substs(substs)[generics.own_counts().lifetimes..][..num_args];
let span = match expr.kind { let span = match expr.kind {
ExprKind::MethodCall(path, _, _) => path.ident.span, ExprKind::MethodCall(path, _, _) => path.ident.span,
_ => expr.span, _ => expr.span,

View File

@ -228,8 +228,47 @@ pub fn has_impl_trait(&'tcx self) -> bool {
}) })
} }
/// Returns the substs corresponding to the generic parameters
/// of this item, excluding `Self`.
///
/// **This should only be used for diagnostics purposes.**
pub fn own_substs_no_defaults(
&'tcx self,
tcx: TyCtxt<'tcx>,
substs: &'tcx [ty::GenericArg<'tcx>],
) -> &'tcx [ty::GenericArg<'tcx>] {
let mut own_params = self.parent_count..self.count();
if self.has_self && self.parent.is_none() {
own_params.start = 1;
}
// Filter the default arguments.
//
// This currently uses structural equality instead
// of semantic equivalance. While not ideal, that's
// good enough for now as this should only be used
// for diagnostics anyways.
own_params.end -= self
.params
.iter()
.rev()
.take_while(|param| {
param.default_value(tcx).map_or(false, |default| {
default.subst(tcx, substs) == substs[param.index as usize]
})
})
.count();
&substs[own_params]
}
/// Returns the substs corresponding to the generic parameters of this item, excluding `Self`. /// Returns the substs corresponding to the generic parameters of this item, excluding `Self`.
pub fn own_substs(&'tcx self, substs: SubstsRef<'tcx>) -> &'tcx [ty::GenericArg<'tcx>] { ///
/// **This should only be used for diagnostics purposes.**
pub fn own_substs(
&'tcx self,
substs: &'tcx [ty::GenericArg<'tcx>],
) -> &'tcx [ty::GenericArg<'tcx>] {
let own = &substs[self.parent_count..][..self.params.len()]; let own = &substs[self.parent_count..][..self.params.len()];
if self.has_self && self.parent.is_none() { &own[1..] } else { &own } if self.has_self && self.parent.is_none() { &own[1..] } else { &own }
} }

View File

@ -22,7 +22,6 @@
use crate::traits::{self, Reveal}; use crate::traits::{self, Reveal};
use crate::ty; use crate::ty;
use crate::ty::fast_reject::SimplifiedType; use crate::ty::fast_reject::SimplifiedType;
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
use crate::ty::util::Discr; use crate::ty::util::Discr;
pub use adt::*; pub use adt::*;
pub use assoc::*; pub use assoc::*;
@ -44,6 +43,7 @@
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span; use rustc_span::Span;
use rustc_target::abi::Align; use rustc_target::abi::Align;
pub use subst::*;
pub use vtable::*; pub use vtable::*;
use std::fmt::Debug; use std::fmt::Debug;

View File

@ -149,7 +149,7 @@ fn default_print_def_path(
// on top of the same path, but without its own generics. // on top of the same path, but without its own generics.
_ => { _ => {
if !generics.params.is_empty() && substs.len() >= generics.count() { if !generics.params.is_empty() && substs.len() >= generics.count() {
let args = self.generic_args_to_print(generics, substs); let args = generics.own_substs_no_defaults(self.tcx(), substs);
return self.path_generic_args( return self.path_generic_args(
|cx| cx.print_def_path(def_id, parent_substs), |cx| cx.print_def_path(def_id, parent_substs),
args, args,
@ -184,43 +184,6 @@ fn default_print_def_path(
} }
} }
fn generic_args_to_print(
&self,
generics: &'tcx ty::Generics,
substs: &'tcx [GenericArg<'tcx>],
) -> &'tcx [GenericArg<'tcx>] {
let mut own_params = generics.parent_count..generics.count();
// Don't print args for `Self` parameters (of traits).
if generics.has_self && own_params.start == 0 {
own_params.start = 1;
}
// Don't print args that are the defaults of their respective parameters.
own_params.end -= generics
.params
.iter()
.rev()
.take_while(|param| match param.kind {
ty::GenericParamDefKind::Lifetime => false,
ty::GenericParamDefKind::Type { has_default, .. } => {
has_default
&& substs[param.index as usize]
== GenericArg::from(
self.tcx().bound_type_of(param.def_id).subst(self.tcx(), substs),
)
}
ty::GenericParamDefKind::Const { has_default } => {
has_default
&& substs[param.index as usize]
== GenericArg::from(self.tcx().const_param_default(param.def_id))
}
})
.count();
&substs[own_params]
}
fn default_print_impl_path( fn default_print_impl_path(
self, self,
impl_def_id: DefId, impl_def_id: DefId,

View File

@ -825,12 +825,11 @@ fn pretty_print_opaque_impl_type(
for (fn_once_trait_ref, entry) in fn_traits { for (fn_once_trait_ref, entry) in fn_traits {
// Get the (single) generic ty (the args) of this FnOnce trait ref. // Get the (single) generic ty (the args) of this FnOnce trait ref.
let generics = self.generic_args_to_print( let generics = self.tcx().generics_of(fn_once_trait_ref.def_id());
self.tcx().generics_of(fn_once_trait_ref.def_id()), let args =
fn_once_trait_ref.skip_binder().substs, generics.own_substs_no_defaults(self.tcx(), fn_once_trait_ref.skip_binder().substs);
);
match (entry.return_ty, generics[0].expect_ty()) { match (entry.return_ty, args[0].expect_ty()) {
// We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
// a return type. // a return type.
(Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => { (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => {
@ -892,15 +891,13 @@ fn pretty_print_opaque_impl_type(
print(trait_ref.skip_binder().print_only_trait_name()) print(trait_ref.skip_binder().print_only_trait_name())
); );
let generics = self.generic_args_to_print( let generics = self.tcx().generics_of(trait_ref.def_id());
self.tcx().generics_of(trait_ref.def_id()), let args = generics.own_substs_no_defaults(self.tcx(), trait_ref.skip_binder().substs);
trait_ref.skip_binder().substs,
);
if !generics.is_empty() || !assoc_items.is_empty() { if !args.is_empty() || !assoc_items.is_empty() {
let mut first = true; let mut first = true;
for ty in generics { for ty in args {
if first { if first {
p!("<"); p!("<");
first = false; first = false;
@ -1071,10 +1068,10 @@ fn pretty_print_dyn_existential(
let dummy_cx = cx.tcx().mk_ty_infer(ty::FreshTy(0)); let dummy_cx = cx.tcx().mk_ty_infer(ty::FreshTy(0));
let principal = principal.with_self_ty(cx.tcx(), dummy_cx); let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
let args = cx.generic_args_to_print( let args = cx
cx.tcx().generics_of(principal.def_id), .tcx()
principal.substs, .generics_of(principal.def_id)
); .own_substs_no_defaults(cx.tcx(), principal.substs);
// Don't print `'_` if there's no unerased regions. // Don't print `'_` if there's no unerased regions.
let print_regions = args.iter().any(|arg| match arg.unpack() { let print_regions = args.iter().any(|arg| match arg.unpack() {

View File

@ -513,6 +513,9 @@ struct DiagnosticMetadata<'ast> {
/// The current impl items (used to suggest). /// The current impl items (used to suggest).
current_impl_items: Option<&'ast [P<AssocItem>]>, current_impl_items: Option<&'ast [P<AssocItem>]>,
/// When processing impl trait
currently_processing_impl_trait: Option<(TraitRef, Ty)>,
} }
struct LateResolutionVisitor<'a, 'b, 'ast> { struct LateResolutionVisitor<'a, 'b, 'ast> {
@ -2087,18 +2090,22 @@ fn with_trait_items<T>(
fn with_optional_trait_ref<T>( fn with_optional_trait_ref<T>(
&mut self, &mut self,
opt_trait_ref: Option<&TraitRef>, opt_trait_ref: Option<&TraitRef>,
self_type: &'ast Ty,
f: impl FnOnce(&mut Self, Option<DefId>) -> T, f: impl FnOnce(&mut Self, Option<DefId>) -> T,
) -> T { ) -> T {
let mut new_val = None; let mut new_val = None;
let mut new_id = None; let mut new_id = None;
if let Some(trait_ref) = opt_trait_ref { if let Some(trait_ref) = opt_trait_ref {
let path: Vec<_> = Segment::from_path(&trait_ref.path); let path: Vec<_> = Segment::from_path(&trait_ref.path);
self.diagnostic_metadata.currently_processing_impl_trait =
Some((trait_ref.clone(), self_type.clone()));
let res = self.smart_resolve_path_fragment( let res = self.smart_resolve_path_fragment(
None, None,
&path, &path,
PathSource::Trait(AliasPossibility::No), PathSource::Trait(AliasPossibility::No),
Finalize::new(trait_ref.ref_id, trait_ref.path.span), Finalize::new(trait_ref.ref_id, trait_ref.path.span),
); );
self.diagnostic_metadata.currently_processing_impl_trait = None;
if let Some(def_id) = res.base_res().opt_def_id() { if let Some(def_id) = res.base_res().opt_def_id() {
new_id = Some(def_id); new_id = Some(def_id);
new_val = Some((self.r.expect_module(def_id), trait_ref.clone())); new_val = Some((self.r.expect_module(def_id), trait_ref.clone()));
@ -2139,7 +2146,7 @@ fn resolve_implementation(
this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| { this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| {
this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter(item_id), |this| { this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter(item_id), |this| {
// Resolve the trait reference, if necessary. // Resolve the trait reference, if necessary.
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| { this.with_optional_trait_ref(opt_trait_reference.as_ref(), self_type, |this, trait_id| {
let item_def_id = this.r.local_def_id(item_id); let item_def_id = this.r.local_def_id(item_id);
// Register the trait definitions from here. // Register the trait definitions from here.

View File

@ -146,6 +146,8 @@ pub(crate) fn smart_resolve_report_errors(
let is_expected = &|res| source.is_expected(res); let is_expected = &|res| source.is_expected(res);
let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _)); let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _));
debug!(?res, ?source);
// Make the base error. // Make the base error.
struct BaseError<'a> { struct BaseError<'a> {
msg: String, msg: String,
@ -250,6 +252,8 @@ struct BaseError<'a> {
let mut err = let mut err =
self.r.session.struct_span_err_with_code(base_error.span, &base_error.msg, code); self.r.session.struct_span_err_with_code(base_error.span, &base_error.msg, code);
self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);
if let Some(sugg) = base_error.suggestion { if let Some(sugg) = base_error.suggestion {
err.span_suggestion_verbose(sugg.0, sugg.1, sugg.2, Applicability::MaybeIncorrect); err.span_suggestion_verbose(sugg.0, sugg.1, sugg.2, Applicability::MaybeIncorrect);
} }
@ -692,6 +696,35 @@ fn detect_assoct_type_constraint_meant_as_path(&self, base_span: Span, err: &mut
} }
} }
fn suggest_swapping_misplaced_self_ty_and_trait(
&mut self,
err: &mut Diagnostic,
source: PathSource<'_>,
res: Option<Res>,
span: Span,
) {
if let Some((trait_ref, self_ty)) =
self.diagnostic_metadata.currently_processing_impl_trait.clone()
&& let TyKind::Path(_, self_ty_path) = &self_ty.kind
&& let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
self.resolve_path(&Segment::from_path(self_ty_path), Some(TypeNS), None)
&& let ModuleKind::Def(DefKind::Trait, ..) = module.kind
&& trait_ref.path.span == span
&& let PathSource::Trait(_) = source
&& let Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)) = res
&& let Ok(self_ty_str) =
self.r.session.source_map().span_to_snippet(self_ty.span)
&& let Ok(trait_ref_str) =
self.r.session.source_map().span_to_snippet(trait_ref.path.span)
{
err.multipart_suggestion(
"`impl` items mention the trait being implemented first and the type it is being implemented for second",
vec![(trait_ref.path.span, self_ty_str), (self_ty.span, trait_ref_str)],
Applicability::MaybeIncorrect,
);
}
}
fn get_single_associated_item( fn get_single_associated_item(
&mut self, &mut self,
path: &[Segment], path: &[Segment],

View File

@ -333,7 +333,7 @@ impl<'a> FileNameDisplay<'a> {
pub fn to_string_lossy(&self) -> Cow<'a, str> { pub fn to_string_lossy(&self) -> Cow<'a, str> {
match self.inner { match self.inner {
FileName::Real(ref inner) => inner.to_string_lossy(self.display_pref), FileName::Real(ref inner) => inner.to_string_lossy(self.display_pref),
_ => Cow::from(format!("{}", self)), _ => Cow::from(self.to_string()),
} }
} }
} }

View File

@ -3,7 +3,7 @@
AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
GenericArgCountResult, GenericArgPosition, GenericArgCountResult, GenericArgPosition,
}; };
use crate::errors::{AssocTypeBindingNotAllowed, ExplicitGenericArgsWithImplTrait}; use crate::errors::AssocTypeBindingNotAllowed;
use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs}; use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
use rustc_ast::ast::ParamKindOrd; use rustc_ast::ast::ParamKindOrd;
use rustc_errors::{struct_span_err, Applicability, Diagnostic, MultiSpan}; use rustc_errors::{struct_span_err, Applicability, Diagnostic, MultiSpan};
@ -397,8 +397,6 @@ pub fn check_generic_arg_count_for_call(
is_method_call: IsMethodCall, is_method_call: IsMethodCall,
) -> GenericArgCountResult { ) -> GenericArgCountResult {
let empty_args = hir::GenericArgs::none(); let empty_args = hir::GenericArgs::none();
let suppress_mismatch = Self::check_impl_trait(tcx, seg, generics);
let gen_args = seg.args.unwrap_or(&empty_args); let gen_args = seg.args.unwrap_or(&empty_args);
let gen_pos = if is_method_call == IsMethodCall::Yes { let gen_pos = if is_method_call == IsMethodCall::Yes {
GenericArgPosition::MethodCall GenericArgPosition::MethodCall
@ -406,10 +404,17 @@ pub fn check_generic_arg_count_for_call(
GenericArgPosition::Value GenericArgPosition::Value
}; };
let has_self = generics.parent.is_none() && generics.has_self; let has_self = generics.parent.is_none() && generics.has_self;
let infer_args = seg.infer_args || suppress_mismatch;
Self::check_generic_arg_count( Self::check_generic_arg_count(
tcx, span, def_id, seg, generics, gen_args, gen_pos, has_self, infer_args, tcx,
span,
def_id,
seg,
generics,
gen_args,
gen_pos,
has_self,
seg.infer_args,
) )
} }
@ -431,19 +436,14 @@ pub(crate) fn check_generic_arg_count(
let param_counts = gen_params.own_counts(); let param_counts = gen_params.own_counts();
// Subtracting from param count to ensure type params synthesized from `impl Trait` // Subtracting from param count to ensure type params synthesized from `impl Trait`
// cannot be explicitly specified even with `explicit_generic_args_with_impl_trait` // cannot be explicitly specified.
// feature enabled. let synth_type_param_count = gen_params
let synth_type_param_count = if tcx.features().explicit_generic_args_with_impl_trait { .params
gen_params .iter()
.params .filter(|param| {
.iter() matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. })
.filter(|param| { })
matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }) .count();
})
.count()
} else {
0
};
let named_type_param_count = let named_type_param_count =
param_counts.types - has_self as usize - synth_type_param_count; param_counts.types - has_self as usize - synth_type_param_count;
let infer_lifetimes = let infer_lifetimes =
@ -611,40 +611,6 @@ pub(crate) fn check_generic_arg_count(
} }
} }
/// Report error if there is an explicit type parameter when using `impl Trait`.
pub(crate) fn check_impl_trait(
tcx: TyCtxt<'_>,
seg: &hir::PathSegment<'_>,
generics: &ty::Generics,
) -> bool {
if seg.infer_args || tcx.features().explicit_generic_args_with_impl_trait {
return false;
}
let impl_trait = generics.has_impl_trait();
if impl_trait {
let spans = seg
.args()
.args
.iter()
.filter_map(|arg| match arg {
GenericArg::Infer(_) | GenericArg::Type(_) | GenericArg::Const(_) => {
Some(arg.span())
}
_ => None,
})
.collect::<Vec<_>>();
tcx.sess.emit_err(ExplicitGenericArgsWithImplTrait {
spans,
is_nightly_build: tcx.sess.is_nightly_build().then_some(()),
});
}
impl_trait
}
/// Emits an error regarding forbidden type binding associations /// Emits an error regarding forbidden type binding associations
pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) { pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) {
tcx.sess.emit_err(AssocTypeBindingNotAllowed { span }); tcx.sess.emit_err(AssocTypeBindingNotAllowed { span });

View File

@ -241,17 +241,6 @@ pub struct UnconstrainedOpaqueType {
pub name: Symbol, pub name: Symbol,
} }
#[derive(SessionDiagnostic)]
#[error(code = "E0632", slug = "typeck-explicit-generic-args-with-impl-trait")]
#[note]
pub struct ExplicitGenericArgsWithImplTrait {
#[primary_span]
#[label]
pub spans: Vec<Span>,
#[help]
pub is_nightly_build: Option<()>,
}
pub struct MissingTypeParams { pub struct MissingTypeParams {
pub span: Span, pub span: Span,
pub def_span: Span, pub def_span: Span,

View File

@ -1417,13 +1417,13 @@ fn from(file: fs::File) -> Stdio {
/// For proper error reporting of failed processes, print the value of `ExitStatus` or /// For proper error reporting of failed processes, print the value of `ExitStatus` or
/// `ExitStatusError` using their implementations of [`Display`](crate::fmt::Display). /// `ExitStatusError` using their implementations of [`Display`](crate::fmt::Display).
/// ///
/// # Differences from `ExitStatus` /// # Differences from `ExitCode`
/// ///
/// `ExitCode` is intended for terminating the currently running process, via /// [`ExitCode`] is intended for terminating the currently running process, via
/// the `Termination` trait, in contrast to [`ExitStatus`], which represents the /// the `Termination` trait, in contrast to `ExitStatus`, which represents the
/// termination of a child process. These APIs are separate due to platform /// termination of a child process. These APIs are separate due to platform
/// compatibility differences and their expected usage; it is not generally /// compatibility differences and their expected usage; it is not generally
/// possible to exactly reproduce an ExitStatus from a child for the current /// possible to exactly reproduce an `ExitStatus` from a child for the current
/// process after the fact. /// process after the fact.
/// ///
/// [`status`]: Command::status /// [`status`]: Command::status
@ -1684,7 +1684,7 @@ impl crate::error::Error for ExitStatusError {}
/// the `Termination` trait, in contrast to [`ExitStatus`], which represents the /// the `Termination` trait, in contrast to [`ExitStatus`], which represents the
/// termination of a child process. These APIs are separate due to platform /// termination of a child process. These APIs are separate due to platform
/// compatibility differences and their expected usage; it is not generally /// compatibility differences and their expected usage; it is not generally
/// possible to exactly reproduce an ExitStatus from a child for the current /// possible to exactly reproduce an `ExitStatus` from a child for the current
/// process after the fact. /// process after the fact.
/// ///
/// # Examples /// # Examples

View File

@ -87,7 +87,9 @@ on your documentation examples make requests to.
#![doc(html_playground_url = "https://playground.example.com/")] #![doc(html_playground_url = "https://playground.example.com/")]
``` ```
Now, when you press "run", the button will make a request to this domain. Now, when you press "run", the button will make a request to this domain. The request
URL will contain 2 query parameters: `code` and `edition` for the code in the documentation
and the Rust edition respectively.
If you don't use this attribute, there will be no run buttons. If you don't use this attribute, there will be no run buttons.

View File

@ -1,53 +0,0 @@
# `explicit_generic_args_with_impl_trait`
The tracking issue for this feature is: [#83701]
[#83701]: https://github.com/rust-lang/rust/issues/83701
------------------------
The `explicit_generic_args_with_impl_trait` feature gate lets you specify generic arguments even
when `impl Trait` is used in argument position.
A simple example is:
```rust
#![feature(explicit_generic_args_with_impl_trait)]
fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
fn main() {
foo::<str>("".to_string());
}
```
This is currently rejected:
```text
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
--> src/main.rs:6:11
|
6 | foo::<str>("".to_string());
| ^^^ explicit generic argument not allowed
```
However it would compile if `explicit_generic_args_with_impl_trait` is enabled.
Note that the synthetic type parameters from `impl Trait` are still implicit and you
cannot explicitly specify these:
```rust,compile_fail
#![feature(explicit_generic_args_with_impl_trait)]
fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
fn bar<T: ?Sized, F: AsRef<T>>(_f: F) {}
fn main() {
bar::<str, _>("".to_string()); // Okay
bar::<str, String>("".to_string()); // Okay
foo::<str>("".to_string()); // Okay
foo::<str, String>("".to_string()); // Error, you cannot specify `impl Trait` explicitly
}
```

View File

@ -15,12 +15,12 @@ impl Traitor<1, 2> for u64 {}
fn uwu<const N: u8>() -> impl Traitor<N> { fn uwu<const N: u8>() -> impl Traitor<N> {
//~^ error: the trait bound `u32: Traitor<N, N>` is not satisfied //~^ error: the trait bound `u32: Traitor<N>` is not satisfied
1_u32 1_u32
} }
fn owo() -> impl Traitor { fn owo() -> impl Traitor {
//~^ error: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied //~^ error: the trait bound `u64: Traitor` is not satisfied
1_u64 1_u64
} }

View File

@ -6,21 +6,21 @@ LL | fn rawr() -> impl Trait {
| |
= help: the trait `Trait` is implemented for `Uwu<N>` = help: the trait `Trait` is implemented for `Uwu<N>`
error[E0277]: the trait bound `u32: Traitor<N, N>` is not satisfied error[E0277]: the trait bound `u32: Traitor<N>` is not satisfied
--> $DIR/rp_impl_trait_fail.rs:17:26 --> $DIR/rp_impl_trait_fail.rs:17:26
| |
LL | fn uwu<const N: u8>() -> impl Traitor<N> { LL | fn uwu<const N: u8>() -> impl Traitor<N> {
| ^^^^^^^^^^^^^^^ the trait `Traitor<N, N>` is not implemented for `u32` | ^^^^^^^^^^^^^^^ the trait `Traitor<N>` is not implemented for `u32`
| |
= help: the following other types implement trait `Traitor<N, M>`: = help: the following other types implement trait `Traitor<N, M>`:
<u32 as Traitor<N, 2_u8>> <u32 as Traitor<N, 2_u8>>
<u64 as Traitor<1_u8, 2_u8>> <u64 as Traitor<1_u8, 2_u8>>
error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied error[E0277]: the trait bound `u64: Traitor` is not satisfied
--> $DIR/rp_impl_trait_fail.rs:22:13 --> $DIR/rp_impl_trait_fail.rs:22:13
| |
LL | fn owo() -> impl Traitor { LL | fn owo() -> impl Traitor {
| ^^^^^^^^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64` | ^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u64`
| |
= help: the following other types implement trait `Traitor<N, M>`: = help: the following other types implement trait `Traitor<N, M>`:
<u32 as Traitor<N, 2_u8>> <u32 as Traitor<N, 2_u8>>

View File

@ -26,5 +26,5 @@ fn main() {
foo(&10_u32); foo(&10_u32);
//~^ error: the trait bound `u32: Trait` is not satisfied //~^ error: the trait bound `u32: Trait` is not satisfied
bar(&true); bar(&true);
//~^ error: the trait bound `bool: Traitor<{_: u8}, {_: u8}>` is not satisfied //~^ error: the trait bound `bool: Traitor<{_: u8}>` is not satisfied
} }

View File

@ -9,16 +9,16 @@ LL | foo(&10_u32);
= help: the trait `Trait<2_u8>` is implemented for `u32` = help: the trait `Trait<2_u8>` is implemented for `u32`
= note: required for the cast to the object type `dyn Trait` = note: required for the cast to the object type `dyn Trait`
error[E0277]: the trait bound `bool: Traitor<{_: u8}, {_: u8}>` is not satisfied error[E0277]: the trait bound `bool: Traitor<{_: u8}>` is not satisfied
--> $DIR/trait_objects_fail.rs:28:9 --> $DIR/trait_objects_fail.rs:28:9
| |
LL | bar(&true); LL | bar(&true);
| --- ^^^^^ the trait `Traitor<{_: u8}, {_: u8}>` is not implemented for `bool` | --- ^^^^^ the trait `Traitor<{_: u8}>` is not implemented for `bool`
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= help: the trait `Traitor<2_u8, 3_u8>` is implemented for `bool` = help: the trait `Traitor<2_u8, 3_u8>` is implemented for `bool`
= note: required for the cast to the object type `dyn Traitor<{_: u8}, {_: u8}>` = note: required for the cast to the object type `dyn Traitor<{_: u8}>`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -1,12 +0,0 @@
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
--> $DIR/impl-trait-with-const-arguments.rs:18:20
|
LL | assert_eq!(f::<4usize>(Usizable), 20usize);
| ^^^^^^ explicit generic argument not allowed
|
= note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
= help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0632`.

View File

@ -1,3 +1,5 @@
// check-pass
trait Usizer { trait Usizer {
fn m(self) -> usize; fn m(self) -> usize;
} }
@ -16,5 +18,4 @@ fn m(self) -> usize {
fn main() { fn main() {
assert_eq!(f::<4usize>(Usizable), 20usize); assert_eq!(f::<4usize>(Usizable), 20usize);
//~^ ERROR cannot provide explicit generic arguments when `impl Trait` is used in argument position
} }

View File

@ -1,5 +1,3 @@
#![feature(explicit_generic_args_with_impl_trait)]
fn foo<T: ?Sized>(_f: impl AsRef<T>) {} fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
fn main() { fn main() {

View File

@ -1,5 +1,5 @@
error[E0107]: this function takes 1 generic argument but 2 generic arguments were supplied error[E0107]: this function takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/explicit-generic-args-for-impl.rs:6:5 --> $DIR/explicit-generic-args-for-impl.rs:4:5
| |
LL | foo::<str, String>("".to_string()); LL | foo::<str, String>("".to_string());
| ^^^ ------ help: remove this generic argument | ^^^ ------ help: remove this generic argument
@ -7,7 +7,7 @@ LL | foo::<str, String>("".to_string());
| expected 1 generic argument | expected 1 generic argument
| |
note: function defined here, with 1 generic parameter: `T` note: function defined here, with 1 generic parameter: `T`
--> $DIR/explicit-generic-args-for-impl.rs:3:4 --> $DIR/explicit-generic-args-for-impl.rs:1:4
| |
LL | fn foo<T: ?Sized>(_f: impl AsRef<T>) {} LL | fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
| ^^^ - | ^^^ -

View File

@ -1,7 +1,5 @@
// check-pass // check-pass
#![feature(explicit_generic_args_with_impl_trait)]
fn foo<T: ?Sized>(_f: impl AsRef<T>) {} fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
fn main() { fn main() {

View File

@ -1,7 +0,0 @@
// gate-test-explicit_generic_args_with_impl_trait
fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
fn main() {
foo::<str>("".to_string()); //~ ERROR E0632
}

View File

@ -1,12 +0,0 @@
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
--> $DIR/feature-gate.rs:6:11
|
LL | foo::<str>("".to_string());
| ^^^ explicit generic argument not allowed
|
= note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
= help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0632`.

View File

@ -1,7 +1,5 @@
// check-pass // check-pass
#![feature(explicit_generic_args_with_impl_trait)]
fn f<T: ?Sized>(_: impl AsRef<T>, _: impl AsRef<T>) {} fn f<T: ?Sized>(_: impl AsRef<T>, _: impl AsRef<T>) {}
fn main() { fn main() {

View File

@ -1,5 +1,3 @@
#![feature(explicit_generic_args_with_impl_trait)]
fn f<T: ?Sized, U: ?Sized>(_: impl AsRef<T>, _: impl AsRef<U>) {} fn f<T: ?Sized, U: ?Sized>(_: impl AsRef<T>, _: impl AsRef<U>) {}
fn main() { fn main() {

View File

@ -1,5 +1,5 @@
error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
--> $DIR/not-enough-args.rs:6:5 --> $DIR/not-enough-args.rs:4:5
| |
LL | f::<[u8]>("a", b"a"); LL | f::<[u8]>("a", b"a");
| ^ ---- supplied 1 generic argument | ^ ---- supplied 1 generic argument
@ -7,7 +7,7 @@ LL | f::<[u8]>("a", b"a");
| expected 2 generic arguments | expected 2 generic arguments
| |
note: function defined here, with 2 generic parameters: `T`, `U` note: function defined here, with 2 generic parameters: `T`, `U`
--> $DIR/not-enough-args.rs:3:4 --> $DIR/not-enough-args.rs:1:4
| |
LL | fn f<T: ?Sized, U: ?Sized>(_: impl AsRef<T>, _: impl AsRef<U>) {} LL | fn f<T: ?Sized, U: ?Sized>(_: impl AsRef<T>, _: impl AsRef<U>) {}
| ^ - - | ^ - -

View File

@ -1,7 +0,0 @@
use std::fmt::Debug;
fn foo<T>(x: impl Debug) { }
fn main() {
foo::<String>('a'); //~ ERROR cannot provide explicit generic arguments
}

View File

@ -1,12 +0,0 @@
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
--> $DIR/universal-issue-48703.rs:6:11
|
LL | foo::<String>('a');
| ^^^^^^ explicit generic argument not allowed
|
= note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
= help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0632`.

View File

@ -1,17 +0,0 @@
use std::any::Any;
pub struct EventHandler {
}
impl EventHandler
{
pub fn handle_event<T: Any>(&mut self, _efunc: impl FnMut(T)) {}
}
struct TestEvent(i32);
fn main() {
let mut evt = EventHandler {};
evt.handle_event::<TestEvent, fn(TestEvent)>(|_evt| {
//~^ ERROR cannot provide explicit generic arguments
});
}

View File

@ -1,14 +0,0 @@
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
--> $DIR/universal-turbofish-in-method-issue-50950.rs:14:24
|
LL | evt.handle_event::<TestEvent, fn(TestEvent)>(|_evt| {
| ^^^^^^^^^ ^^^^^^^^^^^^^ explicit generic argument not allowed
| |
| explicit generic argument not allowed
|
= note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
= help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0632`.

View File

@ -5,6 +5,6 @@
} }
fn main() { fn main() {
let _ = foo("foo"); //<- Do not suggest `foo::<N>("foo");`! let _ = foo("foo");
//~^ ERROR: type annotations needed for `[usize; _]` //~^ ERROR: type annotations needed for `[usize; _]`
} }

View File

@ -1,12 +1,12 @@
error[E0282]: type annotations needed for `[usize; _]` error[E0282]: type annotations needed for `[usize; _]`
--> $DIR/issue-83606.rs:8:9 --> $DIR/issue-83606.rs:8:9
| |
LL | let _ = foo("foo"); //<- Do not suggest `foo::<N>("foo");`! LL | let _ = foo("foo");
| ^ | ^
| |
help: consider giving this pattern a type, where the the value of const parameter `N` is specified help: consider giving this pattern a type, where the the value of const parameter `N` is specified
| |
LL | let _: [usize; _] = foo("foo"); //<- Do not suggest `foo::<N>("foo");`! LL | let _: [usize; _] = foo("foo");
| ++++++++++++ | ++++++++++++
error: aborting due to previous error error: aborting due to previous error

View File

@ -0,0 +1,16 @@
trait Ambiguous<A> {
fn method() {}
}
struct One;
struct Two;
struct Struct;
impl Ambiguous<One> for Struct {}
impl Ambiguous<Two> for Struct {}
fn main() {
<Struct as Ambiguous<_>>::method();
//~^ ERROR type annotations needed
//~| ERROR type annotations needed
}

View File

@ -0,0 +1,33 @@
error[E0282]: type annotations needed
--> $DIR/concrete-impl.rs:13:5
|
LL | <Struct as Ambiguous<_>>::method();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
|
help: consider specifying the generic argument
|
LL | <Struct as Ambiguous::<_>>::method();
| ~~~~~
error[E0283]: type annotations needed
--> $DIR/concrete-impl.rs:13:5
|
LL | <Struct as Ambiguous<_>>::method();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
|
note: multiple `impl`s satisfying `Struct: Ambiguous<_>` found
--> $DIR/concrete-impl.rs:9:1
|
LL | impl Ambiguous<One> for Struct {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl Ambiguous<Two> for Struct {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider specifying the generic argument
|
LL | <Struct as Ambiguous::<_>>::method();
| ~~~~~
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0282, E0283.
For more information about an error, try `rustc --explain E0282`.

View File

@ -0,0 +1,13 @@
// Test that we don't ICE when encountering a `Self` in a path.
struct TestErr<T>(T);
impl<T> TestErr<T> {
fn func_a<U>() {}
fn func_b() {
Self::func_a();
//~^ ERROR type annotations needed
}
}
fn main() {}

View File

@ -0,0 +1,14 @@
error[E0282]: type annotations needed
--> $DIR/self-ty-in-path.rs:8:9
|
LL | Self::func_a();
| ^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the associated function `func_a`
|
help: consider specifying the generic argument
|
LL | Self::func_a::<U>();
| +++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.

View File

@ -0,0 +1,18 @@
// An addition to the `type-alias.rs` test,
// see the FIXME in that file for why this test
// exists.
//
// If there is none, feel free to remove this test
// again.
struct Ty<T>(T);
impl<T> Ty<T> {
fn new() {}
}
type IndirectAlias<T> = Ty<Box<T>>;
fn indirect_alias() {
IndirectAlias::new();
//~^ ERROR type annotations needed
}
fn main() {}

View File

@ -0,0 +1,9 @@
error[E0282]: type annotations needed
--> $DIR/type-alias-indirect.rs:14:5
|
LL | IndirectAlias::new();
| ^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.

View File

@ -0,0 +1,36 @@
// Test the inference errors in case the relevant path
// uses a type alias.
//
// Regression test for #97698.
struct Ty<T>(T);
impl<T> Ty<T> {
fn new() {}
}
type DirectAlias<T> = Ty<T>;
fn direct_alias() {
DirectAlias::new()
//~^ ERROR type annotations needed
}
type IndirectAlias<T> = Ty<Box<T>>;
fn indirect_alias() {
IndirectAlias::new();
// FIXME: This should also emit an error.
//
// Added it separately as `type-alias-indirect.rs`
// where it does error.
}
struct TyDefault<T, U = u32>(T, U);
impl<T> TyDefault<T> {
fn new() {}
}
type DirectButWithDefaultAlias<T> = TyDefault<T>;
fn direct_but_with_default_alias() {
DirectButWithDefaultAlias::new();
//~^ ERROR type annotations needed
}
fn main() {}

View File

@ -0,0 +1,15 @@
error[E0282]: type annotations needed
--> $DIR/type-alias.rs:12:5
|
LL | DirectAlias::new()
| ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
error[E0282]: type annotations needed
--> $DIR/type-alias.rs:32:5
|
LL | DirectButWithDefaultAlias::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0282`.

View File

@ -0,0 +1,22 @@
// edition:2021
pub trait Trait<'a, T> {}
pub struct Struct<T>;
pub enum Enum<T> {}
pub union Union<T> {
f1: usize,
}
impl<'a, T> Struct<T> for Trait<'a, T> {}
//~^ ERROR expected trait, found struct `Struct`
//~| ERROR trait objects must include the `dyn` keyword
impl<'a, T> Enum<T> for Trait<'a, T> {}
//~^ ERROR expected trait, found enum `Enum`
impl<'a, T> Union<T> for Trait<'a, T> {}
//~^ ERROR expected trait, found union `Union`
fn main() {}

View File

@ -0,0 +1,49 @@
error[E0404]: expected trait, found struct `Struct`
--> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:12:13
|
LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
| ^^^^^^^^^ not a trait
|
help: `impl` items mention the trait being implemented first and the type it is being implemented for second
|
LL | impl<'a, T> Trait<'a, T> for Struct<T> {}
| ~~~~~~~~~~~~ ~~~~~~~~~
error[E0404]: expected trait, found enum `Enum`
--> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:16:13
|
LL | impl<'a, T> Enum<T> for Trait<'a, T> {}
| ^^^^^^^ not a trait
|
help: `impl` items mention the trait being implemented first and the type it is being implemented for second
|
LL | impl<'a, T> Trait<'a, T> for Enum<T> {}
| ~~~~~~~~~~~~ ~~~~~~~
error[E0404]: expected trait, found union `Union`
--> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:13
|
LL | impl<'a, T> Union<T> for Trait<'a, T> {}
| ^^^^^^^^ not a trait
|
help: `impl` items mention the trait being implemented first and the type it is being implemented for second
|
LL | impl<'a, T> Trait<'a, T> for Union<T> {}
| ~~~~~~~~~~~~ ~~~~~~~~
error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:12:27
|
LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
| ^^^^^^^^^^^^
|
help: add `dyn` keyword before this trait
|
LL - impl<'a, T> Struct<T> for Trait<'a, T> {}
LL + impl<'a, T> Struct<T> for dyn Trait<'a, T> {}
|
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0404, E0782.
For more information about an error, try `rustc --explain E0404`.

View File

@ -0,0 +1,21 @@
pub trait Trait<'a, T> {}
pub struct Struct<T>;
pub enum Enum<T> {}
pub union Union<T> {
f1: usize,
}
impl<'a, T> Struct<T> for Trait<'a, T> {}
//~^ ERROR expected trait, found struct `Struct`
//~| WARNING trait objects without an explicit `dyn` are deprecated
//~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
impl<'a, T> Enum<T> for Trait<'a, T> {}
//~^ ERROR expected trait, found enum `Enum`
impl<'a, T> Union<T> for Trait<'a, T> {}
//~^ ERROR expected trait, found union `Union`
fn main() {}

View File

@ -0,0 +1,51 @@
error[E0404]: expected trait, found struct `Struct`
--> $DIR/suggest-swapping-self-ty-and-trait.rs:10:13
|
LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
| ^^^^^^^^^ not a trait
|
help: `impl` items mention the trait being implemented first and the type it is being implemented for second
|
LL | impl<'a, T> Trait<'a, T> for Struct<T> {}
| ~~~~~~~~~~~~ ~~~~~~~~~
error[E0404]: expected trait, found enum `Enum`
--> $DIR/suggest-swapping-self-ty-and-trait.rs:15:13
|
LL | impl<'a, T> Enum<T> for Trait<'a, T> {}
| ^^^^^^^ not a trait
|
help: `impl` items mention the trait being implemented first and the type it is being implemented for second
|
LL | impl<'a, T> Trait<'a, T> for Enum<T> {}
| ~~~~~~~~~~~~ ~~~~~~~
error[E0404]: expected trait, found union `Union`
--> $DIR/suggest-swapping-self-ty-and-trait.rs:18:13
|
LL | impl<'a, T> Union<T> for Trait<'a, T> {}
| ^^^^^^^^ not a trait
|
help: `impl` items mention the trait being implemented first and the type it is being implemented for second
|
LL | impl<'a, T> Trait<'a, T> for Union<T> {}
| ~~~~~~~~~~~~ ~~~~~~~~
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/suggest-swapping-self-ty-and-trait.rs:10:27
|
LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
| ^^^^^^^^^^^^
|
= note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
help: use `dyn`
|
LL - impl<'a, T> Struct<T> for Trait<'a, T> {}
LL + impl<'a, T> Struct<T> for dyn Trait<'a, T> {}
|
error: aborting due to 3 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0404`.