diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 46001b8b6d15d..701abc117a083 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -17,10 +17,13 @@ use rustc_hir::{Expr, ExprKind, FnRetTy, HirId, Node, QPath, is_range_literal}; use rustc_hir_analysis::check::potentially_plural_count; use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, ResolvedStructPath}; use rustc_index::IndexVec; -use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TypeTrace}; +use rustc_infer::infer::{ + BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TypeTrace, relate, +}; use rustc_middle::ty::adjustment::AllowTwoPhase; -use rustc_middle::ty::error::TypeError; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_forced_trimmed_paths; +use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Unnormalized}; use rustc_middle::{bug, span_bug}; use rustc_session::Session; @@ -250,41 +253,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // function where-bounds don't actually hold. This results // in weird bugs when later treating these expectations as if // they were actually correct. - self.fudge_inference_if_ok(|| { - let ocx = ObligationCtxt::new(self); - - // Attempt to apply a subtyping relationship between the formal - // return type (likely containing type variables if the function - // is polymorphic) and the expected return type. - // No argument expectations are produced if unification fails. - let origin = self.misc(call_span); - ocx.sup(&origin, self.param_env, expected_output, formal_output)?; - - // Check the well-formedness of expected input tys, as using ill-formed - // expectation may cause type inference errors, see #150316. - for &ty in formal_input_tys { - ocx.register_obligation(traits::Obligation::new( - self.tcx, - self.misc(call_span), - self.param_env, - ty::ClauseKind::WellFormed(ty.into()), - )); - } + let expected_input_tys = self + .fudge_inference_if_ok(|| { + let ocx = ObligationCtxt::new(self); + + // Attempt to apply a subtyping relationship between the formal + // return type (likely containing type variables if the function + // is polymorphic) and the expected return type. + // No argument expectations are produced if unification fails. + let origin = self.misc(call_span); + ocx.sup(&origin, self.param_env, expected_output, formal_output)?; + + // Check the well-formedness of expected input tys, as using ill-formed + // expectation may cause type inference errors, see #150316. + for &ty in formal_input_tys { + ocx.register_obligation(traits::Obligation::new( + self.tcx, + self.misc(call_span), + self.param_env, + ty::ClauseKind::WellFormed(ty.into()), + )); + } - if !ocx.try_evaluate_obligations().no_errors() { - return Err(TypeError::Mismatch); - } + if !ocx.try_evaluate_obligations().no_errors() { + return Err(TypeError::Mismatch); + } - // Record all the argument types, with the args - // produced from the above subtyping unification. - Ok(Some( - formal_input_tys - .iter() - .map(|&ty| self.resolve_vars_if_possible(ty)) - .collect(), - )) - }) - .ok() + // Record all the argument types, with the args + // produced from the above subtyping unification. + Ok(Some( + formal_input_tys + .iter() + .map(|&ty| self.resolve_vars_if_possible(ty)) + .collect::>(), + )) + }) + .ok()?; + + Some(expected_input_tys.map(|expected_input_tys| { + expected_input_tys + .into_iter() + .zip(formal_input_tys) + // if the expected input type is structurally equal to the formal input type, + // i.e. we've only changed some inference variables around, keep the formal + // input ty as the expected input ty. Usually fudging helps because it gains + // information from a callsite of a function. However, Fudging also sometimes + // loses information, when the original, formal, input type had constraints on it, + // and fudging replaces all inference variables with fresh ones, those constraints + // are discarded. This check makes sure we only keep fudging output if structural + // changes were made to the type. If all that was changed were some typevars, + // we go back to the unfudged formal input type. + .map(|(expected_input_ty, formal_input_ty)| { + if same_type_modulo_vars(tcx, expected_input_ty, *formal_input_ty) { + // if they're the same, fall back to the formal input type + *formal_input_ty + } else { + expected_input_ty + } + }) + .collect() + })) }) .unwrap_or_default(); @@ -3535,3 +3563,100 @@ enum SuggestionText { Reorder, DidYouMean, } + +fn same_type_modulo_vars<'tcx>(tcx: TyCtxt<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { + struct SameModuloVars<'tcx> { + tcx: TyCtxt<'tcx>, + } + impl<'tcx> TypeRelation> for SameModuloVars<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn relate_ty_args( + &mut self, + a_ty: Ty<'tcx>, + _b_ty: Ty<'tcx>, + _ty_def_id: DefId, + a_args: ty::GenericArgsRef<'tcx>, + b_args: ty::GenericArgsRef<'tcx>, + _mk: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>, + ) -> RelateResult<'tcx, Ty<'tcx>> { + relate::relate_args_invariantly(self, a_args, b_args)?; + Ok(a_ty) + } + + fn relate_with_variance>>( + &mut self, + _variance: ty::Variance, + _info: ty::VarianceDiagInfo>, + a: T, + b: T, + ) -> RelateResult<'tcx, T> { + self.relate(a, b) + } + + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + if a == b { + return Ok(a); + } + + match (a.kind(), b.kind()) { + (&ty::Infer(ty::InferTy::TyVar(_)), &ty::Infer(ty::InferTy::TyVar(_))) + | (&ty::Infer(ty::InferTy::FloatVar(_)), &ty::Infer(ty::InferTy::FloatVar(_))) + | (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Infer(ty::InferTy::IntVar(_))) => Ok(a), + (&ty::Infer(_), _) | (_, &ty::Infer(_)) => Err(TypeError::Mismatch), + (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.cx(), guar)), + _ => relate::structurally_relate_tys(self, a, b), + } + } + + fn regions( + &mut self, + a: ty::Region<'tcx>, + _b: ty::Region<'tcx>, + ) -> RelateResult<'tcx, ty::Region<'tcx>> { + Ok(a) + } + + fn consts( + &mut self, + mut a: ty::Const<'tcx>, + mut b: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ty::Const<'tcx>> { + if a == b { + return Ok(a); + } + + // Avoid ICEs when in gce, and `structurally_relate_consts` + // turns a non-infer const into an infer const + if self.tcx.features().generic_const_exprs() { + a = self.tcx.expand_abstract_consts(a); + b = self.tcx.expand_abstract_consts(b); + } + + match (a.kind(), b.kind()) { + (ty::ConstKind::Infer(_), ty::ConstKind::Infer(_)) => return Ok(a), + (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => { + return Err(TypeError::ConstMismatch(ExpectedFound::new(a, b))); + } + _ => {} + } + + relate::structurally_relate_consts(self, a, b) + } + + fn binders( + &mut self, + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> + where + T: Relate>, + { + Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?)) + } + } + + SameModuloVars { tcx }.relate(a, b).is_ok() +} diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 9c1907bbe8401..dfa15f4c14768 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1247,22 +1247,45 @@ impl<'tcx> InferCtxt<'tcx> { // // Note: if these two lines are combined into one we get // dynamic borrow errors on `self.inner`. - let known = self.inner.borrow_mut().type_variables().probe(v).known(); - known.map_or(ty, |t| self.shallow_resolve(t)) + let (root_vid, value) = + self.inner.borrow_mut().type_variables().probe_with_root_vid(v); + value.known().map_or_else( + || if root_vid == v { ty } else { Ty::new_var(self.tcx, root_vid) }, + |t| self.shallow_resolve(t), + ) } ty::IntVar(v) => { - match self.inner.borrow_mut().int_unification_table().probe_value(v) { + let (root, value) = + self.inner.borrow_mut().int_unification_table().inlined_probe_key_value(v); + match value { ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty), ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty), - ty::IntVarValue::Unknown => ty, + ty::IntVarValue::Unknown => { + if root == v { + ty + } else { + Ty::new_int_var(self.tcx, root) + } + } } } ty::FloatVar(v) => { - match self.inner.borrow_mut().float_unification_table().probe_value(v) { + let (root, value) = self + .inner + .borrow_mut() + .float_unification_table() + .inlined_probe_key_value(v); + match value { ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty), - ty::FloatVarValue::Unknown => ty, + ty::FloatVarValue::Unknown => { + if root == v { + ty + } else { + Ty::new_float_var(self.tcx, root) + } + } } } @@ -1276,13 +1299,16 @@ impl<'tcx> InferCtxt<'tcx> { pub fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { ty::ConstKind::Infer(infer_ct) => match infer_ct { - InferConst::Var(vid) => self - .inner - .borrow_mut() - .const_unification_table() - .probe_value(vid) - .known() - .unwrap_or(ct), + InferConst::Var(vid) => { + let (root, value) = self + .inner + .borrow_mut() + .const_unification_table() + .inlined_probe_key_value(vid); + value.known().unwrap_or_else(|| { + if root.vid == vid { ct } else { ty::Const::new_var(self.tcx, root.vid) } + }) + } InferConst::Fresh(_) => ct, }, @@ -1307,6 +1333,13 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow_mut().type_variables().root_var(var) } + /// If `ty` is an unresolved type variable, returns its root vid. + pub fn root_vid(&self, ty: Ty<'tcx>) -> Option { + let (root, value) = + self.inner.borrow_mut().type_variables().inlined_probe_with_vid(ty.ty_vid()?); + value.is_unknown().then_some(root) + } + pub fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) { self.inner.borrow_mut().type_variables().sub_unify(a, b); } diff --git a/tests/incremental/const-generics/issue-64087.rs b/tests/incremental/const-generics/issue-64087.rs index c316f787cc932..1377d05706f2e 100644 --- a/tests/incremental/const-generics/issue-64087.rs +++ b/tests/incremental/const-generics/issue-64087.rs @@ -6,6 +6,4 @@ fn combinator() -> [T; S] {} fn main() { combinator().into_iter(); //[bfail1]~^ ERROR type annotations needed - //[bfail1]~| ERROR type annotations needed - //[bfail1]~| ERROR type annotations needed } diff --git a/tests/ui/associated-inherent-types/inference-fail.stderr b/tests/ui/associated-inherent-types/inference-fail.stderr index bf329c69e99c1..12cc3ae7960c6 100644 --- a/tests/ui/associated-inherent-types/inference-fail.stderr +++ b/tests/ui/associated-inherent-types/inference-fail.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/inference-fail.rs:10:12 | LL | let _: S<_>::P = (); - | ^^^^^^^ cannot infer type for type parameter `T` + | ^^^^^^^ cannot infer type error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/index-mut-help2.stderr b/tests/ui/borrowck/index-mut-help2.stderr index 44dd966cfd6a5..0992b520e8687 100644 --- a/tests/ui/borrowck/index-mut-help2.stderr +++ b/tests/ui/borrowck/index-mut-help2.stderr @@ -25,10 +25,10 @@ LL | map.insert(*****index, 23); | ++++ error[E0277]: the trait bound `&B: Borrow<&&&&B>` is not satisfied - --> $DIR/index-mut-help2.rs:95:9 + --> $DIR/index-mut-help2.rs:95:5 | LL | map[index] = 23; - | ^^^^^ the trait `Borrow<&&&&B>` is not implemented for `&B` + | ^^^^^^^^^^ the trait `Borrow<&&&&B>` is not implemented for `&B` | = note: required for `HashMap<&B, u32>` to implement `Index<&&&&&B>` @@ -44,10 +44,10 @@ note: required by a bound in `HashMap::::get_mut` --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL error[E0277]: the trait bound `D: Borrow<&&&&D>` is not satisfied - --> $DIR/index-mut-help2.rs:131:9 + --> $DIR/index-mut-help2.rs:131:5 | LL | map[index] = 23; - | ^^^^^ unsatisfied trait bound + | ^^^^^^^^^^ unsatisfied trait bound | help: the trait `Borrow<&&&&D>` is not implemented for `D` but trait `Borrow` is implemented for it diff --git a/tests/ui/closures/unsized-return-suggest-ref-issue-152064.fixed b/tests/ui/closures/unsized-return-suggest-ref-issue-152064.fixed index 343ec57d41e46..2e1d10fb2804c 100644 --- a/tests/ui/closures/unsized-return-suggest-ref-issue-152064.fixed +++ b/tests/ui/closures/unsized-return-suggest-ref-issue-152064.fixed @@ -7,7 +7,6 @@ fn main() { for s in o.map(|s| &s[3..8]) {} //~^ ERROR the size for values of type `str` cannot be known at compilation time //~| ERROR the size for values of type `str` cannot be known at compilation time - //~| ERROR the size for values of type `str` cannot be known at compilation time //~| ERROR `Option` is not an iterator // Byte slice case @@ -15,6 +14,5 @@ fn main() { for s in arr.map(|s| &s[3..8]) {} //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time //~| ERROR the size for values of type `[u8]` cannot be known at compilation time - //~| ERROR the size for values of type `[u8]` cannot be known at compilation time //~| ERROR `Option<[u8]>` is not an iterator } diff --git a/tests/ui/closures/unsized-return-suggest-ref-issue-152064.rs b/tests/ui/closures/unsized-return-suggest-ref-issue-152064.rs index 7eb4640169548..6a0573248ff8b 100644 --- a/tests/ui/closures/unsized-return-suggest-ref-issue-152064.rs +++ b/tests/ui/closures/unsized-return-suggest-ref-issue-152064.rs @@ -7,7 +7,6 @@ fn main() { for s in o.map(|s| s[3..8]) {} //~^ ERROR the size for values of type `str` cannot be known at compilation time //~| ERROR the size for values of type `str` cannot be known at compilation time - //~| ERROR the size for values of type `str` cannot be known at compilation time //~| ERROR `Option` is not an iterator // Byte slice case @@ -15,6 +14,5 @@ fn main() { for s in arr.map(|s| s[3..8]) {} //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time //~| ERROR the size for values of type `[u8]` cannot be known at compilation time - //~| ERROR the size for values of type `[u8]` cannot be known at compilation time //~| ERROR `Option<[u8]>` is not an iterator } diff --git a/tests/ui/closures/unsized-return-suggest-ref-issue-152064.stderr b/tests/ui/closures/unsized-return-suggest-ref-issue-152064.stderr index 33018fb8a82d4..c5e5e71cd8823 100644 --- a/tests/ui/closures/unsized-return-suggest-ref-issue-152064.stderr +++ b/tests/ui/closures/unsized-return-suggest-ref-issue-152064.stderr @@ -8,15 +8,6 @@ LL | for s in o.map(|s| s[3..8]) {} note: required by an implicit `Sized` bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL -error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/unsized-return-suggest-ref-issue-152064.rs:7:24 - | -LL | for s in o.map(|s| s[3..8]) {} - | ^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `str` - = note: the return type of a function must have a statically known size - error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/unsized-return-suggest-ref-issue-152064.rs:7:14 | @@ -50,7 +41,7 @@ help: the following other types implement trait `IntoIterator` = note: `&mut Option` error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/unsized-return-suggest-ref-issue-152064.rs:15:18 + --> $DIR/unsized-return-suggest-ref-issue-152064.rs:14:18 | LL | for s in arr.map(|s| s[3..8]) {} | ^^^ doesn't have a size known at compile-time @@ -60,16 +51,7 @@ note: required by an implicit `Sized` bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/unsized-return-suggest-ref-issue-152064.rs:15:26 - | -LL | for s in arr.map(|s| s[3..8]) {} - | ^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `[u8]` - = note: the return type of a function must have a statically known size - -error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/unsized-return-suggest-ref-issue-152064.rs:15:14 + --> $DIR/unsized-return-suggest-ref-issue-152064.rs:14:14 | LL | for s in arr.map(|s| s[3..8]) {} | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -83,7 +65,7 @@ LL | for s in arr.map(|s| &s[3..8]) {} | + error[E0277]: `Option<[u8]>` is not an iterator - --> $DIR/unsized-return-suggest-ref-issue-152064.rs:15:14 + --> $DIR/unsized-return-suggest-ref-issue-152064.rs:14:14 | LL | for s in arr.map(|s| s[3..8]) {} | ^^^^^^^^^^^^^^^^^^^^ `Option<[u8]>` is not an iterator @@ -100,6 +82,6 @@ help: the following other types implement trait `IntoIterator` | = note: `&mut Option` -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-1.rs b/tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-1.rs new file mode 100644 index 0000000000000..eb0333491b0d3 --- /dev/null +++ b/tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-1.rs @@ -0,0 +1,12 @@ +//@ build-pass +//@ compile-flags: --crate-type lib +pub trait Trait { + type Assoc; + fn create_from(_: F) -> Self::Assoc; +} + +fn map(_: T::Assoc) {} + +pub fn traverse() { + map::(T::create_from(|| ())); +} diff --git a/tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-2.rs b/tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-2.rs new file mode 100644 index 0000000000000..d26f2238b4896 --- /dev/null +++ b/tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-2.rs @@ -0,0 +1,19 @@ +//@ build-pass +#[expect(dead_code)] + +// Must be invariant +pub struct Server(*mut T); +impl Server { + fn new(_: T) -> Self + where + // Must be higher-ranked + T: Fn(&mut i32), + { + todo!() + } +} + +fn main() { + // Must have a type annotation + let _: Server<_> = Server::new(|_| ()); +} diff --git a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.rs b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.rs index c50bbcec52157..b754b1cb54728 100644 --- a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.rs +++ b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.rs @@ -3,7 +3,7 @@ use std::cmp::Ordering; use std::marker::PhantomData; #[derive(PartialEq, Default)] -//~^ ERROR conflicting implementations of trait `PartialEq>` for type `Interval<_>` +//~^ ERROR conflicting implementations of trait `PartialEq` for type `Interval<_>` pub(crate) struct Interval(PhantomData); // This impl overlaps with the `derive` unless we reject the nested diff --git a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr index a9a99fb28d844..620694aacf83b 100644 --- a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr +++ b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `PartialEq>` for type `Interval<_>` +error[E0119]: conflicting implementations of trait `PartialEq` for type `Interval<_>` --> $DIR/warn-when-cycle-is-error-in-coherence.rs:5:10 | LL | #[derive(PartialEq, Default)] diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.rs index 298cfb512e418..79e9834b54ed2 100644 --- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.rs +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.rs @@ -18,5 +18,4 @@ fn use_dyn(v: &dyn Foo) where [u8; N + 1]: Sized { fn main() { use_dyn(&()); //~^ ERROR type annotations needed - //~| ERROR type annotations needed } diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr index d66623e792635..51a9c6f1d177c 100644 --- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr @@ -14,27 +14,6 @@ help: consider specifying a const for the const parameter `N` LL | use_dyn::(&()); | +++++++++++++++ -error[E0284]: type annotations needed - --> $DIR/dyn-compatibility-ok-infer-err.rs:19:5 - | -LL | use_dyn(&()); - | ^^^^^^^ --- type must be known at this point - | | - | cannot infer the value of the const parameter `N` declared on the function `use_dyn` - | -note: required for `()` to implement `Foo<_>` - --> $DIR/dyn-compatibility-ok-infer-err.rs:8:22 - | -LL | impl Foo for () { - | -------------- ^^^^^^ ^^ - | | - | unsatisfied trait bound introduced here - = note: required for the cast from `&()` to `&dyn Foo<_>` -help: consider specifying a const for the const parameter `N` - | -LL | use_dyn::(&()); - | +++++++++++++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/infer/issue-77092.rs b/tests/ui/const-generics/infer/issue-77092.rs index 47c594e5b11ea..77d1fe187795d 100644 --- a/tests/ui/const-generics/infer/issue-77092.rs +++ b/tests/ui/const-generics/infer/issue-77092.rs @@ -10,6 +10,5 @@ fn main() { for i in 1..4 { println!("{:?}", take_array_from_mut(&mut arr, i)); //~^ ERROR type annotations needed - //~| ERROR type annotations needed } } diff --git a/tests/ui/const-generics/infer/issue-77092.stderr b/tests/ui/const-generics/infer/issue-77092.stderr index 3763cd738a861..96f6496eca537 100644 --- a/tests/ui/const-generics/infer/issue-77092.stderr +++ b/tests/ui/const-generics/infer/issue-77092.stderr @@ -14,24 +14,6 @@ help: consider specifying the generic arguments LL | println!("{:?}", take_array_from_mut::(&mut arr, i)); | ++++++++++ -error[E0284]: type annotations needed - --> $DIR/issue-77092.rs:11:26 - | -LL | println!("{:?}", take_array_from_mut(&mut arr, i)); - | ---- ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `take_array_from_mut` - | | - | required by this formatting parameter - | - = note: required for `[i32; _]` to implement `Debug` - = note: 1 redundant requirement hidden - = note: required for `&mut [i32; _]` to implement `Debug` -note: required by a bound in `core::fmt::rt::Argument::<'_>::new_debug` - --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL -help: consider specifying the generic arguments - | -LL | println!("{:?}", take_array_from_mut::(&mut arr, i)); - | ++++++++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/try-from-with-const-genericsrs-98299.rs b/tests/ui/const-generics/try-from-with-const-genericsrs-98299.rs index 49c88856bc96a..808d960da68b7 100644 --- a/tests/ui/const-generics/try-from-with-const-genericsrs-98299.rs +++ b/tests/ui/const-generics/try-from-with-const-genericsrs-98299.rs @@ -4,8 +4,6 @@ use std::convert::TryFrom; pub fn test_usage(p: ()) { SmallCString::try_from(p).map(|cstr| cstr); //~^ ERROR: type annotations needed - //~| ERROR: type annotations needed - //~| ERROR: type annotations needed } pub struct SmallCString {} diff --git a/tests/ui/const-generics/try-from-with-const-genericsrs-98299.stderr b/tests/ui/const-generics/try-from-with-const-genericsrs-98299.stderr index 1557b83b00ec7..c80efd6df8a89 100644 --- a/tests/ui/const-generics/try-from-with-const-genericsrs-98299.stderr +++ b/tests/ui/const-generics/try-from-with-const-genericsrs-98299.stderr @@ -7,7 +7,7 @@ LL | SmallCString::try_from(p).map(|cstr| cstr); | type must be known at this point | note: required by a const generic parameter in `SmallCString` - --> $DIR/try-from-with-const-genericsrs-98299.rs:11:25 + --> $DIR/try-from-with-const-genericsrs-98299.rs:9:25 | LL | pub struct SmallCString {} | ^^^^^^^^^^^^^^ required by this const generic parameter in `SmallCString` @@ -16,46 +16,6 @@ help: consider giving this closure parameter an explicit type, where the value o LL | SmallCString::try_from(p).map(|cstr: SmallCString| cstr); | +++++++++++++++++ -error[E0284]: type annotations needed for `SmallCString<_>` - --> $DIR/try-from-with-const-genericsrs-98299.rs:5:36 - | -LL | SmallCString::try_from(p).map(|cstr| cstr); - | ------------ ^^^^ - | | - | type must be known at this point - | -note: required for `SmallCString<_>` to implement `TryFrom<()>` - --> $DIR/try-from-with-const-genericsrs-98299.rs:13:22 - | -LL | impl TryFrom<()> for SmallCString { - | -------------- ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ - | | - | unsatisfied trait bound introduced here -help: consider giving this closure parameter an explicit type, where the value of const parameter `N` is specified - | -LL | SmallCString::try_from(p).map(|cstr: SmallCString| cstr); - | +++++++++++++++++ - -error[E0284]: type annotations needed for `SmallCString<_>` - --> $DIR/try-from-with-const-genericsrs-98299.rs:5:36 - | -LL | SmallCString::try_from(p).map(|cstr| cstr); - | ------------------------- ^^^^ - | | - | type must be known at this point - | -note: required for `SmallCString<_>` to implement `TryFrom<()>` - --> $DIR/try-from-with-const-genericsrs-98299.rs:13:22 - | -LL | impl TryFrom<()> for SmallCString { - | -------------- ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ - | | - | unsatisfied trait bound introduced here -help: consider giving this closure parameter an explicit type, where the value of const parameter `N` is specified - | -LL | SmallCString::try_from(p).map(|cstr: SmallCString| cstr); - | +++++++++++++++++ - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/error-emitter/multiline-removal-suggestion.svg b/tests/ui/error-emitter/multiline-removal-suggestion.svg index de54859821b82..5c47481d4c178 100644 --- a/tests/ui/error-emitter/multiline-removal-suggestion.svg +++ b/tests/ui/error-emitter/multiline-removal-suggestion.svg @@ -1,4 +1,4 @@ - +