Skip to content

Remove another DefiningAnchor::Bubble usage #113294

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -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);
Expand Down
54 changes: 40 additions & 14 deletions compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
Original file line number Diff line number Diff line change
@@ -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,
};
Expand Down Expand Up @@ -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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hard errors in rustc_lint is somewhat :/

I also don't think we should error (or even lint, for that matter) here, tho

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a technical perspective, yeah, we shouldn't be doing hard errors inside of the lint infrastructure I think.

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<AddBound<'tcx>>,
}

#[derive(LintDiagnostic)]
#[diag(lint_opaque_hidden_inferred_bound)]
struct OpaqueHiddenInferredBoundLint<'tcx> {
Expand Down
34 changes: 27 additions & 7 deletions compiler/rustc_ty_utils/src/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,24 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
}

fn parent(&self) -> Option<LocalDefId> {
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:?}"
),
}
}
}
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
5 changes: 2 additions & 3 deletions tests/ui/impl-trait/nested-return-type2-tait2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ impl<R: Duh, F: FnMut() -> R> Trait for F {

type Sendable = impl Send;
type Traitable = impl Trait<Assoc = Sendable>;
//~^ 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
Expand All @@ -25,8 +26,6 @@ type Traitable = impl Trait<Assoc = Sendable>;
// 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() {}
21 changes: 7 additions & 14 deletions tests/ui/impl-trait/nested-return-type2-tait2.stderr
Original file line number Diff line number Diff line change
@@ -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: Duh, F: FnMut() -> 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<Assoc = Sendable>;
| ^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
9 changes: 4 additions & 5 deletions tests/ui/impl-trait/nested-return-type2-tait3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@ impl<R: Duh, F: FnMut() -> R> Trait for F {
type Assoc = R;
}

type Traitable = impl Trait<Assoc = impl Send>;

// 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<Assoc = impl Send>;
//~^ 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() {}
22 changes: 10 additions & 12 deletions tests/ui/impl-trait/nested-return-type2-tait3.stderr
Original file line number Diff line number Diff line change
@@ -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<Assoc = impl Send>;
| ^^^^^^^^^^^^^^^^^
|
= 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: Duh, F: FnMut() -> R> Trait for F {
| --- ^^^^^ ^
| |
| unsatisfied trait bound introduced here
LL | type Traitable = impl Trait<Assoc = impl Send + Duh>;
| +++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
7 changes: 2 additions & 5 deletions tests/ui/impl-trait/nested-return-type3-tait2.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// check-pass

#![feature(type_alias_impl_trait)]

trait Duh {}
Expand All @@ -16,11 +14,10 @@ impl<F: Duh> Trait for F {

type Sendable = impl Send;
type Traitable = impl Trait<Assoc = Sendable>;
//~^ 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() {}
8 changes: 3 additions & 5 deletions tests/ui/impl-trait/nested-return-type3-tait2.stderr
Original file line number Diff line number Diff line change
@@ -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<Assoc = Sendable>;
| ^^^^^^^^^^^^^^^^
|
= note: `#[warn(opaque_hidden_inferred_bound)]` on by default

warning: 1 warning emitted
error: aborting due to previous error

4 changes: 1 addition & 3 deletions tests/ui/impl-trait/nested-return-type3-tait3.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// check-pass

#![feature(type_alias_impl_trait)]

trait Duh {}
Expand All @@ -15,7 +13,7 @@ impl<F: Duh> Trait for F {
}

type Traitable = impl Trait<Assoc = impl Send>;
//~^ 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
Expand Down
7 changes: 3 additions & 4 deletions tests/ui/impl-trait/nested-return-type3-tait3.stderr
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
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`
...
LL | type Traitable = impl Trait<Assoc = impl Send>;
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(opaque_hidden_inferred_bound)]` on by default
help: add this bound
|
LL | type Traitable = impl Trait<Assoc = impl Send + Duh>;
| +++++

warning: 1 warning emitted
error: aborting due to previous error

53 changes: 53 additions & 0 deletions tests/ui/type-alias-impl-trait/stronger_where_bounds.rs
Original file line number Diff line number Diff line change
@@ -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<T: Proj> {
pub inner: <T as Proj>::Assoc,
pub _marker: T,
}
impl<T: Proj> Clone for Bar<T> {
fn clone(&self) -> Self {
todo!()
}
}
impl<T: Proj<Assoc = i32> + Copy> Copy for Bar<T> {}
pub type Tait = impl Copy + From<Bar<()>> + Into<Bar<()>>;
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<Assoc = i32>,
{
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
}