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:
commit
7092d42c04
@ -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());
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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>,
|
||||||
|
@ -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);
|
||||||
|
@ -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(|¶m| {
|
|
||||||
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,
|
||||||
|
@ -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 }
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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() {
|
||||||
|
@ -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.
|
||||||
|
@ -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],
|
||||||
|
@ -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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 });
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
```
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>>
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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`.
|
|
@ -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
|
|
||||||
}
|
}
|
@ -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() {
|
||||||
|
@ -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>) {}
|
||||||
| ^^^ -
|
| ^^^ -
|
||||||
|
@ -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() {
|
||||||
|
@ -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
|
|
||||||
}
|
|
@ -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`.
|
|
@ -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() {
|
||||||
|
@ -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() {
|
||||||
|
@ -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>) {}
|
||||||
| ^ - -
|
| ^ - -
|
||||||
|
@ -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
|
|
||||||
}
|
|
@ -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`.
|
|
@ -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
|
|
||||||
});
|
|
||||||
}
|
|
@ -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`.
|
|
@ -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; _]`
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
16
src/test/ui/inference/need_type_info/concrete-impl.rs
Normal file
16
src/test/ui/inference/need_type_info/concrete-impl.rs
Normal 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
|
||||||
|
}
|
33
src/test/ui/inference/need_type_info/concrete-impl.stderr
Normal file
33
src/test/ui/inference/need_type_info/concrete-impl.stderr
Normal 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`.
|
13
src/test/ui/inference/need_type_info/self-ty-in-path.rs
Normal file
13
src/test/ui/inference/need_type_info/self-ty-in-path.rs
Normal 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() {}
|
14
src/test/ui/inference/need_type_info/self-ty-in-path.stderr
Normal file
14
src/test/ui/inference/need_type_info/self-ty-in-path.stderr
Normal 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`.
|
18
src/test/ui/inference/need_type_info/type-alias-indirect.rs
Normal file
18
src/test/ui/inference/need_type_info/type-alias-indirect.rs
Normal 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() {}
|
@ -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`.
|
36
src/test/ui/inference/need_type_info/type-alias.rs
Normal file
36
src/test/ui/inference/need_type_info/type-alias.rs
Normal 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() {}
|
15
src/test/ui/inference/need_type_info/type-alias.stderr
Normal file
15
src/test/ui/inference/need_type_info/type-alias.stderr
Normal 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`.
|
@ -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() {}
|
@ -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`.
|
@ -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() {}
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user