From bdb20f43f6d490b329f0ed6ee050be6256709293 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 3 Jul 2023 17:04:32 +0000 Subject: [PATCH 1/2] Add a test for a tait unsoundess --- .../stronger_where_bounds.rs | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/ui/type-alias-impl-trait/stronger_where_bounds.rs diff --git a/tests/ui/type-alias-impl-trait/stronger_where_bounds.rs b/tests/ui/type-alias-impl-trait/stronger_where_bounds.rs new file mode 100644 index 0000000000000..23b20d4fdc09b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/stronger_where_bounds.rs @@ -0,0 +1,53 @@ +// known-bug: #113278 +// run-fail + +#![feature(trivial_bounds, type_alias_impl_trait)] +#![allow(trivial_bounds)] + +mod sus { + use super::*; + pub type Sep = impl Sized + std::fmt::Display; + pub fn mk_sep() -> Sep { + String::from("hello") + } + + pub trait Proj { + type Assoc; + } + impl Proj for () { + type Assoc = sus::Sep; + } + + pub struct Bar { + pub inner: ::Assoc, + pub _marker: T, + } + impl Clone for Bar { + fn clone(&self) -> Self { + todo!() + } + } + impl + Copy> Copy for Bar {} + pub type Tait = impl Copy + From> + Into>; + pub fn define_tait() -> Tait + where + // This bound does not exist on `type Tait`, but will + // constrain `Sep` to `i32`, and then forget about it. + // On the other hand `mk_sep` constrains it to `String`. + // Since `Tait: Copy`, we can now copy `String`s. + (): Proj, + { + Bar { inner: 1i32, _marker: () } + } +} + +fn copy_tait(x: sus::Tait) -> (sus::Tait, sus::Tait) { + (x, x) +} + +fn main() { + let bar = sus::Bar { inner: sus::mk_sep(), _marker: () }; + let (y, z) = copy_tait(bar.into()); // copy a string + drop(y.into()); // drop one instance + println!("{}", z.into().inner); // print the other +} From 1dfe0e02c143d0678702af1bef0e98927df7f6ef Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 3 Jul 2023 17:04:57 +0000 Subject: [PATCH 2/2] Remove one use of `Bubble` --- .../src/region_infer/opaque_types.rs | 9 ++-- .../src/opaque_hidden_inferred_bound.rs | 54 ++++++++++++++----- compiler/rustc_ty_utils/src/opaque_types.rs | 34 +++++++++--- .../impl-trait/nested-return-type2-tait2.rs | 5 +- .../nested-return-type2-tait2.stderr | 21 +++----- .../impl-trait/nested-return-type2-tait3.rs | 9 ++-- .../nested-return-type2-tait3.stderr | 22 ++++---- .../impl-trait/nested-return-type3-tait2.rs | 7 +-- .../nested-return-type3-tait2.stderr | 8 ++- .../impl-trait/nested-return-type3-tait3.rs | 4 +- .../nested-return-type3-tait3.stderr | 7 ++- 11 files changed, 102 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 4a872eb251c25..fac7db7ee5ce0 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -293,7 +293,8 @@ fn check_opaque_type_well_formed<'tcx>( return Ok(definition_ty); }; let param_env = tcx.param_env(def_id); - // HACK This bubble is required for this tests to pass: + // HACK We use the function's anchor, instead of the TAIT's `DefId`, because the + // `TAIT` may not be in the defining scope of the other (nested) TAITs. // nested-return-type2-tait2.rs // nested-return-type2-tait3.rs // FIXME(-Ztrait-solver=next): We probably should use `DefiningAnchor::Error` @@ -302,11 +303,7 @@ fn check_opaque_type_well_formed<'tcx>( let infcx = tcx .infer_ctxt() .with_next_trait_solver(next_trait_solver) - .with_opaque_type_inference(if next_trait_solver { - DefiningAnchor::Bind(def_id) - } else { - DefiningAnchor::Bubble - }) + .with_opaque_type_inference(DefiningAnchor::Bind(def_id)) .build(); let ocx = ObligationCtxt::new(&infcx); let identity_substs = InternalSubsts::identity_for_item(tcx, def_id); diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 63a56806a4578..a468bbf13cda6 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -1,6 +1,6 @@ use rustc_hir as hir; use rustc_infer::infer::TyCtxtInferExt; -use rustc_macros::{LintDiagnostic, Subdiagnostic}; +use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{ self, fold::BottomUpFolder, print::TraitPredPrintModifiersAndPath, Ty, TypeFoldable, }; @@ -140,25 +140,51 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { }), _ => None, }; - cx.emit_spanned_lint( - OPAQUE_HIDDEN_INFERRED_BOUND, - pred_span, - OpaqueHiddenInferredBoundLint { - ty: cx.tcx.mk_opaque( - def_id, - ty::InternalSubsts::identity_for_item(cx.tcx, def_id), - ), - proj_ty: proj_term, - assoc_pred_span, - add_bound, - }, - ); + let ty = cx + .tcx + .mk_opaque(def_id, ty::InternalSubsts::identity_for_item(cx.tcx, def_id)); + match opaque.origin { + hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => { + cx.emit_spanned_lint( + OPAQUE_HIDDEN_INFERRED_BOUND, + pred_span, + OpaqueHiddenInferredBoundLint { + ty, + proj_ty: proj_term, + assoc_pred_span, + add_bound, + }, + ); + } + hir::OpaqueTyOrigin::TyAlias { .. } => { + cx.tcx.sess.emit_err(OpaqueHiddenInferredBoundErr { + pred_span, + ty, + proj_ty: proj_term, + assoc_pred_span, + add_bound, + }); + } + } } } } } } +#[derive(Diagnostic)] +#[diag(lint_opaque_hidden_inferred_bound)] +struct OpaqueHiddenInferredBoundErr<'tcx> { + #[primary_span] + pred_span: Span, + ty: Ty<'tcx>, + proj_ty: Ty<'tcx>, + #[label(lint_specifically)] + assoc_pred_span: Span, + #[subdiagnostic] + add_bound: Option>, +} + #[derive(LintDiagnostic)] #[diag(lint_opaque_hidden_inferred_bound)] struct OpaqueHiddenInferredBoundLint<'tcx> { diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 29de8bf0e53f5..bca1c6627d3e3 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -50,15 +50,24 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { } fn parent(&self) -> Option { - match self.tcx.def_kind(self.item) { + let mut item = self.item; + let mut kind; + loop { + kind = self.tcx.def_kind(item); + match kind { + DefKind::OpaqueTy => item = self.tcx.local_parent(item), + DefKind::TyAlias => return None, + _ => break, + } + } + match kind { DefKind::Fn => None, DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => { - Some(self.tcx.local_parent(self.item)) + Some(self.tcx.local_parent(item)) + } + other => { + span_bug!(self.tcx.def_span(item), "unhandled item with opaque types: {other:?}") } - other => span_bug!( - self.tcx.def_span(self.item), - "unhandled item with opaque types: {other:?}" - ), } } } @@ -216,6 +225,18 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ } tcx.arena.alloc_from_iter(collector.opaques) } + DefKind::OpaqueTy => { + let mut collector = OpaqueTypeCollector::new(tcx, item); + let span = match tcx.hir().get_by_def_id(item).ty() { + Some(ty) => ty.span, + _ => tcx.def_span(item), + }; + collector.visit_spanned( + span, + tcx.mk_opaque(item.to_def_id(), ty::InternalSubsts::identity_for_item(tcx, item)), + ); + tcx.arena.alloc_from_iter(collector.opaques) + } DefKind::Mod | DefKind::Struct | DefKind::Union @@ -236,7 +257,6 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ | DefKind::ForeignMod | DefKind::AnonConst | DefKind::InlineConst - | DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam diff --git a/tests/ui/impl-trait/nested-return-type2-tait2.rs b/tests/ui/impl-trait/nested-return-type2-tait2.rs index af8e066305471..d9fcc0ab5163d 100644 --- a/tests/ui/impl-trait/nested-return-type2-tait2.rs +++ b/tests/ui/impl-trait/nested-return-type2-tait2.rs @@ -17,6 +17,7 @@ impl R> Trait for F { type Sendable = impl Send; type Traitable = impl Trait; +//~^ ERROR opaque type `Traitable` does not satisfy its associated type bounds // The `impl Send` here is then later compared against the inference var // created, causing the inference var to be set to `impl Send` instead of @@ -25,8 +26,6 @@ type Traitable = impl Trait; // type does not implement `Duh`, even if its hidden type does. So we error out. fn foo() -> Traitable { || 42 - //~^ ERROR `Sendable: Duh` is not satisfied } -fn main() { -} +fn main() {} diff --git a/tests/ui/impl-trait/nested-return-type2-tait2.stderr b/tests/ui/impl-trait/nested-return-type2-tait2.stderr index b85bb5efd100a..b2c0dab9ea0c9 100644 --- a/tests/ui/impl-trait/nested-return-type2-tait2.stderr +++ b/tests/ui/impl-trait/nested-return-type2-tait2.stderr @@ -1,18 +1,11 @@ -error[E0277]: the trait bound `Sendable: Duh` is not satisfied - --> $DIR/nested-return-type2-tait2.rs:27:5 +error: opaque type `Traitable` does not satisfy its associated type bounds + --> $DIR/nested-return-type2-tait2.rs:19:29 | -LL | || 42 - | ^^^^^ the trait `Duh` is not implemented for `Sendable` - | - = help: the trait `Duh` is implemented for `i32` -note: required for `[closure@$DIR/nested-return-type2-tait2.rs:27:5: 27:7]` to implement `Trait` - --> $DIR/nested-return-type2-tait2.rs:14:31 - | -LL | impl R> Trait for F { - | --- ^^^^^ ^ - | | - | unsatisfied trait bound introduced here +LL | type Assoc: Duh; + | --- this associated type bound is unsatisfied for `Sendable` +... +LL | type Traitable = impl Trait; + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/nested-return-type2-tait3.rs b/tests/ui/impl-trait/nested-return-type2-tait3.rs index 74fd8a9dda0bf..e5803cbe6d19a 100644 --- a/tests/ui/impl-trait/nested-return-type2-tait3.rs +++ b/tests/ui/impl-trait/nested-return-type2-tait3.rs @@ -15,17 +15,16 @@ impl R> Trait for F { type Assoc = R; } -type Traitable = impl Trait; - // The `impl Send` here is then later compared against the inference var // created, causing the inference var to be set to `impl Send` instead of // the hidden type. We already have obligations registered on the inference // var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque // type does not implement `Duh`, even if its hidden type does. So we error out. +type Traitable = impl Trait; +//~^ ERROR opaque type `Traitable` does not satisfy its associated type bounds + fn foo() -> Traitable { || 42 - //~^ ERROR `impl Send: Duh` is not satisfied } -fn main() { -} +fn main() {} diff --git a/tests/ui/impl-trait/nested-return-type2-tait3.stderr b/tests/ui/impl-trait/nested-return-type2-tait3.stderr index 19fd3c134acda..07ccdf40c627c 100644 --- a/tests/ui/impl-trait/nested-return-type2-tait3.stderr +++ b/tests/ui/impl-trait/nested-return-type2-tait3.stderr @@ -1,18 +1,16 @@ -error[E0277]: the trait bound `impl Send: Duh` is not satisfied - --> $DIR/nested-return-type2-tait3.rs:26:5 +error: opaque type `Traitable` does not satisfy its associated type bounds + --> $DIR/nested-return-type2-tait3.rs:23:29 | -LL | || 42 - | ^^^^^ the trait `Duh` is not implemented for `impl Send` +LL | type Assoc: Duh; + | --- this associated type bound is unsatisfied for `impl Send` +... +LL | type Traitable = impl Trait; + | ^^^^^^^^^^^^^^^^^ | - = help: the trait `Duh` is implemented for `i32` -note: required for `[closure@$DIR/nested-return-type2-tait3.rs:26:5: 26:7]` to implement `Trait` - --> $DIR/nested-return-type2-tait3.rs:14:31 +help: add this bound | -LL | impl R> Trait for F { - | --- ^^^^^ ^ - | | - | unsatisfied trait bound introduced here +LL | type Traitable = impl Trait; + | +++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/nested-return-type3-tait2.rs b/tests/ui/impl-trait/nested-return-type3-tait2.rs index 5b6f78a989687..a170aa826ee79 100644 --- a/tests/ui/impl-trait/nested-return-type3-tait2.rs +++ b/tests/ui/impl-trait/nested-return-type3-tait2.rs @@ -1,5 +1,3 @@ -// check-pass - #![feature(type_alias_impl_trait)] trait Duh {} @@ -16,11 +14,10 @@ impl Trait for F { type Sendable = impl Send; type Traitable = impl Trait; -//~^ WARN opaque type `Traitable` does not satisfy its associated type bounds +//~^ ERROR opaque type `Traitable` does not satisfy its associated type bounds fn foo() -> Traitable { 42 } -fn main() { -} +fn main() {} diff --git a/tests/ui/impl-trait/nested-return-type3-tait2.stderr b/tests/ui/impl-trait/nested-return-type3-tait2.stderr index a2eddd116653c..678f38ff096cf 100644 --- a/tests/ui/impl-trait/nested-return-type3-tait2.stderr +++ b/tests/ui/impl-trait/nested-return-type3-tait2.stderr @@ -1,13 +1,11 @@ -warning: opaque type `Traitable` does not satisfy its associated type bounds - --> $DIR/nested-return-type3-tait2.rs:18:29 +error: opaque type `Traitable` does not satisfy its associated type bounds + --> $DIR/nested-return-type3-tait2.rs:16:29 | LL | type Assoc: Duh; | --- this associated type bound is unsatisfied for `Sendable` ... LL | type Traitable = impl Trait; | ^^^^^^^^^^^^^^^^ - | - = note: `#[warn(opaque_hidden_inferred_bound)]` on by default -warning: 1 warning emitted +error: aborting due to previous error diff --git a/tests/ui/impl-trait/nested-return-type3-tait3.rs b/tests/ui/impl-trait/nested-return-type3-tait3.rs index 394d8f581102f..8ba978061a5f3 100644 --- a/tests/ui/impl-trait/nested-return-type3-tait3.rs +++ b/tests/ui/impl-trait/nested-return-type3-tait3.rs @@ -1,5 +1,3 @@ -// check-pass - #![feature(type_alias_impl_trait)] trait Duh {} @@ -15,7 +13,7 @@ impl Trait for F { } type Traitable = impl Trait; -//~^ WARN opaque type `Traitable` does not satisfy its associated type bounds +//~^ ERROR opaque type `Traitable` does not satisfy its associated type bounds fn foo() -> Traitable { 42 diff --git a/tests/ui/impl-trait/nested-return-type3-tait3.stderr b/tests/ui/impl-trait/nested-return-type3-tait3.stderr index d98ad89222fa7..b4ebbd52e15db 100644 --- a/tests/ui/impl-trait/nested-return-type3-tait3.stderr +++ b/tests/ui/impl-trait/nested-return-type3-tait3.stderr @@ -1,5 +1,5 @@ -warning: opaque type `Traitable` does not satisfy its associated type bounds - --> $DIR/nested-return-type3-tait3.rs:17:29 +error: opaque type `Traitable` does not satisfy its associated type bounds + --> $DIR/nested-return-type3-tait3.rs:15:29 | LL | type Assoc: Duh; | --- this associated type bound is unsatisfied for `impl Send` @@ -7,11 +7,10 @@ LL | type Assoc: Duh; LL | type Traitable = impl Trait; | ^^^^^^^^^^^^^^^^^ | - = note: `#[warn(opaque_hidden_inferred_bound)]` on by default help: add this bound | LL | type Traitable = impl Trait; | +++++ -warning: 1 warning emitted +error: aborting due to previous error