From e4c1a0016c0bd1b6579123c785e38e63b4ccf143 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 8 Nov 2024 03:46:23 +0000 Subject: [PATCH 1/6] Get rid of check_opaque_type_well_formed --- .../src/region_infer/opaque_types.rs | 90 +------------ .../rustc_hir_analysis/src/check/check.rs | 122 +++++++++++++++--- .../async-await/issue-70935-complex-spans.rs | 2 +- .../issue-70935-complex-spans.stderr | 16 ++- tests/ui/pattern/usefulness/impl-trait.stderr | 56 ++++---- .../closure_wf_outlives.rs | 6 +- .../closure_wf_outlives.stderr | 38 +++--- .../generic_duplicate_param_use3.rs | 3 +- .../generic_duplicate_param_use3.stderr | 29 ++--- .../generic_duplicate_param_use5.rs | 5 +- .../generic_duplicate_param_use5.stderr | 55 ++------ .../generic_duplicate_param_use6.rs | 4 +- .../generic_duplicate_param_use6.stderr | 43 ++---- .../generic_duplicate_param_use8.rs | 3 +- .../generic_duplicate_param_use8.stderr | 31 ++--- .../generic_duplicate_param_use9.rs | 6 +- .../generic_duplicate_param_use9.stderr | 64 ++------- .../implied_lifetime_wf_check4_static.rs | 2 +- .../implied_lifetime_wf_check4_static.stderr | 12 +- .../not_a_defining_use.rs | 4 +- .../not_a_defining_use.stderr | 42 ++---- .../underconstrained_lifetime.rs | 2 +- .../underconstrained_lifetime.stderr | 6 +- .../wf-in-associated-type.fail.stderr | 14 +- .../wf-in-associated-type.rs | 4 +- 25 files changed, 247 insertions(+), 412 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index f9dd649ab9f..d676ce59cfe 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -1,10 +1,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; -use rustc_hir::OpaqueTyOrigin; -use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _}; -use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_macros::extension; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ @@ -12,7 +9,6 @@ TypingMode, }; use rustc_span::Span; -use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::ObligationCtxt; use tracing::{debug, instrument}; @@ -303,91 +299,7 @@ fn infer_opaque_definition_from_instantiation( return Ty::new_error(self.tcx, e); } - // `definition_ty` does not live in of the current inference context, - // so lets make sure that we don't accidentally misuse our current `infcx`. - match check_opaque_type_well_formed( - self.tcx, - self.next_trait_solver(), - opaque_type_key.def_id, - instantiated_ty.span, - definition_ty, - ) { - Ok(hidden_ty) => hidden_ty, - Err(guar) => Ty::new_error(self.tcx, guar), - } - } -} - -/// This logic duplicates most of `check_opaque_meets_bounds`. -/// FIXME(oli-obk): Also do region checks here and then consider removing -/// `check_opaque_meets_bounds` entirely. -fn check_opaque_type_well_formed<'tcx>( - tcx: TyCtxt<'tcx>, - next_trait_solver: bool, - def_id: LocalDefId, - definition_span: Span, - definition_ty: Ty<'tcx>, -) -> Result, ErrorGuaranteed> { - // Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs` - // on stable and we'd break that. - let opaque_ty_hir = tcx.hir().expect_opaque_ty(def_id); - let OpaqueTyOrigin::TyAlias { .. } = opaque_ty_hir.origin else { - return Ok(definition_ty); - }; - let param_env = tcx.param_env(def_id); - - let mut parent_def_id = def_id; - while tcx.def_kind(parent_def_id) == DefKind::OpaqueTy { - parent_def_id = tcx.local_parent(parent_def_id); - } - - // FIXME(#132279): This should eventually use the already defined hidden types - // instead. Alternatively we'll entirely remove this function given we also check - // the opaque in `check_opaque_meets_bounds` later. - let infcx = tcx - .infer_ctxt() - .with_next_trait_solver(next_trait_solver) - .build(TypingMode::analysis_in_body(tcx, parent_def_id)); - let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - let identity_args = GenericArgs::identity_for_item(tcx, def_id); - - // Require that the hidden type actually fulfills all the bounds of the opaque type, even without - // the bounds that the function supplies. - let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_args); - ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty) - .map_err(|err| { - infcx - .err_ctxt() - .report_mismatched_types( - &ObligationCause::misc(definition_span, def_id), - param_env, - opaque_ty, - definition_ty, - err, - ) - .emit() - })?; - - // Require the hidden type to be well-formed with only the generics of the opaque type. - // Defining use functions may have more bounds than the opaque type, which is ok, as long as the - // hidden type is well formed even without those bounds. - let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( - definition_ty.into(), - ))); - ocx.register_obligation(Obligation::misc(tcx, definition_span, def_id, param_env, predicate)); - - // Check that all obligations are satisfied by the implementation's - // version. - let errors = ocx.select_all_or_error(); - - // This is fishy, but we check it again in `check_opaque_meets_bounds`. - // Remove once we can prepopulate with known hidden types. - let _ = infcx.take_opaque_types(); - - if errors.is_empty() { - Ok(definition_ty) - } else { - Err(infcx.err_ctxt().report_fulfillment_errors(errors)) + definition_ty } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 50ea8018e76..12b842e70b7 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -5,13 +5,14 @@ use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::MultiSpan; use rustc_errors::codes::*; -use rustc_hir::Node; use rustc_hir::def::{CtorKind, DefKind}; +use rustc_hir::{Node, intravisit}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::Obligation; use rustc_lint_defs::builtin::{ REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, }; +use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; use rustc_middle::span_bug; @@ -190,7 +191,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo` /// projections that would result in "inheriting lifetimes". fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let hir::OpaqueTy { origin, .. } = tcx.hir().expect_opaque_ty(def_id); + let hir::OpaqueTy { origin, .. } = *tcx.hir().expect_opaque_ty(def_id); // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting // `async-std` (and `pub async fn` in general). @@ -200,23 +201,20 @@ fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) { return; } - let span = tcx.def_span(def_id); - if tcx.type_of(def_id).instantiate_identity().references_error() { return; } - if check_opaque_for_cycles(tcx, def_id, span).is_err() { + if check_opaque_for_cycles(tcx, def_id).is_err() { return; } - let _ = check_opaque_meets_bounds(tcx, def_id, span, origin); + let _ = check_opaque_meets_bounds(tcx, def_id, origin); } /// Checks that an opaque type does not contain cycles. pub(super) fn check_opaque_for_cycles<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, - span: Span, ) -> Result<(), ErrorGuaranteed> { let args = GenericArgs::identity_for_item(tcx, def_id); @@ -233,7 +231,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>( .try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::No) .is_err() { - let reported = opaque_type_cycle_error(tcx, def_id, span); + let reported = opaque_type_cycle_error(tcx, def_id); return Err(reported); } @@ -267,10 +265,11 @@ pub(super) fn check_opaque_for_cycles<'tcx>( fn check_opaque_meets_bounds<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, - span: Span, - origin: &hir::OpaqueTyOrigin, + origin: hir::OpaqueTyOrigin, ) -> Result<(), ErrorGuaranteed> { - let defining_use_anchor = match *origin { + let span = span_of_opaque(tcx, def_id, origin).unwrap_or_else(|| tcx.def_span(def_id)); + + let defining_use_anchor = match origin { hir::OpaqueTyOrigin::FnReturn { parent, .. } | hir::OpaqueTyOrigin::AsyncFn { parent, .. } | hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent, @@ -281,7 +280,7 @@ fn check_opaque_meets_bounds<'tcx>( let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor)); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - let args = match *origin { + let args = match origin { hir::OpaqueTyOrigin::FnReturn { parent, .. } | hir::OpaqueTyOrigin::AsyncFn { parent, .. } | hir::OpaqueTyOrigin::TyAlias { parent, .. } => GenericArgs::identity_for_item( @@ -308,6 +307,7 @@ fn check_opaque_meets_bounds<'tcx>( let misc_cause = traits::ObligationCause::misc(span, def_id); + // FIXME: We should just register the item bounds here, rather than equating. match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) { Ok(()) => {} Err(ty_err) => { @@ -364,6 +364,97 @@ fn check_opaque_meets_bounds<'tcx>( } } +fn span_of_opaque<'tcx>( + tcx: TyCtxt<'tcx>, + opaque_def_id: LocalDefId, + origin: hir::OpaqueTyOrigin, +) -> Option { + struct TaitConstraintLocator<'tcx> { + opaque_def_id: LocalDefId, + tcx: TyCtxt<'tcx>, + } + impl<'tcx> TaitConstraintLocator<'tcx> { + fn check(&self, item_def_id: LocalDefId) -> ControlFlow { + if !self.tcx.has_typeck_results(item_def_id) { + return ControlFlow::Continue(()); + } + + if let Some(hidden_ty) = + self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id) + { + ControlFlow::Break(hidden_ty.span) + } else { + ControlFlow::Continue(()) + } + } + } + impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { + type NestedFilter = nested_filter::All; + type Result = ControlFlow; + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result { + if let hir::ExprKind::Closure(closure) = ex.kind { + self.check(closure.def_id)?; + } + intravisit::walk_expr(self, ex) + } + fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) -> Self::Result { + self.check(it.owner_id.def_id)?; + intravisit::walk_item(self, it) + } + fn visit_impl_item(&mut self, it: &'tcx hir::ImplItem<'tcx>) -> Self::Result { + self.check(it.owner_id.def_id)?; + intravisit::walk_impl_item(self, it) + } + fn visit_trait_item(&mut self, it: &'tcx hir::TraitItem<'tcx>) -> Self::Result { + self.check(it.owner_id.def_id)?; + intravisit::walk_trait_item(self, it) + } + fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) -> Self::Result { + intravisit::walk_foreign_item(self, it) + } + } + + let mut locator = TaitConstraintLocator { tcx, opaque_def_id }; + match origin { + hir::OpaqueTyOrigin::FnReturn { parent, .. } + | hir::OpaqueTyOrigin::AsyncFn { parent, .. } => locator.check(parent).break_value(), + hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty: true } => { + let impl_def_id = tcx.local_parent(parent); + for assoc in tcx.associated_items(impl_def_id).in_definition_order() { + match assoc.kind { + ty::AssocKind::Const | ty::AssocKind::Fn => { + if let ControlFlow::Break(span) = locator.check(assoc.def_id.expect_local()) + { + return Some(span); + } + } + ty::AssocKind::Type => {} + } + } + + None + } + hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => { + let scope = tcx.hir().get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id)); + let found = if scope == hir::CRATE_HIR_ID { + tcx.hir().walk_toplevel_module(&mut locator) + } else { + match tcx.hir_node(scope) { + Node::Item(it) => locator.visit_item(it), + Node::ImplItem(it) => locator.visit_impl_item(it), + Node::TraitItem(it) => locator.visit_trait_item(it), + Node::ForeignItem(it) => locator.visit_foreign_item(it), + other => bug!("{:?} is not a valid scope for an opaque type item", other), + } + }; + found.break_value() + } + } +} + fn sanity_check_found_hidden_type<'tcx>( tcx: TyCtxt<'tcx>, key: ty::OpaqueTypeKey<'tcx>, @@ -1535,11 +1626,8 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD /// /// If all the return expressions evaluate to `!`, then we explain that the error will go away /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder. -fn opaque_type_cycle_error( - tcx: TyCtxt<'_>, - opaque_def_id: LocalDefId, - span: Span, -) -> ErrorGuaranteed { +fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorGuaranteed { + let span = tcx.def_span(opaque_def_id); let mut err = struct_span_code_err!(tcx.dcx(), span, E0720, "cannot resolve opaque type"); let mut label = false; diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs index a74bd9890ca..2851637ae78 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.rs +++ b/tests/ui/async-await/issue-70935-complex-spans.rs @@ -14,8 +14,8 @@ async fn baz(_c: impl FnMut() -> T) where T: Future { fn foo(x: NotSync) -> impl Future + Send { //~^ ERROR `*mut ()` cannot be shared between threads safely - //~| ERROR `*mut ()` cannot be shared between threads safely async move { + //~^ ERROR `*mut ()` cannot be shared between threads safely baz(|| async { foo(x.clone()); }).await; diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index c6b7e21b9dd..777eefe897b 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -1,8 +1,13 @@ error[E0277]: `*mut ()` cannot be shared between threads safely - --> $DIR/issue-70935-complex-spans.rs:15:23 + --> $DIR/issue-70935-complex-spans.rs:17:5 | -LL | fn foo(x: NotSync) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely +LL | / async move { +LL | | +LL | | baz(|| async { +LL | | foo(x.clone()); +LL | | }).await; +LL | | } + | |_____^ `*mut ()` cannot be shared between threads safely | = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()` note: required because it appears within the type `PhantomData<*mut ()>` @@ -26,7 +31,7 @@ LL | async fn baz(_c: impl FnMut() -> T) where T: Future { LL | | } | |_^ note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:18:5 + --> $DIR/issue-70935-complex-spans.rs:17:5 | LL | async move { | ^^^^^^^^^^ @@ -59,11 +64,10 @@ LL | async fn baz(_c: impl FnMut() -> T) where T: Future { LL | | } | |_^ note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:18:5 + --> $DIR/issue-70935-complex-spans.rs:17:5 | LL | async move { | ^^^^^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/impl-trait.stderr b/tests/ui/pattern/usefulness/impl-trait.stderr index 75cba4b5f02..34f8eb1e163 100644 --- a/tests/ui/pattern/usefulness/impl-trait.stderr +++ b/tests/ui/pattern/usefulness/impl-trait.stderr @@ -25,6 +25,20 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types +error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty + --> $DIR/impl-trait.rs:23:11 + | +LL | match return_never_rpit(x) {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `impl Copy` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match return_never_rpit(x) { +LL + _ => todo!(), +LL + } + | + error: unreachable pattern --> $DIR/impl-trait.rs:45:13 | @@ -93,6 +107,20 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types +error[E0004]: non-exhaustive patterns: type `T` is non-empty + --> $DIR/impl-trait.rs:37:11 + | +LL | match return_never_tait(x) {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `T` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match return_never_tait(x) { +LL + _ => todo!(), +LL + } + | + error: unreachable pattern --> $DIR/impl-trait.rs:105:9 | @@ -131,34 +159,6 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types -error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty - --> $DIR/impl-trait.rs:23:11 - | -LL | match return_never_rpit(x) {} - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: the matched value is of type `impl Copy` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match return_never_rpit(x) { -LL + _ => todo!(), -LL + } - | - -error[E0004]: non-exhaustive patterns: type `T` is non-empty - --> $DIR/impl-trait.rs:37:11 - | -LL | match return_never_tait(x) {} - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: the matched value is of type `T` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match return_never_tait(x) { -LL + _ => todo!(), -LL + } - | - error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs b/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs index 430b444aae1..caa9b6d979a 100644 --- a/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs +++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs @@ -12,20 +12,19 @@ // requires `'a: 'b` bound mod test1 { type Opaque<'a, 'b> = impl Sized + 'a + 'b; - //~^ ERROR lifetime bound not satisfied fn define<'a, 'b>() -> Opaque<'a, 'b> where 'a: 'b, { || {} + //~^ ERROR lifetime bound not satisfied } } // Same as the above but through indirection `'x` mod test2 { type Opaque<'a, 'b> = impl Sized + 'a + 'b; - //~^ ERROR cannot infer an appropriate lifetime fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> where @@ -33,6 +32,7 @@ fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> 'x: 'b, { || {} + //~^ ERROR cannot infer an appropriate lifetime } } @@ -52,13 +52,13 @@ fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> // requires `T: 'static` mod test3 { type Opaque = impl Sized; - //~^ ERROR the parameter type `T` may not live long enough fn define() -> Opaque where T: 'static, { || {} + //~^ ERROR the parameter type `T` may not live long enough } } diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr index 3484485e3fd..04288112fa8 100644 --- a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr +++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr @@ -1,8 +1,8 @@ error[E0478]: lifetime bound not satisfied - --> $DIR/closure_wf_outlives.rs:14:27 + --> $DIR/closure_wf_outlives.rs:20:9 | -LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; - | ^^^^^^^^^^^^^^^^^^^^ +LL | || {} + | ^^^^^ | note: lifetime parameter instantiated with the lifetime `'a` as defined here --> $DIR/closure_wf_outlives.rs:14:17 @@ -16,10 +16,10 @@ LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; | ^^ error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/closure_wf_outlives.rs:27:27 + --> $DIR/closure_wf_outlives.rs:34:9 | -LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; - | ^^^^^^^^^^^^^^^^^^^^ +LL | || {} + | ^^^^^ | note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/closure_wf_outlives.rs:27:17 @@ -27,32 +27,32 @@ note: first, the lifetime cannot outlive the lifetime `'a` as defined here... LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; | ^^ note: ...so that the declared lifetime parameter bounds are satisfied - --> $DIR/closure_wf_outlives.rs:27:27 + --> $DIR/closure_wf_outlives.rs:34:9 | -LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; - | ^^^^^^^^^^^^^^^^^^^^ +LL | || {} + | ^^^^^ note: but, the lifetime must be valid for the lifetime `'b` as defined here... --> $DIR/closure_wf_outlives.rs:27:21 | LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; | ^^ note: ...so that the declared lifetime parameter bounds are satisfied - --> $DIR/closure_wf_outlives.rs:27:27 + --> $DIR/closure_wf_outlives.rs:34:9 | -LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; - | ^^^^^^^^^^^^^^^^^^^^ +LL | || {} + | ^^^^^ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/closure_wf_outlives.rs:54:22 + --> $DIR/closure_wf_outlives.rs:60:9 | -LL | type Opaque = impl Sized; - | ^^^^^^^^^^ - | | - | the parameter type `T` must be valid for the static lifetime... - | ...so that the type `T` will meet its required lifetime bounds... +LL | || {} + | ^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds... | note: ...that is required by this bound - --> $DIR/closure_wf_outlives.rs:59:12 + --> $DIR/closure_wf_outlives.rs:58:12 | LL | T: 'static, | ^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs index e7a25fc7240..2074f12750f 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs @@ -9,10 +9,9 @@ fn main() {} fn two(t: T, _: U) -> Two { t - //~^ ERROR `T` doesn't implement `Debug` } fn three(_: T, u: U) -> Two { u - //~^ ERROR `U` doesn't implement `Debug` + //~^ ERROR concrete type differs } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr index 7bec3822071..9a10a4980d8 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr @@ -1,25 +1,14 @@ -error[E0277]: `T` doesn't implement `Debug` +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_duplicate_param_use3.rs:15:5 + | +LL | u + | ^ expected `T`, got `U` + | +note: previous use here --> $DIR/generic_duplicate_param_use3.rs:11:5 | LL | t - | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ + | ^ -error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use3.rs:16:5 - | -LL | u - | ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | -help: consider restricting type parameter `U` - | -LL | type Two = impl Debug; - | +++++++++++++++++ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs index 3bd1dda6331..b3d6beaf848 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs @@ -9,12 +9,9 @@ fn main() {} fn two(t: T, u: U) -> Two { (t, u) - //~^ ERROR `T` doesn't implement `Debug` - //~| ERROR `U` doesn't implement `Debug` } fn three(t: T, u: U) -> Two { (u, t) - //~^ ERROR `T` doesn't implement `Debug` - //~| ERROR `U` doesn't implement `Debug` + //~^ ERROR concrete type differs } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr index 586ea82342a..b0027f8fa57 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr @@ -1,51 +1,14 @@ -error[E0277]: `T` doesn't implement `Debug` +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_duplicate_param_use5.rs:15:5 + | +LL | (u, t) + | ^^^^^^ expected `(T, U)`, got `(U, T)` + | +note: previous use here --> $DIR/generic_duplicate_param_use5.rs:11:5 | LL | (t, u) - | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(T, U)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ + | ^^^^^^ -error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use5.rs:11:5 - | -LL | (t, u) - | ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(T, U)` to implement `Debug` -help: consider restricting type parameter `U` - | -LL | type Two = impl Debug; - | +++++++++++++++++ +error: aborting due to 1 previous error -error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use5.rs:17:5 - | -LL | (u, t) - | ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(U, T)` to implement `Debug` -help: consider restricting type parameter `U` - | -LL | type Two = impl Debug; - | +++++++++++++++++ - -error[E0277]: `T` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use5.rs:17:5 - | -LL | (u, t) - | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(U, T)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs index 5120925e5a4..fa8b2a290b9 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs @@ -9,11 +9,9 @@ fn main() {} fn two(t: T, u: U) -> Two { (t, t) - //~^ ERROR `T` doesn't implement `Debug` } fn three(t: T, u: U) -> Two { (u, t) - //~^ ERROR `T` doesn't implement `Debug` - //~| ERROR `U` doesn't implement `Debug` + //~^ ERROR concrete type differs } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr index cb162d382b6..09c01932cef 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr @@ -1,39 +1,14 @@ -error[E0277]: `T` doesn't implement `Debug` +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_duplicate_param_use6.rs:15:5 + | +LL | (u, t) + | ^^^^^^ expected `(T, T)`, got `(U, T)` + | +note: previous use here --> $DIR/generic_duplicate_param_use6.rs:11:5 | LL | (t, t) - | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(T, T)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ + | ^^^^^^ -error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use6.rs:16:5 - | -LL | (u, t) - | ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(U, T)` to implement `Debug` -help: consider restricting type parameter `U` - | -LL | type Two = impl Debug; - | +++++++++++++++++ +error: aborting due to 1 previous error -error[E0277]: `T` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use6.rs:16:5 - | -LL | (u, t) - | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(U, T)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs index 3a4b5047b41..76c13bb027b 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs @@ -8,10 +8,9 @@ fn main() {} fn two(t: T, _: U) -> Two { (t, 4u32) - //~^ ERROR `T` doesn't implement `Debug` } fn three(_: T, u: U) -> Two { (u, 4u32) - //~^ ERROR `U` doesn't implement `Debug` + //~^ concrete type differs } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr index 14cbfb3806f..09d2abe3663 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr @@ -1,27 +1,14 @@ -error[E0277]: `T` doesn't implement `Debug` +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_duplicate_param_use8.rs:14:5 + | +LL | (u, 4u32) + | ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)` + | +note: previous use here --> $DIR/generic_duplicate_param_use8.rs:10:5 | LL | (t, 4u32) - | ^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(T, u32)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ + | ^^^^^^^^^ -error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use8.rs:15:5 - | -LL | (u, 4u32) - | ^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(U, u32)` to implement `Debug` -help: consider restricting type parameter `U` - | -LL | type Two = impl Debug; - | +++++++++++++++++ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs index 6afcdfe4d1c..5da7aab0da7 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs @@ -13,13 +13,9 @@ trait Foo { fn two(t: T, u: U) -> Two { (t, u, T::BAR) - //~^ ERROR the trait bound `A: Foo` is not satisfied - //~| ERROR `A` doesn't implement `Debug` - //~| ERROR `B` doesn't implement `Debug` } fn three(t: T, u: U) -> Two { (t, u, 42) - //~^ ERROR `A` doesn't implement `Debug` - //~| ERROR `B` doesn't implement `Debug` + //~^ ERROR concrete type differs } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr index 722693e4266..6e1bb3dfa17 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr @@ -1,62 +1,14 @@ -error[E0277]: the trait bound `A: Foo` is not satisfied - --> $DIR/generic_duplicate_param_use9.rs:15:5 - | -LL | (t, u, T::BAR) - | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` - | -help: consider restricting type parameter `A` - | -LL | type Two = impl Debug; - | +++++ - -error[E0277]: `A` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use9.rs:15:5 - | -LL | (t, u, T::BAR) - | ^^^^^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(A, B, _)` to implement `Debug` -help: consider restricting type parameter `A` - | -LL | type Two = impl Debug; - | +++++++++++++++++ - -error[E0277]: `B` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use9.rs:15:5 - | -LL | (t, u, T::BAR) - | ^^^^^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(A, B, _)` to implement `Debug` -help: consider restricting type parameter `B` - | -LL | type Two = impl Debug; - | +++++++++++++++++ - -error[E0277]: `A` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use9.rs:22:5 +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_duplicate_param_use9.rs:19:5 | LL | (t, u, 42) - | ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^ expected `(A, B, ::Bar)`, got `(A, B, i32)` | - = note: required for `(A, B, i32)` to implement `Debug` -help: consider restricting type parameter `A` +note: previous use here + --> $DIR/generic_duplicate_param_use9.rs:15:5 | -LL | type Two = impl Debug; - | +++++++++++++++++ +LL | (t, u, T::BAR) + | ^^^^^^^^^^^^^^ -error[E0277]: `B` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use9.rs:22:5 - | -LL | (t, u, 42) - | ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(A, B, i32)` to implement `Debug` -help: consider restricting type parameter `B` - | -LL | type Two = impl Debug; - | +++++++++++++++++ +error: aborting due to 1 previous error -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs index f8b09814caa..7b2bbc99530 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs @@ -2,9 +2,9 @@ mod test_type_param_static { pub type Ty = impl Sized + 'static; - //~^ ERROR: the parameter type `A` may not live long enough fn defining(s: A) -> Ty { s + //~^ ERROR: the parameter type `A` may not live long enough } pub fn assert_static() {} } diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr index f2e5e95b96f..e5919be0532 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -1,11 +1,11 @@ error[E0310]: the parameter type `A` may not live long enough - --> $DIR/implied_lifetime_wf_check4_static.rs:4:22 + --> $DIR/implied_lifetime_wf_check4_static.rs:6:9 | -LL | pub type Ty = impl Sized + 'static; - | ^^^^^^^^^^^^^^^^^^^^ - | | - | the parameter type `A` must be valid for the static lifetime... - | ...so that the type `A` will meet its required lifetime bounds +LL | s + | ^ + | | + | the parameter type `A` must be valid for the static lifetime... + | ...so that the type `A` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound | diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.rs b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs index fa47d13f516..b5ef1470629 100644 --- a/tests/ui/type-alias-impl-trait/not_a_defining_use.rs +++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs @@ -8,7 +8,6 @@ fn main() {} fn three(t: T) -> Two { (t, 5i8) - //~^ ERROR `T` doesn't implement `Debug` } trait Bar { @@ -23,8 +22,7 @@ impl Bar for u32 { fn four(t: T) -> Two { (t, ::FOO) - //~^ ERROR `U: Bar` is not satisfied - //~| ERROR `T` doesn't implement `Debug` + //~^ ERROR concrete type differs } fn is_sync() {} diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr index b11198c584c..b59f9c49b07 100644 --- a/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr +++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr @@ -1,38 +1,14 @@ -error[E0277]: `T` doesn't implement `Debug` +error: concrete type differs from previous defining opaque type use + --> $DIR/not_a_defining_use.rs:24:5 + | +LL | (t, ::FOO) + | ^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, ::Blub)` + | +note: previous use here --> $DIR/not_a_defining_use.rs:10:5 | LL | (t, 5i8) - | ^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(T, i8)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ + | ^^^^^^^^ -error[E0277]: the trait bound `U: Bar` is not satisfied - --> $DIR/not_a_defining_use.rs:25:5 - | -LL | (t, ::FOO) - | ^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `U` - | -help: consider restricting type parameter `U` - | -LL | type Two = impl Debug; - | +++++ +error: aborting due to 1 previous error -error[E0277]: `T` doesn't implement `Debug` - --> $DIR/not_a_defining_use.rs:25:5 - | -LL | (t, ::FOO) - | ^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(T, _)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs index c5b2e8a1c5e..e8e7dd0ea08 100644 --- a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs +++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs @@ -13,11 +13,11 @@ fn convert(_: PhantomData, r: &'a T) -> &'b T { } type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; -//~^ ERROR reference has a longer lifetime than the data it references // Even _defining_use with an explicit `'a: 'b` compiles fine, too. fn _defining_use<'a, 'b>(x: &'b &'a ()) -> Converter<'a, 'b> { x + //~^ ERROR reference has a longer lifetime than the data it references } fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr index 34b50fb1f05..7c07578d887 100644 --- a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr +++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr @@ -1,8 +1,8 @@ error[E0491]: in type `&'b &'a ()`, reference has a longer lifetime than the data it references - --> $DIR/underconstrained_lifetime.rs:15:26 + --> $DIR/underconstrained_lifetime.rs:19:5 | -LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | x + | ^ | note: the pointer is valid for the lifetime `'b` as defined here --> $DIR/underconstrained_lifetime.rs:15:20 diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr index c4ad8434ed1..03ff2e3444b 100644 --- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr @@ -1,10 +1,11 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/wf-in-associated-type.rs:38:23 + --> $DIR/wf-in-associated-type.rs:40:13 | LL | impl<'a, T> Trait<'a, T> for () { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... -LL | type Opaque = impl Sized + 'a; - | ^^^^^^^^^^^^^^^ ...so that the type `&'a T` will meet its required lifetime bounds +... +LL | req + | ^^^ ...so that the type `&'a T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound | @@ -12,12 +13,13 @@ LL | impl<'a, T: 'a> Trait<'a, T> for () { | ++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/wf-in-associated-type.rs:38:23 + --> $DIR/wf-in-associated-type.rs:40:13 | LL | impl<'a, T> Trait<'a, T> for () { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... -LL | type Opaque = impl Sized + 'a; - | ^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at +... +LL | req + | ^^^ ...so that the reference type `&'a T` does not outlive the data it points at | help: consider adding an explicit lifetime bound | diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs b/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs index c20be3125bc..e548609e89a 100644 --- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs +++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs @@ -36,10 +36,10 @@ trait Trait<'a, T> { impl<'a, T> Trait<'a, T> for () { type Opaque = impl Sized + 'a; - //[fail]~^ ERROR the parameter type `T` may not live long enough - //[fail]~| ERROR the parameter type `T` may not live long enough fn constrain_opaque(req: &'a T) -> Self::Opaque { req + //[fail]~^ ERROR the parameter type `T` may not live long enough + //[fail]~| ERROR the parameter type `T` may not live long enough } } } From 97dfe8b87115c44d480b6282aae7754e7c4ab4fe Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 8 Nov 2024 04:27:20 +0000 Subject: [PATCH 2/6] Manually register some bounds for a better span --- .../rustc_hir_analysis/src/check/check.rs | 45 +++++++++++++++---- .../src/infer/outlives/obligations.rs | 1 + compiler/rustc_middle/src/traits/mod.rs | 5 +++ .../src/error_reporting/traits/suggestions.rs | 16 +++++++ .../issue-70935-complex-spans.stderr | 5 +++ .../bounds-are-checked-2.stderr | 10 +++++ .../generic_duplicate_param_use2.stderr | 10 +++++ .../generic_duplicate_param_use4.stderr | 10 +++++ .../hidden_type_mismatch.stderr | 14 ++++++ .../implied_lifetime_wf_check4_static.stderr | 7 ++- .../type-alias-impl-trait/issue-52843.stderr | 10 +++++ .../issue-90400-2.stderr | 20 +++++++-- .../underconstrained_generic.stderr | 10 +++++ .../wf-in-associated-type.fail.stderr | 7 ++- 14 files changed, 156 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 12b842e70b7..3080d8b3510 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -8,7 +8,7 @@ use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::{Node, intravisit}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; -use rustc_infer::traits::Obligation; +use rustc_infer::traits::{Obligation, ObligationCauseCode}; use rustc_lint_defs::builtin::{ REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, }; @@ -267,7 +267,12 @@ fn check_opaque_meets_bounds<'tcx>( def_id: LocalDefId, origin: hir::OpaqueTyOrigin, ) -> Result<(), ErrorGuaranteed> { - let span = span_of_opaque(tcx, def_id, origin).unwrap_or_else(|| tcx.def_span(def_id)); + let (span, definition_def_id) = + if let Some((span, def_id)) = best_definition_site_of_opaque(tcx, def_id, origin) { + (span, Some(def_id)) + } else { + (tcx.def_span(def_id), None) + }; let defining_use_anchor = match origin { hir::OpaqueTyOrigin::FnReturn { parent, .. } @@ -305,8 +310,32 @@ fn check_opaque_meets_bounds<'tcx>( _ => re, }); - let misc_cause = traits::ObligationCause::misc(span, def_id); + // HACK: We eagerly instantiate some bounds to report better errors for them... + // This isn't necessary for correctness, since we register these bounds when + // equating the opaque below, but we should clean this up in the new solver. + for (predicate, pred_span) in + tcx.explicit_item_bounds(def_id).iter_instantiated_copied(tcx, args) + { + let predicate = predicate.fold_with(&mut BottomUpFolder { + tcx, + ty_op: |ty| if ty == opaque_ty { hidden_ty } else { ty }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }); + ocx.register_obligation(Obligation::new( + tcx, + ObligationCause::new( + span, + def_id, + ObligationCauseCode::OpaqueTypeBound(pred_span, definition_def_id), + ), + param_env, + predicate, + )); + } + + let misc_cause = ObligationCause::misc(span, def_id); // FIXME: We should just register the item bounds here, rather than equating. match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) { Ok(()) => {} @@ -364,17 +393,17 @@ fn check_opaque_meets_bounds<'tcx>( } } -fn span_of_opaque<'tcx>( +fn best_definition_site_of_opaque<'tcx>( tcx: TyCtxt<'tcx>, opaque_def_id: LocalDefId, origin: hir::OpaqueTyOrigin, -) -> Option { +) -> Option<(Span, LocalDefId)> { struct TaitConstraintLocator<'tcx> { opaque_def_id: LocalDefId, tcx: TyCtxt<'tcx>, } impl<'tcx> TaitConstraintLocator<'tcx> { - fn check(&self, item_def_id: LocalDefId) -> ControlFlow { + fn check(&self, item_def_id: LocalDefId) -> ControlFlow<(Span, LocalDefId)> { if !self.tcx.has_typeck_results(item_def_id) { return ControlFlow::Continue(()); } @@ -382,7 +411,7 @@ fn check(&self, item_def_id: LocalDefId) -> ControlFlow { if let Some(hidden_ty) = self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id) { - ControlFlow::Break(hidden_ty.span) + ControlFlow::Break((hidden_ty.span, item_def_id)) } else { ControlFlow::Continue(()) } @@ -390,7 +419,7 @@ fn check(&self, item_def_id: LocalDefId) -> ControlFlow { } impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { type NestedFilter = nested_filter::All; - type Result = ControlFlow; + type Result = ControlFlow<(Span, LocalDefId)>; fn nested_visit_map(&mut self) -> Self::Map { self.tcx.hir() } diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index e0e03a29220..b1d5d688295 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -104,6 +104,7 @@ pub fn register_region_obligation_with_cause( infer::RelateParamBound(cause.span, sup_type, match cause.code().peel_derives() { ObligationCauseCode::WhereClause(_, span) | ObligationCauseCode::WhereClauseInExpr(_, span, ..) + | ObligationCauseCode::OpaqueTypeBound(span, _) if !span.is_dummy() => { Some(*span) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 40e5ec45959..09731d565b6 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -193,6 +193,11 @@ pub enum ObligationCauseCode<'tcx> { /// The span corresponds to the clause. WhereClause(DefId, Span), + /// Represents a bound for an opaque we are checking the well-formedness of. + /// The def-id corresponds to a specific definition site that we found the + /// hidden type from, if any. + OpaqueTypeBound(Span, Option), + /// Like `WhereClause`, but also identifies the expression /// which requires the `where` clause to be proven, and also /// identifies the index of the predicate in the `predicates_of` diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 86fd4c230f6..a5e364d49f7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2953,6 +2953,22 @@ pub(super) fn note_obligation_cause_code( // We hold the `DefId` of the item introducing the obligation, but displaying it // doesn't add user usable information. It always point at an associated item. } + ObligationCauseCode::OpaqueTypeBound(span, definition_def_id) => { + err.span_note(span, "required by a bound in an opaque type"); + if let Some(definition_def_id) = definition_def_id + // If there are any stalled coroutine obligations, then this + // error may be due to that, and not because the body has more + // where-clauses. + && self.tcx.typeck(definition_def_id).coroutine_stalled_predicates.is_empty() + { + // FIXME(compiler-errors): We could probably point to something + // specific here if we tried hard enough... + err.span_note( + tcx.def_span(definition_def_id), + "this definition site has more where clauses than the opaque type", + ); + } + } ObligationCauseCode::Coercion { source, target } => { let source = tcx.short_ty_string(self.resolve_vars_if_possible(source), long_ty_file); diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index 777eefe897b..31d15c45921 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -35,6 +35,11 @@ note: required because it's used within this `async` block | LL | async move { | ^^^^^^^^^^ +note: required by a bound in an opaque type + --> $DIR/issue-70935-complex-spans.rs:15:37 + | +LL | fn foo(x: NotSync) -> impl Future + Send { + | ^^^^ error[E0277]: `*mut ()` cannot be shared between threads safely --> $DIR/issue-70935-complex-spans.rs:15:23 diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr index 0c937f92253..8f887a6ac68 100644 --- a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr @@ -4,6 +4,16 @@ error[E0277]: the trait bound `T: Clone` is not satisfied LL | t | ^ the trait `Clone` is not implemented for `T` | +note: required by a bound in an opaque type + --> $DIR/bounds-are-checked-2.rs:7:26 + | +LL | pub type X = impl Clone; + | ^^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/bounds-are-checked-2.rs:9:5 + | +LL | fn f(t: T) -> X { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider restricting type parameter `T` | LL | pub type X = impl Clone; diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr index d2d6380b65a..af6e6e1e66e 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr @@ -4,6 +4,16 @@ error[E0277]: `T` doesn't implement `Debug` LL | t | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | +note: required by a bound in an opaque type + --> $DIR/generic_duplicate_param_use2.rs:8:23 + | +LL | type Two = impl Debug; + | ^^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/generic_duplicate_param_use2.rs:10:1 + | +LL | fn two(t: T, _: U) -> Two { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider restricting type parameter `T` | LL | type Two = impl Debug; diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr index 2338dbd522b..a847bed93da 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr @@ -4,6 +4,16 @@ error[E0277]: `U` doesn't implement `Debug` LL | u | ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` | +note: required by a bound in an opaque type + --> $DIR/generic_duplicate_param_use4.rs:8:23 + | +LL | type Two = impl Debug; + | ^^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/generic_duplicate_param_use4.rs:10:1 + | +LL | fn three(_: T, u: U) -> Two { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider restricting type parameter `U` | LL | type Two = impl Debug; diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr index b05121a489e..be68bac5575 100644 --- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr +++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr @@ -21,6 +21,20 @@ LL | impl + Copy> Copy for Bar {} | ----------- ^^^^ ^^^^^^ | | | unsatisfied trait bound introduced here +note: required by a bound in an opaque type + --> $DIR/hidden_type_mismatch.rs:36:26 + | +LL | pub type Tait = impl Copy + From> + Into>; + | ^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/hidden_type_mismatch.rs:37:5 + | +LL | / pub fn define_tait() -> Tait +LL | | where +LL | | // this proves `Bar<()>: Copy`, but `define_tait` is +LL | | // now uncallable +LL | | (): Proj, + | |______________________________^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr index e5919be0532..f23b978d0b6 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -5,8 +5,13 @@ LL | s | ^ | | | the parameter type `A` must be valid for the static lifetime... - | ...so that the type `A` will meet its required lifetime bounds + | ...so that the type `A` will meet its required lifetime bounds... | +note: ...that is required by this bound + --> $DIR/implied_lifetime_wf_check4_static.rs:4:35 + | +LL | pub type Ty = impl Sized + 'static; + | ^^^^^^^ help: consider adding an explicit lifetime bound | LL | pub type Ty = impl Sized + 'static; diff --git a/tests/ui/type-alias-impl-trait/issue-52843.stderr b/tests/ui/type-alias-impl-trait/issue-52843.stderr index ea4c5297ad5..a6bdddbc98c 100644 --- a/tests/ui/type-alias-impl-trait/issue-52843.stderr +++ b/tests/ui/type-alias-impl-trait/issue-52843.stderr @@ -4,6 +4,16 @@ error[E0277]: the trait bound `T: Default` is not satisfied LL | t | ^ the trait `Default` is not implemented for `T` | +note: required by a bound in an opaque type + --> $DIR/issue-52843.rs:3:20 + | +LL | type Foo = impl Default; + | ^^^^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/issue-52843.rs:6:1 + | +LL | fn foo(t: T) -> Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider restricting type parameter `T` | LL | type Foo = impl Default; diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr index b4b78f8175f..4a6a62bdf96 100644 --- a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr @@ -4,11 +4,23 @@ error[E0277]: the trait bound `B: Bar` is not satisfied LL | MyBaz(bar) | ^^^^^^^^^^ the trait `Bar` is not implemented for `B` | -note: required by a bound in `MyBaz` - --> $DIR/issue-90400-2.rs:29:17 +note: required for `MyBaz` to implement `Baz` + --> $DIR/issue-90400-2.rs:30:14 | -LL | struct MyBaz(B); - | ^^^ required by this bound in `MyBaz` +LL | impl Baz for MyBaz { + | --- ^^^ ^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in an opaque type + --> $DIR/issue-90400-2.rs:22:26 + | +LL | type FooFn = impl Baz; + | ^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/issue-90400-2.rs:24:5 + | +LL | fn foo(&self, bar: B) -> Self::FooFn { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider restricting type parameter `B` | LL | type FooFn = impl Baz; diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr index e4de9245951..48cef847fbb 100644 --- a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr +++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr @@ -11,6 +11,16 @@ LL | impl ProofForConversion for () { | ----- ^^^^^^^^^^^^^^^^^^^^^ ^^ | | | unsatisfied trait bound introduced here +note: required by a bound in an opaque type + --> $DIR/underconstrained_generic.rs:19:26 + | +LL | type Converter = impl ProofForConversion; + | ^^^^^^^^^^^^^^^^^^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/underconstrained_generic.rs:21:1 + | +LL | fn _defining_use() -> Converter { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider restricting type parameter `T` | LL | type Converter = impl ProofForConversion; diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr index 03ff2e3444b..34648a420ac 100644 --- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr @@ -5,8 +5,13 @@ LL | impl<'a, T> Trait<'a, T> for () { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... ... LL | req - | ^^^ ...so that the type `&'a T` will meet its required lifetime bounds + | ^^^ ...so that the type `&'a T` will meet its required lifetime bounds... | +note: ...that is required by this bound + --> $DIR/wf-in-associated-type.rs:38:36 + | +LL | type Opaque = impl Sized + 'a; + | ^^ help: consider adding an explicit lifetime bound | LL | impl<'a, T: 'a> Trait<'a, T> for () { From b004cac72ef9e0b4ab2d47a6bbb1a543659b1e2b Mon Sep 17 00:00:00 2001 From: binarycat Date: Fri, 8 Nov 2024 09:51:46 -0600 Subject: [PATCH 3/6] update io::Error::into_inner to acknowlage io::Error::other --- library/std/src/io/error.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index adf103e9430..5d7adcace52 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -818,10 +818,12 @@ pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'stat /// Consumes the `Error`, returning its inner error (if any). /// - /// If this [`Error`] was constructed via [`new`] then this function will - /// return [`Some`], otherwise it will return [`None`]. + /// If this [`Error`] was constructed via [`new`] or [`other`], + /// then this function will return [`Some`], + /// otherwise it will return [`None`]. /// /// [`new`]: Error::new + /// [`other`]: Error::other /// /// # Examples /// From 0e481b44f5d851e9b7b3b3ed1b576d92437c7684 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 8 Nov 2024 16:57:53 +0000 Subject: [PATCH 4/6] use verbose for path separator suggestion --- .../rustc_resolve/src/late/diagnostics.rs | 2 +- tests/ui/resolve/issue-100365.stderr | 27 +++++++++++-- tests/ui/resolve/issue-22692.stderr | 33 ++++++++++++--- .../suggest-path-for-tuple-struct.stderr | 14 ++++++- ...uggest-path-instead-of-mod-dot-item.stderr | 40 ++++++++++++++++--- .../suggestions/assoc-const-as-field.stderr | 7 +++- 6 files changed, 104 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 42455983575..09f5a8e96d3 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1472,7 +1472,7 @@ fn smart_resolve_context_dependent_help( }; if lhs_span.eq_ctxt(rhs_span) { - err.span_suggestion( + err.span_suggestion_verbose( lhs_span.between(rhs_span), MESSAGE, "::", diff --git a/tests/ui/resolve/issue-100365.stderr b/tests/ui/resolve/issue-100365.stderr index 372d7726668..2d9bab4304d 100644 --- a/tests/ui/resolve/issue-100365.stderr +++ b/tests/ui/resolve/issue-100365.stderr @@ -2,19 +2,34 @@ error[E0423]: expected value, found trait `Into` --> $DIR/issue-100365.rs:2:16 | LL | let addr = Into::.into([127, 0, 0, 1]); - | ^^^^^^^^^^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let addr = Into::::into([127, 0, 0, 1]); + | ~~ error[E0423]: expected value, found trait `Into` --> $DIR/issue-100365.rs:6:13 | LL | let _ = Into.into(()); - | ^^^^- help: use the path separator to refer to an item: `::` + | ^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = Into::into(()); + | ~~ error[E0423]: expected value, found trait `Into` --> $DIR/issue-100365.rs:10:13 | LL | let _ = Into::<()>.into; - | ^^^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = Into::<()>::into; + | ~~ error[E0423]: expected value, found trait `std::iter::Iterator` --> $DIR/issue-100365.rs:17:9 @@ -42,12 +57,16 @@ error[E0423]: expected value, found trait `Into` --> $DIR/issue-100365.rs:25:9 | LL | Into::.into("") - | ^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^^^^^^^ ... LL | let _ = create!(); | --------- in this macro invocation | = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | Into::::into("") + | ~~ error: aborting due to 6 previous errors diff --git a/tests/ui/resolve/issue-22692.stderr b/tests/ui/resolve/issue-22692.stderr index 6962aa161e9..be0634ebffc 100644 --- a/tests/ui/resolve/issue-22692.stderr +++ b/tests/ui/resolve/issue-22692.stderr @@ -2,19 +2,34 @@ error[E0423]: expected value, found struct `String` --> $DIR/issue-22692.rs:2:13 | LL | let _ = String.new(); - | ^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = String::new(); + | ~~ error[E0423]: expected value, found struct `String` --> $DIR/issue-22692.rs:6:13 | LL | let _ = String.default; - | ^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = String::default; + | ~~ error[E0423]: expected value, found struct `Vec` --> $DIR/issue-22692.rs:10:13 | LL | let _ = Vec::<()>.with_capacity(1); - | ^^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = Vec::<()>::with_capacity(1); + | ~~ error[E0423]: expected value, found struct `std::cell::Cell` --> $DIR/issue-22692.rs:17:9 @@ -50,23 +65,31 @@ error[E0423]: expected value, found struct `Vec` --> $DIR/issue-22692.rs:26:9 | LL | Vec.new() - | ^^^- help: use the path separator to refer to an item: `::` + | ^^^ ... LL | let _ = create!(type method); | -------------------- in this macro invocation | = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | Vec::new() + | ~~ error[E0423]: expected value, found struct `Vec` --> $DIR/issue-22692.rs:31:9 | LL | Vec.new - | ^^^- help: use the path separator to refer to an item: `::` + | ^^^ ... LL | let _ = create!(type field); | ------------------- in this macro invocation | = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | Vec::new + | ~~ error[E0423]: expected value, found struct `std::cell::Cell` --> $DIR/issue-22692.rs:17:9 diff --git a/tests/ui/resolve/suggest-path-for-tuple-struct.stderr b/tests/ui/resolve/suggest-path-for-tuple-struct.stderr index 4764cf2db20..12c631f5a83 100644 --- a/tests/ui/resolve/suggest-path-for-tuple-struct.stderr +++ b/tests/ui/resolve/suggest-path-for-tuple-struct.stderr @@ -2,13 +2,23 @@ error[E0423]: expected value, found struct `SomeTupleStruct` --> $DIR/suggest-path-for-tuple-struct.rs:22:13 | LL | let _ = SomeTupleStruct.new(); - | ^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = SomeTupleStruct::new(); + | ~~ error[E0423]: expected value, found struct `SomeRegularStruct` --> $DIR/suggest-path-for-tuple-struct.rs:24:13 | LL | let _ = SomeRegularStruct.new(); - | ^^^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^^^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = SomeRegularStruct::new(); + | ~~ error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr index a4ce0deeb70..9c12fd2644c 100644 --- a/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr +++ b/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -2,19 +2,34 @@ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:17:5 | LL | a.I - | ^- help: use the path separator to refer to an item: `::` + | ^ + | +help: use the path separator to refer to an item + | +LL | a::I + | ~~ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:23:5 | LL | a.g() - | ^- help: use the path separator to refer to an item: `::` + | ^ + | +help: use the path separator to refer to an item + | +LL | a::g() + | ~~ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:29:5 | LL | a.b.J - | ^- help: use the path separator to refer to an item: `::` + | ^ + | +help: use the path separator to refer to an item + | +LL | a::b.J + | ~~ error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:35:5 @@ -38,7 +53,12 @@ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:42:5 | LL | a.b.f(); - | ^- help: use the path separator to refer to an item: `::` + | ^ + | +help: use the path separator to refer to an item + | +LL | a::b.f(); + | ~~ error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:46:12 @@ -117,23 +137,31 @@ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:80:9 | LL | a.f() - | ^- help: use the path separator to refer to an item: `::` + | ^ ... LL | let _ = create!(method); | --------------- in this macro invocation | = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | a::f() + | ~~ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:85:9 | LL | a.f - | ^- help: use the path separator to refer to an item: `::` + | ^ ... LL | let _ = create!(field); | -------------- in this macro invocation | = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | a::f + | ~~ error: aborting due to 13 previous errors diff --git a/tests/ui/suggestions/assoc-const-as-field.stderr b/tests/ui/suggestions/assoc-const-as-field.stderr index 0f58ce65049..6c095e52ac9 100644 --- a/tests/ui/suggestions/assoc-const-as-field.stderr +++ b/tests/ui/suggestions/assoc-const-as-field.stderr @@ -2,7 +2,12 @@ error[E0423]: expected value, found struct `Mod::Foo` --> $DIR/assoc-const-as-field.rs:11:9 | LL | foo(Mod::Foo.Bar); - | ^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL | foo(Mod::Foo::Bar); + | ~~ error: aborting due to 1 previous error From cea82ed1626f00930845ea48e3485eae8d44b422 Mon Sep 17 00:00:00 2001 From: dianne Date: Fri, 8 Nov 2024 13:47:36 -0800 Subject: [PATCH 5/6] Don't suggest `.into_iter()` on iterators --- .../rustc_hir_typeck/src/method/suggest.rs | 18 ++++++------ .../iterator-does-not-need-into-iter.rs | 18 ++++++++++++ .../iterator-does-not-need-into-iter.stderr | 28 +++++++++++++++++++ 3 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 tests/ui/iterators/iterator-does-not-need-into-iter.rs create mode 100644 tests/ui/iterators/iterator-does-not-need-into-iter.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index eaf40a193a6..cb20a1d7c7b 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -100,9 +100,9 @@ fn impl_into_iterator_should_be_iterator( ty: Ty<'tcx>, span: Span, unsatisfied_predicates: &Vec<( - ty::Predicate<'_>, - Option>, - Option>, + ty::Predicate<'tcx>, + Option>, + Option>, )>, ) -> bool { fn predicate_bounds_generic_param<'tcx>( @@ -131,15 +131,17 @@ fn predicate_bounds_generic_param<'tcx>( } } - fn is_iterator_predicate(predicate: ty::Predicate<'_>, tcx: TyCtxt<'_>) -> bool { + let is_iterator_predicate = |predicate: ty::Predicate<'tcx>| -> bool { if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = predicate.kind().as_ref().skip_binder() { - tcx.is_diagnostic_item(sym::Iterator, trait_pred.trait_ref.def_id) + self.tcx.is_diagnostic_item(sym::Iterator, trait_pred.trait_ref.def_id) + // ignore unsatisfied predicates generated from trying to auto-ref ty (#127511) + && trait_pred.trait_ref.self_ty() == ty } else { false } - } + }; // Does the `ty` implement `IntoIterator`? let Some(into_iterator_trait) = self.tcx.get_diagnostic_item(sym::IntoIterator) else { @@ -164,7 +166,7 @@ fn is_iterator_predicate(predicate: ty::Predicate<'_>, tcx: TyCtxt<'_>) -> bool generics, generic_param, self.tcx, - ) && is_iterator_predicate(unsatisfied.0, self.tcx) + ) && is_iterator_predicate(unsatisfied.0) { return true; } @@ -172,7 +174,7 @@ fn is_iterator_predicate(predicate: ty::Predicate<'_>, tcx: TyCtxt<'_>) -> bool } ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::Opaque, _) => { for unsatisfied in unsatisfied_predicates.iter() { - if is_iterator_predicate(unsatisfied.0, self.tcx) { + if is_iterator_predicate(unsatisfied.0) { return true; } } diff --git a/tests/ui/iterators/iterator-does-not-need-into-iter.rs b/tests/ui/iterators/iterator-does-not-need-into-iter.rs new file mode 100644 index 00000000000..29196449e30 --- /dev/null +++ b/tests/ui/iterators/iterator-does-not-need-into-iter.rs @@ -0,0 +1,18 @@ +//! regression test for #127511: don't suggest `.into_iter()` on iterators + +trait Missing {} +trait HasMethod { + fn foo(self); +} +impl HasMethod for T { + fn foo(self) {} +} + +fn get_iter() -> impl Iterator { + core::iter::once(()) +} + +fn main() { + get_iter().foo(); + //~^ ERROR the method `foo` exists for opaque type `impl Iterator`, but its trait bounds were not satisfied [E0599] +} diff --git a/tests/ui/iterators/iterator-does-not-need-into-iter.stderr b/tests/ui/iterators/iterator-does-not-need-into-iter.stderr new file mode 100644 index 00000000000..3d3861e959f --- /dev/null +++ b/tests/ui/iterators/iterator-does-not-need-into-iter.stderr @@ -0,0 +1,28 @@ +error[E0599]: the method `foo` exists for opaque type `impl Iterator`, but its trait bounds were not satisfied + --> $DIR/iterator-does-not-need-into-iter.rs:16:16 + | +LL | get_iter().foo(); + | ^^^ method cannot be called on `impl Iterator` due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `&impl Iterator: Iterator` + `&impl Iterator: Missing` + `&mut impl Iterator: Missing` + `impl Iterator: Missing` + --> $DIR/iterator-does-not-need-into-iter.rs:7:9 + | +LL | impl HasMethod for T { + | ^^^^^^^^ ^^^^^^^ --------- - + | | | + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `HasMethod` defines an item `foo`, perhaps you need to implement it + --> $DIR/iterator-does-not-need-into-iter.rs:4:1 + | +LL | trait HasMethod { + | ^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From 13ab08d7dc353d1d30ad055eea4c7ec4e5310237 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 9 Nov 2024 03:54:08 +0000 Subject: [PATCH 6/6] Do not reveal opaques in the param-env, we got lazy norm instead --- compiler/rustc_middle/src/ty/mod.rs | 11 ++++++----- compiler/rustc_middle/src/ty/util.rs | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6d9ba3d60e3..1a3128ed936 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1076,11 +1076,6 @@ pub fn new(caller_bounds: Clauses<'tcx>, reveal: Reveal) -> Self { ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal }) } } - pub fn with_user_facing(mut self) -> Self { - self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() }); - self - } - /// Returns a new parameter environment with the same clauses, but /// which "reveals" the true results of projections in all cases /// (even for associated types that are specializable). This is @@ -1095,6 +1090,12 @@ pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self { return self; } + // No need to reveal opaques with the new solver enabled, + // since we have lazy norm. + if tcx.next_trait_solver_globally() { + return ParamEnv::new(self.caller_bounds(), Reveal::All); + } + ParamEnv::new(tcx.reveal_opaque_types_in_bounds(self.caller_bounds()), Reveal::All) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index fc5a3b762e5..3c6e34160f4 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1751,6 +1751,7 @@ pub fn reveal_opaque_types_in_bounds<'tcx>( tcx: TyCtxt<'tcx>, val: ty::Clauses<'tcx>, ) -> ty::Clauses<'tcx> { + assert!(!tcx.next_trait_solver_globally()); let mut visitor = OpaqueTypeExpander { seen_opaque_tys: FxHashSet::default(), expanded_cache: FxHashMap::default(),